我的系统有一个3输入D_in,在每个正clk边缘读取。 如果说我想查看当前输入D_in是否比先前的D_in大至少2,则计数将递增。我如何用VHDL写这个?
if clk'event and clk = '1' then --read at positive edge
if D_in > (D_in + 010) then <---I am sure this is wrong. How to write the proper code?
Entity ABC is
Port(D_in: in std_logic_vector(2 downto 0);
Count: out std_logic_vector(2 downto 0));
Architecture ABC_1 of ABC is
signal D_last: std_logic_vector(2 downto 0);
Begin
Process(D_in)
D_last <= D_in;
if clk'event and clk = '1' then
if D_last > (D_in + 2) then
count <= count + 1;
end if;
end process;
end ABC_1;
答案 0 :(得分:1)
编写此过程的“好”方法如下:
process (clk)
begin
if (rising_edge(clk)) then
-- store the value for the next time the process will be activated
-- Note that D_last value will be changed after the whole process is completed
D_last <= D_in;
-- compare the actual D_in value with the previous one stored in D_last.
-- D_last value is its value at the very beginning of the process activation
if (D_in > D_last + 2) then
-- increment the counter
count <= count + 1;
end if;
end if;
end process;
请注意,D_in,D_last和count必须声明为unsigned而不是std_logic_vector。
我建议你阅读this post,它解释了一个过程是如何工作的:信号何时更新以及哪个信号值用于过程。
干杯
[编辑]这个答案对你的问题应该没问题。但是您显示的代码还有其他错误:
无法在架构中读取信号计数,因为它在实体中定义为输出。然后无法解析“count&lt; = count + 1”这一行。您必须使用内部信号,然后将其值分配给进程外的“count”:
count&lt; = count_in;
答案 1 :(得分:0)
您的设计规范中还有其他一些错误。这个答案试图在一个地方回答所有问题。
通过在模拟周期中执行过程来模拟VHDL。一切 并发语句可以表示为等效进程 语句或过程语句和块语句的组合。
信号分配是指定的预计输出波形队列 时间。如果没有指定时间,则表示当前时间,并且将更新该值 在下一个模拟周期中执行过程之前,进行增量循环,模拟 当没有安排剩余事件时,时间会提前 当前的模拟时间。
为避免混淆信号分配何时发生,请将其视为 单独的过程(无论你是否以这种方式表达)。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity abc is
port (
clk: in std_logic; -- Note 1
d_in: in std_logic_vector(2 downto 0);
count: out std_logic_vector(2 downto 0)
);
end entity; -- Note 2
architecture foo of abc is
signal d_last: std_logic_vector(2 downto 0);
begin
DLAST: -- Note 3
process (clk)
begin
if rising_edge(clk) then -- Note 4
d_last <= d_in;
end if;
end process;
INC_COUNT:
process (clk)
variable cnt: unsigned(2 downto 0) := "000"; -- Note 5
begin
if rising_edge(clk) and
unsigned(d_last) > unsigned(d_in) + 2 then -- Mote 6,7
cnt := cnt + 1;
end if;
count <= std_logic_vector(cnt);
end process;
end architecture;
备注强>
包numeric_std为
提供关系和添加运算符
键入符号并键入无符号,需要D_last的类型转换
和D_in。
或者使用Synopsys软件包std_logic_unsigned 依赖于Synopsys软件包std_logic_arith并对待 std_logic_vector为无符号。这避免了类型转换,并且 允许将数组类型声明为std_logic_vector类型。
如果要将端口cnt
声明为模式count
并提供默认值,则可以取消变量buffer
:
count: buffer std_logic_vector(2 downto 0) :="000" -- Note 5
和
INC_COUNT:
process (clk)
begin
if rising_edge(clk) and
unsigned(d_last) > unsigned(d_in) + 2 then -- Note 6,7
count <= std_logic_vector(unsigned(count) + 1);
end if;
end process;
您无法使用Count
作为模式out
来对其自身的值进行算法修改。访问模式输出端口值的能力用于验证,并且是IEEE Std 1076-2008功能。
现在你可以看到Synopsys的std_logic_unsigned包的价值,至少可以避免类型转换。
此外,我还有另一个问题。如果连续3个clk周期d_in为0,我想将count重置为0.如何编写代表3 clk周期的代码?
为D_in添加另一个管道信号:
signal d_last: std_logic_vector(2 downto 0) := "000";
signal d_last1: std_logic_vector(2 downto 0) := "000";
注意这些也有默认值,FPGA合成通常会尊重它,它由用于编程FPGA的bistream图像中的触发器状态表示。
修改计数器的操作方式:
INC_COUNT:
process (clk)
begin
if rising_edge(clk) then
if d_in = "000" and d_last = "000" and d_last1 = "000" then
count <= "000";
elsif unsigned(d_last) > unsigned(d_in) + 2 then -- Note 6,7
count <= std_logic_vector(unsigned(count) + 1);
end if;
end if;
end process;
该示例的三个版本都进行了分析,它们尚未进行模拟,并且应该是合成资格。