我一直试图在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条“你应该使用寄存器,永远不会锁存”,所以我想解决这个警告。
如果你能给我指路的话会很棒!
答案 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;