打印
[FPGA]

面试时提到一个关于大计数器的问题

[复制链接]
3361|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hqbenson|  楼主 | 2016-8-16 16:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
面试官问道针对一个大数分频器(比如1千分频1万分频)的计数器,有什么好方法可以节省一点资源?
当时想了很久,就说按实际分频用到多少位就分配几位,避免一些无用寄存器的使用。然后他摇了摇头,我向他请教,他说正确的是要把大计数器分拆成几个小计数器,溢出计数。他说这样子反转的位数就少,才可靠。
我当时纳闷了,你不是说要节省资源吗?怎么问题跑到这上面去了?
私底下思考了一下,请问大神:分拆成小计数器对节省资源来说有作用吗?按我理解用到几位就需要有几个寄存器,这是省不了的。
盼回复,谢谢!

相关帖子

沙发
nstel| | 2016-8-16 16:37 | 只看该作者
面试官说的对,但是,没有说明白,或许是有意不说明白的?
因为,你要真的是实际搞过分频器而不只是个书面高手,那你就应该明白:分频器就是同步计数器,而多位同步计数器是很占资源的。分拆成几个小的同步计数器,再串联成大的计数器,就能节省大量的资源!这时,几个小的计数器之间不是同步计数而是异步计数。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
hqbenson + 1 很给力!
板凳
hqbenson|  楼主 | 2016-8-16 17:14 | 只看该作者
nstel 发表于 2016-8-16 16:37
面试官说的对,但是,没有说明白,或许是有意不说明白的?
因为,你要真的是实际搞过分频器而不只是个书面 ...

谢谢大神您的快速回复!谢谢!经您的解释好像有点懂了。
可以具体举个例子吗?比如用一个8位计数器拆成两个4位来说,具体可以节省哪些资源呢?(寄存器应该是少不了吧,我理解是不是节省了一些组合逻辑资源?)
谢谢您!

使用特权

评论回复
地板
nstel| | 2016-8-16 17:23 | 只看该作者
hqbenson 发表于 2016-8-16 17:14
谢谢大神您的快速回复!谢谢!经您的解释好像有点懂了。
可以具体举个例子吗?比如用一个8位计数器拆成两 ...

节省大量的组合逻辑和布线资源。多位同步计数器的组合逻辑,会是几何级数增加的。布线,也是很占资源的。有时,布线比寄存器占的资源还多!而且,布线多了还要隔离,隔离占用的资源也不小。单层布线走不通,还要用多层布线,这个资源就是几何级数增加了!

使用特权

评论回复
5
hqbenson|  楼主 | 2016-8-16 17:38 | 只看该作者
nstel 发表于 2016-8-16 17:23
节省大量的组合逻辑和布线资源。多位同步计数器的组合逻辑,会是几何级数增加的。布线,也是很占资源的。 ...

嗯嗯明白了!感谢大神您的耐心解答!

使用特权

评论回复
6
kdurant| | 2016-9-2 15:38 | 只看该作者
本帖最后由 kdurant 于 2016-9-2 15:39 编辑

纯属胡扯,以altera为例:
assign                  led = cnt[127];
reg     [127:0]           cnt;

always @(posedge clk or negedge rst)
begin
    if(~rst)
        cnt <= 0;
    else
        cnt <= cnt + 1'b1;;
end

一个128bit的计数器,消耗资源
Total logic elements        128 / 10,320 ( 1 % )
Total combinational functions        128 / 10,320 ( 1 % )
Dedicated logic registers        128 / 10,320 ( 1 % )
Total registers        128

assign                  led = cnt2[63];
reg     [63:0]           cnt1;
reg     [63:0]           cnt2;

always [url=home.php?mod=space&uid=72445]@[/url] (posedge clk or negedge rst)
begin
    if(~rst)
        cnt1 <= 0;
    else
        cnt1 <= cnt1 + 1'b1;;
end

always @ (posedge clk or negedge rst)
begin
    if(~rst)
        cnt2 <= 0;
    else if(cnt1 == {64{1'b1}})
        cnt2 <= cnt2 + 1;
end

拆分成2个64bit的计数器,消耗资源
Total logic elements        149 / 10,320 ( 1 % )
Total combinational functions        149 / 10,320 ( 1 % )
Dedicated logic registers        128 / 10,320 ( 1 % )
Total registers        128


可见拆分为2个更小的计数器,消耗的资源反而更多了,比较cnt2需要多一个比较逻辑才能加

这么做只有一个理由,那就是减少了计数器的组合逻辑路径(减少了加法器的进位链级数),提高了Fmax
可以说是面积换速度吧

使用特权

评论回复
7
pkuzhx| | 2016-9-9 11:39 | 只看该作者
关注

使用特权

评论回复
8
drentsi| | 2016-9-9 13:19 | 只看该作者
远离这种低水平学究型的单位,资源不是这么省的,等我有空写个超级省资源的计数器,128bit可能只需要十几个LUT

使用特权

评论回复
9
drentsi| | 2016-9-9 14:28 | 只看该作者
试了一下,160bit的计数器,spartan-6使用资源
Slice Logic Utilization:
Number of Slice Registers:              13  out of   4800     0%  
Number of Slice LUTs:                   39  out of   2400     1%  
    Number used as Logic:                29  out of   2400     1%  
    Number used as Memory:               10  out of   1200     0%  
       Number used as RAM:               10

Slice Logic Distribution:
Number of LUT Flip Flop pairs used:     40
   Number with an unused Flip Flop:      27  out of     40    67%  
   Number with an unused LUT:             1  out of     40     2%  
   Number of fully used LUT-FF pairs:    12  out of     40    30%  
   Number of unique control sets:         3

使用特权

评论回复
10
drentsi| | 2016-9-9 14:29 | 只看该作者
代码贴上,没测试,不保证能用,能理解就理解,不教会,不解释
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date:    13:24:23 09/09/2016
-- Design Name:
-- Module Name:    WideCntr - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity WideCntr is
generic(A_SIZE:integer:=5); -- VEC=A_SIZE*2**A_SIZE,3=>24,4=>64,5=>160,6=>384
port(
        clk        :        in std_logic;
        rst        :        in std_logic;
        p                :        in std_logic;
        addr        :        in std_logic_vector(0 to A_SIZE-1);
        cntr        :  out std_logic_vector(0 to A_SIZE-1)
);
end WideCntr;

architecture Behavioral of WideCntr is
        type RAM_TYPE is array(0 to 2**A_SIZE-1) of std_logic_vector(0 to A_SIZE-1);
        signal ram:RAM_TYPE:=(others=>(others=>'0'));
       
        signal p_cntr:std_logic_vector(0 to A_SIZE);
        signal p_c_clr:std_logic;
        signal cy:std_logic;       
        signal ram_addr:std_logic_vector(0 to A_SIZE-1);
        signal ram_data:std_logic_vector(0 to A_SIZE);
       
begin

process(clk)
begin
if clk'event and clk='1' then
if rst='1' then
        p_cntr<=(others=>'0');
else
        if p='1' then
                if p_c_clr='1' then
                        p_cntr(0)<='0';
                        p_cntr(1 to A_SIZE)<=p_cntr(1 to A_SIZE)+1;
                else
                        p_cntr<=p_cntr +1;
                end if;
        end if;
end if;
end if;
end process;

process(clk)
begin
if clk'event and clk='1' then
        ram(conv_integer(ram_addr)) <=ram_data(1 to A_SIZE);
end if;
end process;

        ram_data<=(others=>'0') when rst='1' else ('0'&ram(conv_integer(ram_addr)))+cy;
       
process(clk)
begin
if clk'event and clk='1' then
if rst='1' then
        ram_addr<=ram_addr+1;
        p_c_clr<='0';
        cy<='0';
else
        p_c_clr<='0';
        cy<='0';
        ram_addr<=conv_std_logic_vector(1,A_SIZE);
        if p_cntr(0)='1' then
                cy<='1';
                p_c_clr<='1';
        elsif ram_data(0)='1' then
                cy<='1';
                ram_addr<=ram_addr+1;
        end if;
end if;
end if;
end process;


        cntr<=p_cntr(1 to A_SIZE) when addr=0 else ram(conv_integer(addr));

end Behavioral;

使用特权

评论回复
11
hqbenson|  楼主 | 2016-9-13 10:26 | 只看该作者
本帖最后由 hqbenson 于 2016-9-13 11:46 编辑
drentsi 发表于 2016-9-9 14:29
代码贴上,没测试,不保证能用,能理解就理解,不教会,不解释
----------------------------------------- ...

      谢谢!先感谢大神回复!我再仔细研究一下.VHDL忘得差不多了。。
      个人理解,您写应该就是把计数值存进RAM中是吗?只用几个RAM就能够实现多位计数,可以省下上百个LUT和REG。。
      确实很省资源!学习了!

使用特权

评论回复
12
hqbenson|  楼主 | 2016-9-13 10:32 | 只看该作者
kdurant 发表于 2016-9-2 15:38
纯属胡扯,以altera为例:

一个128bit的计数器,消耗资源

谢谢!先感谢大神回复!我再仔细研究一下.
        其实后来我也实际写过这两种情况下的代码,我也发现实际上分拆计数器的话消耗资源确实比一个大计数器要多出很多LUT和REG!
       我也很同意您的观点。实际上只是速度变快了,反转变少了。感觉其实跟流水线是一个原理。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

9

帖子

0

粉丝