尝试在VHDL中创建内存总线时生成的锁存器

时间:2014-03-13 08:31:50

标签: vhdl

我一直试图在FPGA中创建一个简单的内存,我可以用另一个处理器写入。我知道我应该使用FPGA RAM但是有人告诉我,我可以使用下面的代码制作一个简单的寄存器:

vcap_data_store : process(resetb,clk)
begin
    if resetb = '0' then
        vcap_data_in11 <= "0000000000000000000000";
        vcap_data_in12 <= "0000000000000000000000";
        vcap_data_in13 <= "0000000000000000000000";
        vcap_data_in14 <= "0000000000000000000000";
    elsif (rising_edge(clk)) then
        vcap_data_in11 <= vcap_data_in_11;
        vcap_data_in12 <= vcap_data_in_12;
        vcap_data_in13 <= vcap_data_in_13;
        vcap_data_in14 <= vcap_data_in_14;
    end if;
end process;

vdi_input_gen : process(vdi_csb, vdi_wrb, vdi_indt)
begin

    if (vdi_csb = '0' and vdi_wrb = '0') then
        if vdi_addr = "00000" then
            vcap_data_in_11(15 downto 0) <= vdi_indt(15 downto 0);
        elsif vdi_addr = "00001" then
            vcap_data_in_11(21 downto 16) <= vdi_indt(5 downto 0);
        elsif vdi_addr = "00010" then
            vcap_data_in_12(15 downto 0) <= vdi_indt(15 downto 0);
        elsif vdi_addr = "00011" then
            vcap_data_in_12(21 downto 16) <= vdi_indt(5 downto 0);
        elsif vdi_addr = "00100" then
            vcap_data_in_13(15 downto 0) <= vdi_indt(15 downto 0);
        elsif vdi_addr = "00101" then
            vcap_data_in_13(21 downto 16) <= vdi_indt(5 downto 0);
        elsif vdi_addr = "00110" then
            vcap_data_in_14(15 downto 0) <= vdi_indt(15 downto 0);
        elsif vdi_addr = "00111" then
            vcap_data_in_14(21 downto 16) <= vdi_indt(5 downto 0);
                    end if;
    end if;

end process;

问题是我一直在犯这些错误:

WARNING:Xst:737 - Found 1-bit latch for signal <vcap_data_in_11_7>. Latches may be
generated from incomplete case or if statements. We do not recommend the use of latches
in FPGA/CPLD designs, as they may lead to timing problems.

我不想使用锁存器,但我不知道如何将它们变成寄存器。 仅供参考我对vcap_data_in11使用“缓冲”类型。

是否有任何解决方法将这些作为寄存器实现?

我对VHDL很陌生,虽然我知道VDHL的10条诫命中有1条“你应该使用寄存器,永远不会锁存”,所以我想解决这个警告。

如果你能给我指路的话会很棒!

2 个答案:

答案 0 :(得分:0)

您所描述的是异步逻辑。你错过了一个时钟。首先,一个好的开始是描述一个顺序过程,其中所有寄存器都被更新,以及一个异步部分,其中逻辑发生。看看this link. 重要部分:      - 信号     信号Q,tempQ:;

process (Clock, Reset)
begin
  if Reset = '0' then
    -- reset register, Q <= <init state>
  elsif rising_edge(Clock) then
    -- update Register, Q <= tempQ;
 end if;
end process;

process(sig1,sig2,...,sign)
  -- set tempQ <= func(input signals)
end process;

如果操作正确,这将确保您生成注册表。当然,您可以将这两个流程合并为一个流程,但在我看来,这只会让您更难理解正在发生的事情。

答案 1 :(得分:0)

我有两个单独的建议。第一个修复你的代码。第二个(推荐)提出了一种更好的方法来构造这个问题的代码

首先,以下将修复您的代码,但不是最好的答案。问题是因为第二个进程没有定义vcap_data_in_11,...在未被选中时得到的信号。快速回答是使用默认分配。请注意,由于您选择的名称太相似,因此难以阅读代码。

vdi_input_gen : process(vdi_csb, vdi_wrb, vdi_indt)
begin
   -- default assignments:
   vcap_data_in_11 <= vcap_data_in11 ;   -- tempQ <= Q;
   vcap_data_in_12 <= vcap_data_in12 ; 
   vcap_data_in_13 <= vcap_data_in13 ; 
   vcap_data_in_14 <= vcap_data_in14 ; 

   -- your other code goes here:
    if (vdi_csb = '0' and vdi_wrb = '0') then
        if vdi_addr = "00000" then
            vcap_data_in_11(15 downto 0) <= vdi_indt(15 downto 0);
        elsif vdi_addr = "00001" then
            vcap_data_in_11(21 downto 16) <= vdi_indt(5 downto 0);
        elsif vdi_addr = "00010" then
    . . . 

    end if;
end process;

我的更大建议是将代码重新编写为单个进程。感到惊讶我是第一个推荐这个,因为其他人对此感到强烈,我实际上并不是这样。我主要关注的是编写简单易读的代码。我还建议你使用case语句,而不是在处理同一个对象时(在这种情况下是vdi_addr):

因此,您的代码将变为以下内容。请注意,您不再需要默认分配,因为在时钟进程中,反馈变为负载启用条件(这是此问题所需)而不是锁存器。

vcap_data_store : process(resetb,clk)
begin
    if resetb = '0' then
        vcap_data_in11 <= "0000000000000000000000";
        vcap_data_in12 <= "0000000000000000000000";
        vcap_data_in13 <= "0000000000000000000000";
        vcap_data_in14 <= "0000000000000000000000";
    elsif (rising_edge(clk)) then
      if (vdi_csb = '0' and vdi_wrb = '0') then
        case vdi_addr is
          when "00000" =>   vcap_data_in11(15 downto 0)  <= vdi_indt(15 downto 0);
          when "00001" =>   vcap_data_in11(21 downto 16) <= vdi_indt( 5 downto 0);
          when "00010" =>   vcap_data_in12(15 downto 0)  <= vdi_indt(15 downto 0);
          when "00011" =>   vcap_data_in12(21 downto 16) <= vdi_indt( 5 downto 0);
          when "00100" =>   vcap_data_in13(15 downto 0)  <= vdi_indt(15 downto 0);
          when "00101" =>   vcap_data_in13(21 downto 16) <= vdi_indt( 5 downto 0);
          when "00110" =>   vcap_data_in14(15 downto 0)  <= vdi_indt(15 downto 0);
          when "00111" =>   vcap_data_in14(21 downto 16) <= vdi_indt( 5 downto 0);
          when others  =>   null ; -- do nothing !
        end case;
      end if;
    end if;
end process;