Filter FSM,产品总数计数
我的VHDL项目有一个问题。代码如下: 注册模块: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
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_reg1001”,则
是当前状态下的活动分支(加载)
->
中的数据被写入索引到_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;