2

我有使用闲置语法的 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;

wherecau_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

我收到许多信号的这些消息,但不是所有使用此语法的信号。对于获得此消息的信号,我得到它的所有位:cross_3_sig[0][31]to 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
                       ...

有什么问题,我该如何解决?

4

1 回答 1

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 将保持其当前值。

或者更好的选择:在过程中使用 case 语句:

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 中很麻烦!

于 2013-03-19T13:45:27.830 回答