VHDL - iSIM 输出未初始化,不改变状态 [英] VHDL - iSIM output uninitialised, doesn't change states
问题描述
我是 Xilinx 的新用户,在如何在测试台上编写激励/模拟时遇到了麻烦.我的输出(Kd)没有给我任何合理的值,而是在前几个时钟周期给出u",然后移动并始终保持在1".
Hi I am a new Xilinx user and been having trouble with how to write stimulus/simulate in a test bench. My output(Kd) isn't giving me any sensible values and gives 'u' for the first few clock cycles before moving and staying at '1' throughout.
不确定我是否写了正确的刺激,但希望有人能帮助我!
Not sure if I have written the correct stimulus but hoping someone would help me out here!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity codeFig2b is
Port ( R0 : in STD_LOGIC;
R1 : in STD_LOGIC;
R2 : in STD_LOGIC;
R3 : in STD_LOGIC;
Kd : out STD_LOGIC;
clock : in STD_LOGIC);
end codeFig2b;
architecture Behavioral of codeFig2b is
signal Qa, Qb: STD_LOGIC;
begin
process(clock, R0, R1, R2, R3)
begin
if clock = '1' and clock'event then
Qa <= (R0 or R1 or R2 or R3) or (Qa and Qb);
Qb <= Qa;
end if;
end process;
Kd <= Qa and Qb;
end Behavioral;
我的测试平台##
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY codeFig2b_test IS
END codeFig2b_test;
ARCHITECTURE behavior OF codeFig2b_test IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT codeFig2b
PORT(
R0 : IN std_logic;
R1 : IN std_logic;
R2 : IN std_logic;
R3 : IN std_logic;
Kd : OUT std_logic;
clock : IN std_logic
);
END COMPONENT;
--Inputs
signal R0 : std_logic := '0';
signal R1 : std_logic := '0';
signal R2 : std_logic := '0';
signal R3 : std_logic := '0';
signal clock : std_logic := '0';
--Outputs
signal Kd : std_logic;
-- Clock period definitions
constant clock_period : time := 100 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: codeFig2b PORT MAP (
R0 => R0,
R1 => R1,
R2 => R2,
R3 => R3,
Kd => Kd,
clock => clock
);
-- Clock process definitions
clock_process :process
begin
clock <= '0';
wait for clock_period/2;
clock <= '1';
wait for clock_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
wait for 100 ns;
R0 <= '0';
R1 <= '0';
R2 <= '0';
R3 <= '0';
wait for 100 ns;
R0 <= '0';
R1 <= '0';
R2 <= '0';
R3 <= '1';
wait for 100 ns;
R0 <= '0';
R1 <= '0';
R2 <= '1';
R3 <= '0';
wait for 100 ns;
R0 <= '0';
R1 <= '0';
R2 <= '1';
R3 <= '1';
wait for 100 ns;
R0 <= '0';
R1 <= '1';
R2 <= '0';
R3 <= '0';
wait for 100 ns;
R0 <= '0';
R1 <= '1';
R2 <= '0';
R3 <= '1';
wait for 100 ns;
R0 <= '0';
R1 <= '1';
R2 <= '1';
R3 <= '0';
wait for 100 ns;
R0 <= '0';
R1 <= '1';
R2 <= '1';
R3 <= '1';
wait for 100 ns;
R0 <= '1';
R1 <= '0';
R2 <= '0';
R3 <= '0';
wait for 100 ns;
R0 <= '1';
R1 <= '0';
R2 <= '0';
R3 <= '1';
wait for 100 ns;
R0 <= '1';
R1 <= '0';
R2 <= '1';
R3 <= '0';
wait for 100 ns;
R0 <= '1';
R1 <= '0';
R2 <= '1';
R3 <= '1';
wait for 100 ns;
R0 <= '1';
R1 <= '1';
R2 <= '0';
R3 <= '0';
wait for 100 ns;
R0 <= '1';
R1 <= '1';
R2 <= '0';
R3 <= '1';
wait for 100 ns;
R0 <= '1';
R1 <= '1';
R2 <= '1';
R3 <= '0';
wait for 100 ns;
R0 <= '1';
R1 <= '1';
R2 <= '1';
R3 <= '1';
wait for clock_period*10;
-- insert stimulus here
wait;
end process;
END;
推荐答案
您构建的是顺序逻辑,这意味着输出取决于先前的历史输入/输出.在您的情况下,我们有 Qa 和 Qb,这是 Qa 的最后一个值.
What you built is a sequential logic, meaning that the outputs depend on the previous hystory of the inputs/outputs. In your case we have Qa, and Qb which is the last value of Qa.
记住这一点,您在测试平台中使用的方法不是最佳的,因为您尝试输入的每一种组合,而没有考虑到最后一个 Qa 实际上很重要.
Keeping this in mind, the approach you have used in the testbench is not optimal, because you are trying every combination of the inputs without taking into account that the last Qa is actually important.
事情是这样的:
Start : Qa = U Qb = U => Kb = U
Inputs 1: Qa = 1 Qb = U => Kb = U
Inputs 2: Qa = 1 Qb = 1 => Kb = 1
Inputs 3: Qa = 1 Qb = 1 => Kb = 1
Inputs 4: Qa = 1 Qb = 1 => Kb = 1
....
只要其中一个 Rs 变高,Qa 就会变高.鉴于输入组合的顺序,Qa 不会再次变低.这意味着在第二次输入组合后,Qb 获得一个已知值,而 Kb 变高.
As soon as one of the Rs goes high, Qa is high. Given the order of your combinations of inputs, there is no case where Qa goes low again. This means that after the second input combination, Qb gets a known value and Kb goes high.
敏感列表
这不是答案的一部分,而是对您编写的代码的考虑:您已将敏感度列表 R0、R1、R2、R3 放在了敏感列表中,但是,鉴于您之后编写的内容,这不是必需的.
This is not part of the answer but it's a consideration on the code you have written: you have put on the sensitivity list R0, R1, R2, R3 but, given what you have written after that, this is not necessary.
该进程仅在以下情况下执行某些操作
The process does something only if
if clock'event and clock = 1 then
这意味着 Rs 上的任何事件都将被忽略.我确信合成器实际上意识到了这一点并忽略了它,但设置适当的敏感度列表是一个很好的做法,并且在可能的情况下,仅对时序逻辑和有限状态机使用时钟过程.
this means that any event on the Rs are ignored. I'm sure that the synthetizer actually realizes that and ignores it, but it's a good practice to set a proper sensitivity list and, when possible, only use clocked processes for sequential logic and finite state machines.
我也建议你使用更易读的rising_edge(clock) 和falling_edge(clock) 函数:
I also suggest that you use the more readable rising_edge(clock) and falling_edge(clock) functions:
process(clock)
begin
if rising_edge(clock) then
Qa <= R0 or R1 or R2 or R3 or (Qa and Qb);
Qb <= Qa;
end if;
end process;
<小时>
信号和过程
您应该知道的另一件事是该过程的工作原理:您不是为信号分配新值,而是为它们规划值.如果您重新编程某个信号,您只是在覆盖之前的计划,并且永远不会分配第一个值.最终在过程结束时分配值.
Another thing you should know is how the process work: you are not assigning new values to the signals, but rather planning values for them. If you reprogram a certain signal you are just overwriting the previous planning, and the first value is never assigned. The values are finally assigned at the end of the process.
这是一个简单的例子:
-- Let's assume A = 0 and B = 0 at startup
clocked_process : process(clk)
begin
if rising_edge(clk) then
A <= '1';
B <= A;
A <= '0';
end if;
end process;
最后B还是0,这是因为整个过程A=0,只得到一个计划值为1,实际上从未赋值,因为它在过程结束前被覆盖了(在这种特定情况下,合成器将忽略 A <= '1' 实现).
At the end B is still 0, this because A = 0 for the whole process and only gets a planned value of 1, actually never assigned because it is overwritten before the end of the process (in this specific case the synthetizer will ignore A <= '1' for the implementation).
覆盖计划值可以简化逻辑:我通常做的是设置一些默认值,然后仅在需要时才覆盖它们.
Overwriting the planned value can be used to simplify the logic: what I usually do is setting some default values and then overwriting them only when I need to.
所以,而不是写
...
case A is
when "00" =>
B <= '0';
when "01" =>
B <= '0';
when "10" =>
B <= '0';
when "11" =>
B <= '1';
end case;
...
我写这个(如果我需要它用于其他信号,通常在有限状态机中,我可能会保留案例结构):
I write this (I may retain the case structure if I need it for other signals, typically in Finite State Machines):
...
B <= '0';
if A = "11" then
B <= '1';
end if;
...
对于这个简单的例子,合成器可能能够推断出示例.但是,您应该习惯于在逻辑级端口中思考,因为从行为的角度来看,以两种等效方式编写的同一件事实际上实现方式不同.
For this simple examples the synthetizer may be able to infer the semplification. However, you should get used to think in logic level ports because the same thing written in two equivalent ways from a behavioral point of view, is actually implemented differently.
这篇关于VHDL - iSIM 输出未初始化,不改变状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!