【发布时间】:2013-07-22 17:12:21
【问题描述】:
这是一个通用的 FPGA 设计问题,我是 FPGA 设计的新手,刚刚开始了我的第一个大型项目,构建了一些不错的线性代数求解器。这些系统非常大,所以第一次就做好很重要。
在成功模拟之后,我现在正在合成,但我做噩梦了,我必须逐个组件地构建和测试它,因为在模拟中没有任何表现!我主要遇到输出未同步的状态机问题,例如这是我正在使用的数据加载器:
entity TriDiag_Data_Scheduler is
generic( W : integer :=16;
AW : integer := 10 -- address width
);
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC; --attatched to data finished
d_ready : in STD_LOGIC;
din : in STD_LOGIC_VECTOR (W-1 downto 0);
wr_en : out STD_LOGIC_VECTOR (3 downto 0);
dout_a, dout_b, dout_c, dout_y : out STD_LOGIC_VECTOR (W-1 downto 0);
addr_out : out STD_LOGIC_VECTOR (AW-1 downto 0));
end TriDiag_Data_Scheduler;
architecture Behavioral of TriDiag_Data_Scheduler is
type state is (a,b,c,y);
signal state_pr, state_next : state := y;
signal addr_reg, addr_next : std_logic_vector(AW-1 downto 0) :=(others =>'1');
signal wr_en_next : std_logic_vector(3 downto 0);
--data buffer
signal d_buff, d_buff_a, d_buff_b, d_buff_c, d_buff_y : std_logic_vector (W-1 downto 0) :=(others =>'0');
signal d_buff_a_reg, d_buff_b_reg, d_buff_c_reg, d_buff_y_reg : std_logic_vector (W-1 downto 0) :=(others =>'0');
begin
process(clk,rst)
begin
if(clk'event and clk ='1') then
state_pr <= state_next;
d_buff_a <= d_buff_a_reg;
d_buff_b <= d_buff_b_reg;
d_buff_c <= d_buff_c_reg;
d_buff_y <= d_buff_y_reg;
addr_reg <= addr_next;
wr_en <= wr_en_next;
end if;
end process;
addr_out <= addr_reg;
dout_a <= d_buff_a;
dout_b <= d_buff_b;
dout_c <= d_buff_c;
dout_y <= d_buff_y;
--Data out logic
process(state_pr, d_buff_a, d_buff_b, d_buff_c, d_buff_y, d_buff)
begin
d_buff_a_reg <= d_buff_a;
d_buff_b_reg <= d_buff_b;
d_buff_c_reg <= d_buff_c;
d_buff_y_reg <= d_buff_y;
case state_pr is
when a => --move data to a reg
d_buff_a_reg <= d_buff;
when b => --move data to b reg
d_buff_b_reg <= d_buff;
when c => --move data to c reg
d_buff_c_reg <= d_buff;
when y =>
d_buff_y_reg <= d_buff;
end case;
end process;
--next state and addr logic
process(state_pr, d_ready, rst, din)
begin
state_next <= state_pr;
addr_next <= addr_reg;
wr_en_next <= (others => '0');
if(rst = '1') then
state_next <= a;
addr_next <= (others =>'1');
wr_en_next <= (others => '0');
elsif(d_ready = '1') then
--Read in the data to the buffer
d_buff <= din;
--next state logic
case state_pr is
when a => --move data to a reg
addr_next <= addr_reg + 1;
-- d_buff_a_reg <= din;
wr_en_next <= "0001";
state_next <= b;
when b => --move data to b reg
wr_en_next <= "0010";
-- d_buff_b_reg <= din;
state_next <= c;
when c => --move data to c reg
wr_en_next <= "0100";
-- d_buff_c_reg <= din;
state_next <= y;
when y =>
-- d_buff_y_reg <= din;
wr_en_next <= "1000";
state_next <= a;
end case;
end if;
end process;
end Behavioral;
基本上,当通过 UART 模块接收数据时,它的工作就是加载到正确的内存中(由 write_en 信号控制)。问题是在我所有的设计(这是修订版 7)中,所有 addr_out、wr_en 和正确的数据都是同步的,但在综合中我一直发现 addr 和 wr_en 与数据不同步,并且从前面读取了一半和前一个状态的一半。
我应该使用哪些设计实践以使我的 VHDL 更易于综合,因为按照这种速度,我将不得不为每个组件重新编写我之前的所有辛勤工作!
非常感谢 山姆
【问题讨论】:
-
我的 VHDL 是在家教的,如果冒犯了任何人,我深表歉意!
-
每当我看到具有大敏感度列表的非时钟进程时,我都会认为它们缺少某些东西。我没有详细了解它,但检查合成器警告,看看它是否发现了任何东西。就我个人而言,我会将其重写为单个时钟进程
-
再次感谢马丁。问题是它对外部 d_ready 信号很敏感。我通过添加一个由 d_ready 信号设置但随后在 clk 上断言的同步滴答声解决了这个问题。我认为我在 d_ready 和 clk 之间遭受了如此好的偏差,这就是为什么它不完全同步的原因。但是现在一切都在同步滴答声中处于活动状态,并且似乎可以正常工作。
-
我的经验是,软件人员使用更大的、单一的、有时钟的每个实体的进程和 变量 来处理不涉及与另一个进程通信的所有事情会取得更大的成功。当然是 YMMV,但可能值得一试......
-
我同意@MartinThompson 的观点:作为对如此大的组合过程有多危险的演示,请查看为
d_buff生成的闩锁。只是一个小疏忽,不会出现在模拟中,但会对综合产生很大影响。此外,在不是寄存器的情况下命名 _reg 非常令人困惑(例如,d_buff_a_reg)!
标签: hardware vhdl fpga xilinx state-machine