我的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;
多个模块:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity mul is
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 mul;
architecture arch of mul is
signal result : signed (23 downto 0);
begin
result <= signed(a) * signed(b);
r <= std_logic_vector(result);
end arch;
加法器模块:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity add is
port (
a,b : in std_logic_vector(23 downto 0);
s : out std_logic_vector(23 downto 0)
);
end add;
architecture arch of add is
signal result : signed(23 downto 0);
begin
result <= signed(a) + signed(b);
s <= std_logic_vector(result);
end arch;
ALU模块:
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;
热门模块,fsm:
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;
这个简单的系统计算了一系列产品。在时钟的前9个节拍中,我从输入获得了样本,我使用地址来增加下一个位置以保存样本。我的问题是当系统进入九个时钟节拍时,样本不会保存到内存中,这样可以减少最终结果。谁知道这个bug在哪里?
答案 0 :(得分:1)
这是我的建议 改进:
修改1:
我忘记了alu延迟了1个周期。因此,你可以将状态计数计数到9或在计数和结果之间插入一个nop状态。
为什么数据索引的计算错误?
- 上电后和每次重置后,adress_reg
为零,加载state
- &GT; if adress_reg < "1001" then
是当前状态(加载)的活动分支
- &GT; data_in
写入索引to_integer("0000")-1)
=&GT;这是-1
=&GT;模拟应该超出范围错误
为什么cof_alu_reg
和dt_in_alu_reg
上的其他寄存器错误?
- FSM为状态计数中的alu选择适当的系数和输入
- 注册这些值(1个循环延迟)
- alu模块使用另一个延迟周期执行计算
=&GT;因此,在为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;