【问题标题】:How can I make this VHDL code synthesizable?如何使这个 VHDL 代码可合成?
【发布时间】:2013-03-19 21:45:27
【问题描述】:

我有 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

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

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

【问题讨论】:

    标签: vhdl


    【解决方案1】:

    问题在于这种形式的表达式创建了一个锁存器(它对其控制信号上的毛刺很敏感),而且它是一个具有多个控制信号的锁存器,在实际硬件中没有直接等效的。

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

    【讨论】:

    • 我所做的就是把and rising_edge(CLK)加到所有when语句中,这样看起来像:signal_1 &lt;= (others =&gt; '0') when cau_state = st_idle and rising_edge(CLK) else signal_1;这和放在一个进程和一个case里面是一样的吗?跨度>
    • 如果它有效并且sim 和synth 都支持它,是的,我相信是的。此外,我似乎欠“sharth”一个道歉——你现在可以在一个过程中使用条件分配风格——如果你的工具支持 VHDL-2008!称我为恐龙,但我(就像许多仍然存在的工具一样)仍然不了解所有 VHDL-2008。到“sharth”:如果你取消删除你的答案,我会支持它......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多