我有VHDL代码,它使用了令人厌恶的语法:
signal_1 <= (others => '0') when cau_state = st_idle else
signal_2 - signal_3 when cau_state = st_cycle_1 else
signal_4 when cau_state = st_cycle_2 else
signal_5 when cau_state = st_cycle_3 else
signal_6 when cau_state = st_cycle_4 else
signal_1;
其中cau_state
是保持当前状态的信号。这种语法适用于Model-Sim的模拟,一切正常。但是当我想将代码刻录到FPGA时,代码没有在Altera Quartus II 32位版本上合成。 12.1我收到了错误消息:
Warning (13012): Latch CAU:uut|cross_3_sig[0][31] has unsafe behavior
Warning (13013): Ports D and ENA on the latch are fed by the same signal CAU:uut|cau_state.st_cycle_2
Warning (13012): Latch CAU:uut|cross_3_sig[0][30] has unsafe behavior
Warning (13013): Ports D and ENA on the latch are fed by the same signal CAU:uut|cau_state.st_cycle_2
我收到许多信号的这些信息,但 NOT 表示使用此语法的所有信号。对于获得此消息的信号,我得到它的所有位:cross_3_sig[0][31]
到cross_3_sig[0][0]
。信号cross_3_sig(0)
的语法是:
constant WIDTH : integer := 32;
...
subtype scalar is std_logic_vector((WIDTH-1) downto 0);
type vector_nd is array (natural range <>) of scalar;
subtype vector_3d is vector_nd(2 downto 0);
...
signal cross_3_sig : vector_3d;
...
cross_3_sig(0) <= sum_mults_out_sig when cau_state = st_cycle_2 else
mult1_out_sig - mult2_out_sig when cau_state = st_cycle_9 else
cross_3_sig(0);
在某些地方我将cross_3_sig(0)
分配给其他信号,即:
numer_sig <= C_ZERO - cross_3_sig(0) & (16 downto 0 => '0');
mult1_in2_sig <= (others => '0') when cau_state = st_idle else
...
cross_3_sig(0) when cau_state = st_cycle_11 else
...
问题是什么,我该如何解决?
答案 0 :(得分:3)
问题在于这种表达形式会产生一个锁存器(对其控制信号上的毛刺很敏感),而且它是一个具有多个控制信号的锁存器,在实际硬件中没有直接的等价物。
signal_1 <= (others => '0') when cau_state = st_idle else
...
signal_6 when cau_state = st_cycle_4 else
signal_1;
任何时候你看到(在时钟进程之外)类似
的东西signal_1 <= ... else signal_1;
你知道你有问题吗?这是一个直接馈电的信号,试图用简单的电线作为记忆。
此模式的正确用法是作为多路复用器,而不是内存,
output_1 <= input_1 when ... else
input_2 when ... else
input_n;
记住signal1旧值的正确方法是一个时钟进程,例如
process (clk)
begin
if rising_edge(clk) then
if cau_state = st_idle then signal_1 <= (others => '0')
...
elsif cau_state = st_cycle_4 then signal_1 <= signal_6;
end if;
end if;
end process;
如果没有分配,signal_1将保持其当前值。
或者更好的选择:在流程中使用案例陈述:
process (clk)
begin
if rising_edge(clk) then
case cau_state is
when st_idle => signal_1 <= (others => '0')
...
when st_cycle_4 => signal_1 <= signal_6;
-- when others => some default action
end case;
end if;
end process;
这确实将语义转换为时钟设计,但至少可以说,非FPGA设计在FPGA中很麻烦!