I've learned that SR-Latch does oscillate when S and R are both '0' after they were just '1' in following circuit VHDL Code.
here is VHDL of SRLATCH
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity SRLATCH_VHDL is
port(
S : in STD_LOGIC;
R : in STD_LOGIC;
Q : inout STD_LOGIC;
NOTQ: inout STD_LOGIC);
end SRLATCH_VHDL;
architecture Behavioral of SRLATCH_VHDL is
begin
process(S,R,Q,NOTQ)
begin
Q <= R NOR NOTQ;
NOTQ<= S NOR Q;
end process;
end Behavioral;
and followings are process in Testbench code and its simulation results
-- Stimulus process
stim_proc: process
begin
S <= '1'; R <= '0'; WAIT FOR 100NS;
S <= '0'; R <= '0'; WAIT FOR 100NS;
S <= '0'; R <= '1'; WAIT FOR 100NS;
S <= '0'; R <= '0'; WAIT FOR 100NS;
S <= '1'; R <= '1'; WAIT FOR 500NS;
end process;
and totally I don't have any idea why simulation doesn't reflect...
(click to enlarge)
Someone is teaching you wrong knowledge!
SR and RS basic flip-flops (also called latches) don't oscillate. The problem on S = R = 1 (forbidden) is that you don't know the state after you leave S = R = 1 because you can never go to S = R = 0 (save) simultaneously. You will transition for S = R = 1 to S = R = 0 through S = 1; R = 0 (set) or S = 0; R = 1 (reset). This will trigger either a set or reset operation before you arrive in state save.
Be aware that VHDL simulates with discrete time and is reproducing the same simulation results on every run. You can not (easily) simulate physical effects that cause different signal delays per simulation run.
Btw. you VHDL description is also wrong. Q and NOTQ are of mode out, not inout. Use either a proper simulator supporting VHDL-2008 (that allows read back of out-ports) or use an intermediate signal.
Nice question, and your instructor is right - this circuit will oscillate if both S and R are released at the "same" time. Your issue is that your TB isn't doing this, but this one does:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity TOP is
end entity TOP;
architecture A of TOP is
signal S,R,Q,NOTQ: std_logic;
component SRLATCH_VHDL is
port(
S : in std_logic;
R : in std_logic;
Q : inout std_logic;
NOTQ : inout std_logic);
end component SRLATCH_VHDL;
begin
U1 : SRLATCH_VHDL port map(S, R, Q, NOTQ);
process is
begin
S <= '1';
R <= '1';
wait for 10 ns;
S <= '0';
R <= '0';
wait;
end process;
end architecture A;
This will produce infinite delta-delay oscillation:
This isn't a great way to demonstrate asynchronous behaviour, because you are effectively simplifying the physical nature of the circuit, and using the VHDL scheduler to show that there's a problem (with the use of 'delta delays'). A better way to do this is to model real circuit behaviour by adding signal delays (this is exactly what your tools are doing when they back-annotate for timing simulations). Look up signal assignments with after, and the difference between transport and inertial delays. If you draw a circuit diagram, you'll see that the issue arises if both S and R are released in a 'small' time window that doesn't allow the signal propagation around your circuit to complete before the second control signal changes. You now need to write a testbench that changes S and R inside this time window.
Pretty much everything you ever design will be asynchronous, in exactly the same way as your SR circuit. We make circuits 'synchronous' only by ensuring that input signals don't change at the same time. The job of the timing tools is to tell us what 'same' actually means: when you get a report or a datasheet value giving you a setup or a hold time, then that number is simply the numerical version of 'not the same'.
Related
I was hoping you could help me with a problem I encountered while trying to design synchronous circuits.
I have a simple D flip-flop in my design, such as the one shown in the figure below. But when I initialize my inputs and set the reset to 1 in the test bench, the output of the D flip-flop is always undefined (as can be seen in the "Objects" view), even though I explicitly define it to be 0 when reset is high (the code for the D flip-flop is shown below).
This causes errors in larger circuits when I use the flip-flops and the outputs as signals to other components that require a defined input. How can I achieve an output of zero when my reset is high during initialization?
library ieee;
use ieee.std_logic_1164.all;
entity Dff_en is
port (
d : in std_logic;
en : in std_logic;
clk : in std_logic;
reset : in std_logic;
q : out std_logic
) ;
end entity;
architecture rtl of Dff_en is
signal q_next, q_reg : std_logic;
begin
--dff logic
process(clk, reset) is
begin
if(reset = '1') then
q_reg <= '0';
elsif(rising_edge(clk)) then
q_reg <= q_next;
end if;
end process;
-- next-state logic
q_next <= d when (en = '1') else q_reg;
--output
q <= q_reg;
end architecture; -- arch
Your code will only update the q_reg output when there are events on the signals in the sensitivity list (clk, reset). VHDL (and Verilog) require events to trigger changes. With signal initialization, then at time 0 the values are set, but there are no further events to simulate.
Even if you did a run 100 ns, there would be no change in outputs since you have not had any events. Change either clk or reset some time after time 0 and try again.
I have some difficulties understanding how sequential statements inside a vhdl process are synthesized.
The IEEE standard reference manual Std 1076-2008 states:
Sequential statements are used to define algorithms for the execution of a subprogram or process; they execute in the order in which they appear.
It's easy to understand how it works in simulation since simulation is done by a CPU, that is build for sequential execution. In this case the hardest thing is to simulate concurrent executions, and this is done with the trick of delta delays.
But what about the synthesis? I don't understand how it is possible for two statements to be sequential in a fully logical architecture...
Any help ?
An example process:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity example is
Port (clk, rst, A : in STD_LOGIC; B : out STD_LOGIC);
end example;
architecture example_arch of example is
begin
process(clk, rst)
variable C : STD_LOGIC;
begin
if rst = '1' then
C := '0';
B <= '0';
elsif rising_edge(clk) then
if A = '1' then
E := '1';
else
E := '0';
end if;
-- then sequentially ?
if E = '1' then
B <= '1';
else
B <= '0';
end if;
end if;
end process;
end example_arch;
The synthesis tool will analyze the process and turn it into gates and flip-flops in a way that is faithful to the sequential (but also "instantaneous") execution of the process.
For example, your process (where I assume you meant to assign-to, and check the value of, variable C, not E) should be turned (synthesized) into a simple DFF with an asynchronous reset.
I am designing a parking-lot gate in VHDL. When I simulate it using Quartus VWF files, I am getting unknown values (X), but I don't know why.
Basically you just have to validate your card (Sin) and the gate opens for 10 seconds.
And when a car exits the parking lot (Sout), it counts the total cars at the moment inside of the parking lot.
I have created the signal Ncarros (to count number of cars) and s_count for the timer.
It all compiles correctly. But when I'm testing it using a VWF file, this is what I get:
Original simulation output
I'm using Altera Quartus Prime Lite Edition.
Can someone check my code and tell me what I'm doing wrong?
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
entity MicroProj is
port (clk : in std_logic;
Sin : in std_logic;
Sout : in std_logic;
cancela : out std_logic;
timerOut : out std_logic);
end MicroProj;
architecture Behavioral of MicroProj is
signal Ncarros : integer := 0;
signal s_count : integer := 0;
begin
process (Sin,Sout,clk)
begin
if (Sin = '0') then
cancela <= '0';
else
if (Ncarros < 99) then
Ncarros <= Ncarros + 1;
cancela <= '1';
if(rising_edge(clk)) then
if(s_count /= 0) then
if(s_count = 499999999) then
timerOut <= '1';
s_count <= 0;
else
timerOut <= '0';
s_count <= s_count + 1;
end if;
else
timerOut <= '0';
s_count <= s_count + 1;
end if;
end if;
end if;
end if;
if (Sout ='1') then
Ncarros <= Ncarros - 1;
end if;
end process;
end Behavioral;
When you simulate with a Vector Waveform File (VWF), Quartus-II actually simulates the behaviour of the synthesized netlist (checked here with Quartus-II 13.1). If you haven't run the step "Analysis & Synthesis", Quartus asks to do so. You have to always run this step manually, when you change your VHDL files before simulating the VWF again. The synthesized netlist is written out as Verilog code which will be the input of the ModelSim simulator. You can find it in the file simulation/qsim/microproj.vo.
As long as Quartus reports warnings (or errors), the behavior of the synthesized design can differ from the VHDL description. And this is the case here as pointed out below. To directly simulate the behavior of your VHDL description, you have to write a testbench.
The following testbench will be a good starter. It assign the same input values as in your VWF file for the first 200 ns. You will have to extend the code at the indicated location to add more signal transitions.
library ieee;
use ieee.std_logic_1164.all;
entity microproj_tb is
end entity microproj_tb;
architecture sim of microproj_tb is
-- component ports
signal clk : std_logic := '0';
signal Sin : std_logic;
signal Sout : std_logic;
signal cancela : std_logic;
signal timerOut : std_logic;
begin -- architecture sim
-- component instantiation
DUT: entity work.microproj
port map (
clk => clk,
Sin => Sin,
Sout => Sout,
cancela => cancela,
timerOut => timerOut);
-- clock generation
clk <= not clk after 10 ns;
-- waveform generation
WaveGen : process
begin
Sin <= '0';
Sout <= '0';
wait for 40 ns; -- simulation time = 40 ns
Sin <= '1';
wait for 70 ns; -- simulation time = 110 ns
Sin <= '0';
wait for 50 ns; -- simulation time = 160 ns
Sin <= '1';
-- Extend here to add more signal transistions
wait;
end process WaveGen;
end architecture sim;
The Quartus Prime Lite Edition includes an installation of the ModelSim Altera Edition. You can setup and start the simulation using ModelSim directly within the Quartus project settings. The simulation output for the first 200 ns using my testbench is as follows:
As you see, the output differs from your simulation of the VWF file because the VHDL design itself is simulated now.
In your VHDL code you described latches for the signals cancela and Ncarros as also reported by the "Analysis & Synthesis" step:
Warning (10492): VHDL Process Statement warning at MicroProj.vhdl(26): signal "Ncarros" is read inside the Process Statement but isn't in the Process Statement's sensitivity list
Warning (10492): VHDL Process Statement warning at MicroProj.vhdl(27): signal "Ncarros" is read inside the Process Statement but isn't in the Process Statement's sensitivity list
Warning (10492): VHDL Process Statement warning at MicroProj.vhdl(48): signal "Ncarros" is read inside the Process Statement but isn't in the Process Statement's sensitivity list
Warning (10631): VHDL Process Statement warning at MicroProj.vhdl(21): inferring latch(es) for signal or variable "cancela", which holds its previous value in one or more paths through the process
Warning (10631): VHDL Process Statement warning at MicroProj.vhdl(21): inferring latch(es) for signal or variable "Ncarros", which holds its previous value in one or more paths through the process
Info (10041): Inferred latch for "Ncarros[0]" at MicroProj.vhdl(20)
Info (10041): Inferred latch for "Ncarros[1]" at MicroProj.vhdl(20)
Info (10041): Inferred latch for "Ncarros[2]" at MicroProj.vhdl(20)
...
Info (10041): Inferred latch for "Ncarros[31]" at MicroProj.vhdl(20)
Info (10041): Inferred latch for "cancela" at MicroProj.vhdl(20)
On Altera FPGAs, latches are implemented using the look-up table (LUT) and a combinational feedback path within the logic element (LE). The state of such a latch is undefined after programming the FPGA. The simulation of the synthesized netlist shows this as 'X'es.
I recommend to fix the latches anyway and transform your code into a fullly synchronous, clock-edge driven design. That is, assign new values to cancela and Ncarros only at the rising edge of the clock. The VHDL code pattern is:
process(clk)
begin
if rising_edge(clk) then
-- put all your assignments to cancela and Ncarros here
end if;
end process;
I have been modelling a few simple VHDL gates, but I can't seem to get the time delay rightI have the following code:
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
ENTITY AND_4 IS
GENERIC (delay : delay_length := 0 ns);
PORT (a, b, c, d : IN std_logic;
x : OUT STD_logic);
END ENTITY AND_4;
ARCHITECTURE dflow OF AND_4 IS
BEGIN
x <= ( a and b and c and d) AFTER delay;
END ARCHITECTURE dflow;
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
ENTITY TEST_AND_4 IS
END ENTITY TEST_AND_4;
ARCHITECTURE IO OF TEST_AND_4 IS
COMPONENT AND_4 IS
GENERIC (delay : delay_length := 0 ns);
PORT (a, b, c, d : IN std_logic;
x : OUT STD_logic);
END COMPONENT AND_4;
SIGNAL a,b,c,d,x : std_logic := '0';
BEGIN
G1 : AND_4 GENERIC MAP (delay => 5ns) PORT MAP (a,b,c,d,x);
PROCESS
VARIABLE error_count : integer:= 0;
BEGIN
WAIT FOR 1 NS;
a <= '1';
b <= '0';
c <= '0';
d <= '0';
ASSERT (x = '1') REPORT "output error" SEVERITY error;
IF (x /= '1') THEN
error_count := error_count + 1;
END IF;
--Repeated test vector -- omitted
END PROCESS;
END ARCHITECTURE IO;
CONFIGURATION TESTER1 OF TEST_AND_4 IS
FOR IO
FOR G1 : AND_4
USE ENTITY work.AND_4(dflow)
GENERIC MAP (delay);
END FOR;
END FOR;
END CONFIGURATION TESTER1;
When I simulate the model I only get the 1 ns delay that I added to each test vector. I'm guessing the problem is how I pass the delay to the component declaration in the test bench. I've tried a few things and reread the topic in the book I have but still no joy. Any help ?
Many thanks
D
modifying the unlabelled stimulus process in your testbench:
process
variable error_count : integer:= 0;
begin
wait for 1 ns;
a <= '1';
-- b <= '0';
-- c <= '0';
-- d <= '0';
-- assert (x = '1') report "output error" severity error;
-- if (x /= '1') then
-- error_count := error_count + 1;
-- end if;
--repeated test vector -- omitted
b <= '1';
c <= '1';
d <= '1';
wait for 5 ns;
wait for 5 ns;
wait;
end process;
to simply demonstrated the delay shows that the generic delay is being passed to the instantiated component:
If you get something different perhaps you could convert your question to a Minimal, Complete, and Verifiable example by ensuring that the example actually reproduces the problem and that we know your results:
Describe the problem. "It doesn't work" is not a problem statement. Tell us what the expected behavior should be. Tell us what the exact wording of the error message is, and which line of code is producing it. Put a brief summary of the problem in the title of your question.
The little bit of stimulus you left in your testbench doesn't appear properly test the and_4.
In the event there was more stimulus and you weren't waiting the pulse rejection limit implied by your signal assignment delay mechanism, you'd get nothing but those annoying assertions.
See IEEE Std 1076-2008 10.5. Simple signal assignment statements, 5.2.1 General, paragraphs 5 and 6:
The right-hand side of a simple waveform assignment may optionally specify a delay mechanism. A delay mechanism consisting of the reserved word transport specifies that the delay associated with the first waveform element is to be construed as transport delay. Transport delay is characteristic of hardware devices (such as transmission lines) that exhibit nearly infinite frequency response: any pulse is transmitted, no matter how short its duration. If no delay mechanism is present, or if a delay mechanism including the reserved word inertial is present, the delay is construed to be inertial delay. Inertial delay is characteristic of switching circuits: a pulse whose duration is shorter than the switching time of the circuit will not be transmitted, or in the case that a pulse rejection limit is specified, a pulse whose duration is shorter than that limit will not be transmitted.
Every inertially delayed signal assignment has a pulse rejection limit. If the delay mechanism specifies inertial delay, and if the reserved word reject followed by a time expression is present, then the time expression specifies the pulse rejection limit. In all other cases, the pulse rejection limit is specified by the time expression associated with the first waveform element.
(Note you can go to 10.5.2.2 Executing a simple assignment statement and see the after time_expression is part of the waveform_element and not the delay mechanism).
Sure
ENTITY TEST_AND_4 IS
END ENTITY TEST_AND_4;
ARCHITECTURE IO OF TEST_AND_4 IS
COMPONENT AND_4 IS
GENERIC (delay : delay_length := 0 ns);
PORT (a, b, c, d : IN std_logic;
x : OUT STD_logic);
END COMPONENT AND_4;
SIGNAL a,b,c,d,x : std_logic := '0';
BEGIN
G1 : AND_4 GENERIC MAP (delay => 5 NS) PORT MAP (a,b,c,d,x);
PROCESS
VARIABLE error_count : integer:= 0;
BEGIN
WAIT FOR 1 NS; -- Changed to 6 ns so that the wait is longer then the
-- generic gate propagation delay
a <= '1';
b <= '1';
c <= '1';
d <= '1';
ASSERT (x = '1') REPORT "output error" SEVERITY error;
IF (x /= '1') THEN
error_count := error_count + 1;
END IF;
I have noted the change I made to the test bench model above, seems kinda obvious now but yesterday it had me pulling my hair out.
Cheers
D
The 'fix' was to change the WAIT value in the sequential test bench model from 1 ns to 6 ns. This gives the gate the time to change state because it has a 5 ns inertial delay.
WAIT FOR 6 NS; -- Changed to 6 ns so that the wait is longer then the
-- generic gate propagation delay
Thanks for the help, but I spotted the problem this morning after reading USER115520's post. The delay I set was 'inertial' and set generically at 5 ns. In my test bench process I had only set 1 ns wait statements in between input signal changes. Thus the gate would not perform the transition when the correct stimuli and introduced.
I inserted a 6 ns delay after a=1 b=1 c=1 d=1 and got the correct response from the gate
Description:
I want to include vhdl assert statements to report when set_delay and hold_delay time violations occur. I am not sure how to do this with my code and I have been to many places on the web and I don't understand. Please give examples with my code.
Code:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY dff IS
GENERIC (set_delay : TIME := 3 NS; prop_delay : TIME := 12 NS;
hold_delay : TIME := 5 NS);
PORT (d, set, rst, clk : IN BIT; q : OUT BIT; nq : OUT BIT := '1');
END dff;
--
ARCHITECTURE dff OF dff IS
SIGNAL state : BIT := '0';
BEGIN
dff: PROCESS
BEGIN
wait until rst;
wait until set;
wait until clk;
IF set = '1' THEN
q <= '1' AFTER set_delay;
nq <= '0' AFTER set_delay;
ELSIF rst = '1' THEN
q <= '0' AFTER prop_delay;
nq <= '1' AFTER prop_delay;
ELSIF clk = '1' AND clk'EVENT THEN
q <= d AFTER hold_delay;
nq <= NOT d AFTER hold_delay;
END IF;
END PROCESS dff;
END dff;
I do understand that the general assert syntax is:
ASSERT
condition
REPORT
"message"
SEVERITY
severity level;
Part of my problem is that I don't know where to put these assert statements and I am not sure how I would write them.
I would introduce additional signals in which you store the time of the last manipulation. Then I'd add other process which manage the signals and check the times:.
time_debug : block
signal t_setup, t_hold : time := 0 ns;
begin
setup_check : process (clk)
begin
if clk'event and clk = '1' then
t_hold <= now;
assert (t_setup - now)>set_delay REPORT "Setup time violated." SEVERITY note;
end if;
end process setup_check;
hold_check: process (d)
begin
if d'event then
t_setup <= now;
assert (t_hold - now)>hold_delay REPORT "Hold time violated." SEVERITY note;
end if;
end process hold_check;
end block time_debug;
What this does is it saves the time of the last positive clock edge and the time of the last input change. Now every time either d changes or the clock rises the delays are checked. I couldn't verify this in a compiler because I don't have one set up here, but I'll gladly do so if there are problems with this solution.
I personally like to keep debug stuff in a dedicated block, so I can easily keep track of which signals I only use for debugging and can later easily remove them. It also makes it easier to add all debug signals to e.g. modelsim's wave screen.
Also note that these asserts and reports will only work in simulation.