Filter FSM,产品总数计数

Filter FSM,产品总数计数,filter,signal-processing,vhdl,Filter,Signal Processing,Vhdl,我的VHDL项目有一个问题。代码如下: 注册模块: library ieee; use ieee.std_logic_1164.all; entity reg is port( clk, rst : in std_logic; d : in std_logic_vector(23 downto 0); q : out std_logic_vector(23 downto 0) ); end reg; architecture

我的VHDL项目有一个问题。代码如下:

注册模块:

library ieee;
use ieee.std_logic_1164.all;

entity reg is 
port(
    clk, rst : in std_logic;
    d           : in std_logic_vector(23 downto 0);
    q           : out std_logic_vector(23 downto 0)
);
end reg;

architecture arch of reg is

signal q_reg, q_next : std_logic_vector(23 downto 0);

begin
    process(clk, rst)
        begin
        if (rst ='1') then
                q_reg <= (others => '0');
        elsif rising_edge(clk) then
            q_reg <= q_next;
        end if;
    end process;

    q_next <= d;
    q <= q_reg;

end arch;
ieee库;
使用ieee.std_logic_1164.all;
实体注册号为
港口(
时钟,rst:标准逻辑中;
d:标准逻辑向量(23向下至0);
q:输出标准逻辑向量(23到0)
);
结束注册;
reg is的建筑拱门
信号q_reg,q_next:std_逻辑向量(23向下至0);
开始
过程(时钟、rst)
开始
如果(rst='1'),则
q_reg“0”);
elsif上升沿(clk)则
q_reg clk,
rst=>rst,
d=>reg_in,
q=>reg_out
);

这是我的建议。
改进:

  • 减少异步重置
  • 从FSM提取的数据流
  • 为propper重置传播引入状态空闲
  • 更正地址计算->不带-1
  • 定义为常数的系数
  • 删除冗余寄存器
编辑1:

    architecture arch of top is

        type STYPE is (idle,load,count,nop,result);
        signal state_reg            : STYPE     := idle;
        signal state_next           : STYPE;

        signal address_rst          : std_logic;
        signal address_reg          : unsigned(3 downto 0)                      := (others => '0');

        type cof_table  is array (8 downto 0) of std_logic_vector(15 downto 0);
        type data_table is array (8 downto 0) of std_logic_vector(7 downto 0);

        signal datat_en             : std_logic;
        signal datat                : data_table;

        signal cof_alu_next         : std_logic_vector(15 downto 0);
        signal dt_in_alu_next       : std_logic_vector(7 downto 0);

        signal data_out_next        : std_logic_vector(23 downto 0);
        signal data_out_en          : std_logic;
        signal data_out_reg         : std_logic_vector(23 downto 0)     := (others => '0');

        constant coft                   : cof_table := (
            0 => "0000000001101110",
            1 => "1111111110111011",
            2 => "1111111011000000",
            3 => "0000010001000101",
            4 => "0000100110100110",
            5 => "0000010001000101",
            6 => "1111111011000000",
            7 => "1111111110111011",
            8 => "0000000001101110"
        );

    begin

        # no registers needed, because oft is constant and datat is already registered
        cof_alu_next    <= coft(to_integer(address_reg));
        dt_in_alu_next  <= datat(to_integer(address_reg));

        a1:alu port map (
                clk => clk,
                rst => clr,
                cof => cof_alu_next,
                data => dt_in_alu_next,
                y =>  data_out_next
        );

        process(rst, clk)
        begin
                if rst = '1' then
                        state_reg <= idle;
                elsif rising_edge(clk) then
                        state_reg <= state_next;
                end if;
        end process;

        # rewritten to synchronous registers
        process(clk)
        begin
                if rising_edge(clk) then
                    # address counter
                    # count if reset is low
                    if (address_rst = '1') then
                        address_reg     <= (others => '0');
                    else
                        address_reg     <= address_reg + 1;
                    end if;

                    # datatable
                    # store data if enabled
                    if (datat_en = '1') then
                        datat(to_integer(address_reg)) <= data_in;
                    end if;

                    # result register
                    if (data_out_en = '1') then
                        data_out_reg    <= data_out_next;
                    end if;
                end if;
        end process;


        process(state_reg, address_reg)
        begin
            state_next          <= state_reg;

            address_rst         <= '0';
            datat_en                <= '0';
            data_out_en         <= '0';

            case state_reg is
                when idle =>
                    address_rst <= '1';
                    state_next  <= load;                # add a condition if needed

                when load =>
                    datat_en        <= '1';
                    Yacc_next       <= address_reg;

                    if (address_reg = datat'high) then
                        address_rst <= '1';
                        state_next  <= count;
                    end if;

                when count =>
                    if (address_reg = datat'high) then
                        address_rst <= '1';
                        state_next  <= nop;
                    end if;

                when nop =>
                  state_next        <= result;

                when result =>
                    data_out_en     <= '1';
                    state_next      <= idle;        # if you want to go to count: assert address_rst in this state

                when others =>
                    state_next <= load;

            end case;
        end process;

        # outputs
        Yacc            <= address_reg when rising_edge(clk);       # delay Yacc output by one cycle (short form)
        data_out    <= data_out_reg;
    end arch;
我忘了alu有1个周期的延迟。所以,您可以在count状态下最多计数9,或者在count和result之间插入nop状态

为什么数据索引的计算是错误的?
-通电后和每次复位后,
address_reg
为零,
state
为负载。
->
如果address_reg
是当前状态下的活动分支(加载)
->
中的
数据被写入索引
到_integer(“0000”)-1)

=>这是-1
=>模拟应给出超出范围的错误

为什么
cof\u-alu\u reg
dt\u-in\u-alu\u reg
上的附加寄存器错误?
-FSM为alu状态计数选择适当的系数和输入。
-记录这些值(1个周期延迟)
-alu模块以另一个延迟周期执行计算 =>因此,在为alu分配最后一个输入值后,在data_out_reg捕获结果之前,必须有2个周期的延迟

修改的源代码(非模拟):

    architecture arch of top is

        type STYPE is (idle,load,count,nop,result);
        signal state_reg            : STYPE     := idle;
        signal state_next           : STYPE;

        signal address_rst          : std_logic;
        signal address_reg          : unsigned(3 downto 0)                      := (others => '0');

        type cof_table  is array (8 downto 0) of std_logic_vector(15 downto 0);
        type data_table is array (8 downto 0) of std_logic_vector(7 downto 0);

        signal datat_en             : std_logic;
        signal datat                : data_table;

        signal cof_alu_next         : std_logic_vector(15 downto 0);
        signal dt_in_alu_next       : std_logic_vector(7 downto 0);

        signal data_out_next        : std_logic_vector(23 downto 0);
        signal data_out_en          : std_logic;
        signal data_out_reg         : std_logic_vector(23 downto 0)     := (others => '0');

        constant coft                   : cof_table := (
            0 => "0000000001101110",
            1 => "1111111110111011",
            2 => "1111111011000000",
            3 => "0000010001000101",
            4 => "0000100110100110",
            5 => "0000010001000101",
            6 => "1111111011000000",
            7 => "1111111110111011",
            8 => "0000000001101110"
        );

    begin

        # no registers needed, because oft is constant and datat is already registered
        cof_alu_next    <= coft(to_integer(address_reg));
        dt_in_alu_next  <= datat(to_integer(address_reg));

        a1:alu port map (
                clk => clk,
                rst => clr,
                cof => cof_alu_next,
                data => dt_in_alu_next,
                y =>  data_out_next
        );

        process(rst, clk)
        begin
                if rst = '1' then
                        state_reg <= idle;
                elsif rising_edge(clk) then
                        state_reg <= state_next;
                end if;
        end process;

        # rewritten to synchronous registers
        process(clk)
        begin
                if rising_edge(clk) then
                    # address counter
                    # count if reset is low
                    if (address_rst = '1') then
                        address_reg     <= (others => '0');
                    else
                        address_reg     <= address_reg + 1;
                    end if;

                    # datatable
                    # store data if enabled
                    if (datat_en = '1') then
                        datat(to_integer(address_reg)) <= data_in;
                    end if;

                    # result register
                    if (data_out_en = '1') then
                        data_out_reg    <= data_out_next;
                    end if;
                end if;
        end process;


        process(state_reg, address_reg)
        begin
            state_next          <= state_reg;

            address_rst         <= '0';
            datat_en                <= '0';
            data_out_en         <= '0';

            case state_reg is
                when idle =>
                    address_rst <= '1';
                    state_next  <= load;                # add a condition if needed

                when load =>
                    datat_en        <= '1';
                    Yacc_next       <= address_reg;

                    if (address_reg = datat'high) then
                        address_rst <= '1';
                        state_next  <= count;
                    end if;

                when count =>
                    if (address_reg = datat'high) then
                        address_rst <= '1';
                        state_next  <= nop;
                    end if;

                when nop =>
                  state_next        <= result;

                when result =>
                    data_out_en     <= '1';
                    state_next      <= idle;        # if you want to go to count: assert address_rst in this state

                when others =>
                    state_next <= load;

            end case;
        end process;

        # outputs
        Yacc            <= address_reg when rising_edge(clk);       # delay Yacc output by one cycle (short form)
        data_out    <= data_out_reg;
    end arch;
顶部的建筑拱门是
类型STYPE为(空闲、负载、计数、nop、结果);
信号状态_reg:STYPE:=空闲;
信号状态_next:STYPE;
信号地址:标准逻辑;
信号地址_reg:unsigned(从3到0):=(其他=>'0');
cof_表类型为std_逻辑_向量(15向下到0)的数组(8向下到0);
类型数据表是标准逻辑向量(7到0)的数组(8到0);
信号数据:标准逻辑;
信号数据:数据表;
信号COFU alu next:标准逻辑矢量(15向下至0);
信号dt_in_alu_next:标准逻辑向量(7到0);
信号数据输出下一步:标准逻辑向量(23向下至0);
信号数据输出:标准逻辑;
信号数据_out_reg:std_逻辑_向量(23向下至0):=(其他=>'0');
常数coft:cof_表=(
0 => "0000000001101110",
1 => "1111111110111011",
2 => "1111111011000000",
3 => "0000010001000101",
4 => "0000100110100110",
5 => "0000010001000101",
6 => "1111111011000000",
7 => "1111111110111011",
8 => "0000000001101110"
);
开始
#不需要寄存器,因为oft是常量,并且datat已经注册
下一个clr的cof_alu__,
cof=>cof_alu_下一步,
数据=>dt\u in\u alu\u next,
y=>data\u out\u next
);
过程(rst、clk)
开始
如果rst='1',则

陈述一些问题:为什么要在
中将
数据写入
地址-1
datat
像寄存器一样寻址,但它没有时钟或相应的进程。内存是std逻辑向量的简单表。我在时钟的第二个节拍开始写入内存的第一个地址,这就是为什么adress-1在那里。那么为什么不把计数器调整到正确的值呢?有时需要从-1或-2开始。但在指数计算中加入-1会迫使合成插入减法器(减法器)。这是用于合成的吗?你能用模拟结果来说明缺点吗?提供链接,有人可以编辑您的问题以添加图像。这个想法是为了让问题和答案对其他Stackoverflow用户都有价值。您是否在提问者的设计规范中确定了“bug在哪里”?您的
top
版本是否能够克服这一问题?如果是,原因是什么?@DavidKoontz我认为主要的问题是:错误的计算索引和不必要的“管道”寄存器引入的许多延迟。FSM不尊重总体延迟,它将数据捕获到早期。“我认为”,“延迟太多”?提问者和回答者都没有提供任何模拟数据,甚至连管道延迟图都没有。即使发问者能够根据您的假设使其设计工作正常,对其他Stackoverflow用户也没有任何价值,除非发问者明确说明发生了什么变化并解释了问题所在。我认为你可能是对的,但没有证据表明你的回答和我的评论都是观点。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity alu is 
port (
    clk, rst : in std_logic;
    data        : in std_logic_vector(7 downto 0);
    cof     : in std_logic_vector(15 downto 0);
    y           : out std_logic_vector(23 downto 0)
);
end alu;

architecture arch of alu is

signal mul_in_a               : std_logic_vector(7 downto 0);
signal mul_in_b               : std_logic_vector(15 downto 0);
signal mul_out            : std_logic_vector(23 downto 0);

signal add_in_a, add_in_b : std_logic_vector(23 downto 0);
signal add_out                : std_logic_vector(23 downto 0);

signal reg_in, reg_out    : std_logic_vector(23 downto 0);

component mul
    port(
        a : in std_logic_vector(7 downto 0);
        b : in std_logic_vector(15 downto 0);
        r : out std_logic_vector(23 downto 0)   
    );
end component;

component add
    port(
        a : in std_logic_vector(23 downto 0);
        b : in std_logic_vector(23 downto 0);
        s : out std_logic_vector(23 downto 0)
    );
end component;

component reg
    port(
        clk  : in std_logic;
        rst  : in std_logic;
        d     : in std_logic_vector(23 downto 0);
        q    : out std_logic_vector(23 downto 0)
    );
end component;

begin

b1:mul port map(
    a => mul_in_a,
    b => mul_in_b,
    r => mul_out
);

b2:add port map (
    a => add_in_a,
    b => add_in_b,
    s => add_out
);

b3:reg port map (
    clk => clk,
    rst => rst,
    d   => reg_in,
    q   => reg_out
);

mul_in_a <= data;
mul_in_b <= cof;

add_in_a <= mul_out;
add_in_b <= reg_out;

reg_in  <= add_out;

       y <= reg_out;
end arch;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity top is
port(
    clk   : in std_logic;
    rst   : in std_logic;
    rst_a     : in std_logic;
    data_in : in std_logic_vector(7 downto 0);
    data_out: out std_logic_vector(23 downto 0);
    Yacc      :  out unsigned(3 downto 0)
);
end top;

architecture arch of top is

type STYPE is (load,count,result);
signal cof_alu_reg, cof_alu_next                              : std_logic_vector(15 downto 0);
signal dt_in_alu_reg,dt_in_alu_next                       : std_logic_vector(7 downto 0);
signal datao                              : std_logic_vector(23 downto 0);
signal state_reg, state_next          : STYPE;
signal adress_reg, adress_next                            :unsigned(3 downto 0);
signal data_out_reg, data_out_next : std_logic_vector(23 downto 0);

type cof_table is array ( 8 downto 0) of std_logic_vector( 15 downto 0);
type data_table is array ( 8 downto 0) of std_logic_vector(7 downto 0);
signal Yacc_reg, Yacc_next :  unsigned(3 downto 0);
signal clr : std_logic;
signal datat                              : data_table;
signal coft                               : cof_table;

component alu
port(
    clk, rst : in std_logic;
    data        : in std_logic_vector(7 downto 0);
    cof     : in std_logic_vector(15 downto 0);
    y           : out std_logic_vector(23 downto 0)
     );
end component;

begin

a1:alu port map (
    clk => clk,
    rst => clr,
    cof => cof_alu_reg,
    data => dt_in_alu_reg,
    y =>  datao
);

process(rst, clk)
begin
    if rst = '1' then
        state_reg <= load;
    elsif rising_edge(clk) then
        state_reg <= state_next;
    end if;
end process;



process(rst, clk)
begin
    if rst = '1' then
        cof_alu_reg <= (others => '0');
        dt_in_alu_reg <= (others => '0');
        adress_reg <= "0000";
        data_out_reg <= (others => '0');
        Yacc_reg <= "0000";
    elsif rising_edge(clk) then
        cof_alu_reg <= cof_alu_next;
        dt_in_alu_reg <= dt_in_alu_next;
        adress_reg <= adress_next;
        data_out_reg <= data_out_next;
        Yacc_reg <= Yacc_next;
    end if;
end process;


process(state_reg, cof_alu_reg,dt_in_alu_reg,adress_reg,Yacc_reg,datao,clr)
begin
    state_next <= state_reg;
    cof_alu_next <= cof_alu_reg;
    dt_in_alu_next <= dt_in_alu_reg;
    adress_next <= adress_reg;
    data_out_next <= data_out_reg;
    Yacc_next <= Yacc_reg;

    coft(0) <= "0000000001101110";
    coft(1) <= "1111111110111011";
    coft(2) <= "1111111011000000";
    coft(3) <= "0000010001000101";
    coft(4) <= "0000100110100110";
    coft(5) <= "0000010001000101";
    coft(6) <= "1111111011000000";
    coft(7) <= "1111111110111011";
    coft(8) <= "0000000001101110";

    Yacc <= Yacc_reg;
    case state_reg is
        when load =>
        if adress_reg < "1001" then
            datat(to_integer(adress_reg)-1) <= data_in;
            Yacc_next <= adress_reg;
            adress_next <= adress_reg + "0001";
            state_next <= load;
        elsif adress_reg = "1001" then
            datat(to_integer(adress_reg)-1) <= data_in;
            Yacc_next <= adress_reg;
            adress_next <= "0000";
            state_next <= count;
        end if;

        when count =>
        if adress_reg < "1001" then
            dt_in_alu_next <= datat(to_integer(adress_reg)-1);
            cof_alu_next    <= coft(to_integer(adress_reg)-1);
            Yacc_next <= adress_reg;
            adress_next <= adress_reg + "0001";
            state_next <= count;
        elsif adress_reg = "1001" then
            dt_in_alu_next <= datat(to_integer(adress_reg-1));
            cof_alu_next    <= coft(to_integer(adress_reg)-1);
            state_next <= result;
            adress_next <= "0000";
            Yacc_next <= adress_reg;
        end if;

        when result =>
            data_out_next <= datao;
            Yacc_next <= adress_reg;
            adress_next <= adress_reg + "0001";
            state_next <= load;


        when others =>
            state_next <= load;

    end case;
end process;

    data_out    <= data_out_reg;


end arch;
    architecture arch of top is

        type STYPE is (idle,load,count,nop,result);
        signal state_reg            : STYPE     := idle;
        signal state_next           : STYPE;

        signal address_rst          : std_logic;
        signal address_reg          : unsigned(3 downto 0)                      := (others => '0');

        type cof_table  is array (8 downto 0) of std_logic_vector(15 downto 0);
        type data_table is array (8 downto 0) of std_logic_vector(7 downto 0);

        signal datat_en             : std_logic;
        signal datat                : data_table;

        signal cof_alu_next         : std_logic_vector(15 downto 0);
        signal dt_in_alu_next       : std_logic_vector(7 downto 0);

        signal data_out_next        : std_logic_vector(23 downto 0);
        signal data_out_en          : std_logic;
        signal data_out_reg         : std_logic_vector(23 downto 0)     := (others => '0');

        constant coft                   : cof_table := (
            0 => "0000000001101110",
            1 => "1111111110111011",
            2 => "1111111011000000",
            3 => "0000010001000101",
            4 => "0000100110100110",
            5 => "0000010001000101",
            6 => "1111111011000000",
            7 => "1111111110111011",
            8 => "0000000001101110"
        );

    begin

        # no registers needed, because oft is constant and datat is already registered
        cof_alu_next    <= coft(to_integer(address_reg));
        dt_in_alu_next  <= datat(to_integer(address_reg));

        a1:alu port map (
                clk => clk,
                rst => clr,
                cof => cof_alu_next,
                data => dt_in_alu_next,
                y =>  data_out_next
        );

        process(rst, clk)
        begin
                if rst = '1' then
                        state_reg <= idle;
                elsif rising_edge(clk) then
                        state_reg <= state_next;
                end if;
        end process;

        # rewritten to synchronous registers
        process(clk)
        begin
                if rising_edge(clk) then
                    # address counter
                    # count if reset is low
                    if (address_rst = '1') then
                        address_reg     <= (others => '0');
                    else
                        address_reg     <= address_reg + 1;
                    end if;

                    # datatable
                    # store data if enabled
                    if (datat_en = '1') then
                        datat(to_integer(address_reg)) <= data_in;
                    end if;

                    # result register
                    if (data_out_en = '1') then
                        data_out_reg    <= data_out_next;
                    end if;
                end if;
        end process;


        process(state_reg, address_reg)
        begin
            state_next          <= state_reg;

            address_rst         <= '0';
            datat_en                <= '0';
            data_out_en         <= '0';

            case state_reg is
                when idle =>
                    address_rst <= '1';
                    state_next  <= load;                # add a condition if needed

                when load =>
                    datat_en        <= '1';
                    Yacc_next       <= address_reg;

                    if (address_reg = datat'high) then
                        address_rst <= '1';
                        state_next  <= count;
                    end if;

                when count =>
                    if (address_reg = datat'high) then
                        address_rst <= '1';
                        state_next  <= nop;
                    end if;

                when nop =>
                  state_next        <= result;

                when result =>
                    data_out_en     <= '1';
                    state_next      <= idle;        # if you want to go to count: assert address_rst in this state

                when others =>
                    state_next <= load;

            end case;
        end process;

        # outputs
        Yacc            <= address_reg when rising_edge(clk);       # delay Yacc output by one cycle (short form)
        data_out    <= data_out_reg;
    end arch;