Understanding this T Flip-Flop example? - vhdl

I'm reading a VHDL book and having trouble understanding an example they gave.
The code given:
-------------------------------------------------------------------
-- RET T Flip-flop model with active-low asynchronous set input. --
-------------------------------------------------------------------
-- library declaration
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity t_ff_s is
port ( T,S,CLK : in std_logic;
Q : out std_logic);
end t_ff_s;
-- entity
architecture my_t_ff_s of t_ff_s is
signal t_tmp : std_logic; -- intermediate signal declaration
begin
tff: process (S,CLK)
begin
if (S = '0') then
Q <= '1';
elsif (rising_edge(CLK)) then
t_tmp <= T XOR t_tmp; -- temp output assignment
end if;
end process tff;
Q <= t_tmp; -- final output assignment
end my_t_ff_s;
What I don't understand is how they assign multiple signals to Q. Outside of the process statement, it's Q <= t_tmp but inside the process if S='0' then Q <= '1'. How exactly does this work? It looks wrong to me with my limited understanding of VHDL. Basically, this looks the same to me as if writing:
Q <= '0';
Q <= '1';
Can anyone help me better understand this example better?

You're right to question the example. It's broken.
Q <= '1';
should be
t_tmp <= '1';
Somebody realised they couldn't read an output, introduced t_tmp and only changed half the code.

Related

VHDL state machine testbench - works when on board but not on simulation

I have the VHDL implementation that works on board, it detects the sequence 01110 and will raise a flag for 2 clock counts. It detects overlapping sequences as well where 011101110 would raise the flag twice.
I've checked my implementation with a logic analyzer on the board and am fairly confident that it works. I am feeding in a repetition sequence of 0111 at 10 kHz, on the board, it has a clock at 100 MHz where I scale it to 10 kHz with a prescaler.
My problem is, when trying to recreate a similar scenario using a simulation, I do not get any outputs as expected
Image from logic analyzer from board
Image from Test Bench
Test Bench Code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity test_FSM_prac4 is
-- Port ( );
end test_FSM_prac4;
architecture Behavioral of test_FSM_prac4 is
component FSM_prac4 is
port (
inputSignal : in STD_LOGIC;
pushButton : in STD_LOGIC;
clk100mhz : in STD_LOGIC;
logic_analyzer : out STD_LOGIC_VECTOR (7 downto 0);
LEDs: out STD_LOGIC
); end component;
signal inputSignal : std_logic := '0';
signal pushButton: std_logic := '0';
signal clk100mhz: std_logic := '0';
signal logic_analyzer: std_logic_vector(7 downto 0);
signal LEDs : std_logic;
begin
uut : FSM_prac4 port map(
inputSignal => inputSignal,
pushButton => pushButton,
clk100mhz => clk100mhz,
logic_analyzer => logic_analyzer,
LEDs => LEDs
);
--generate clock 100mhz
clock_tic: process begin
loop
clk100mhz <= '0';
wait for 5ns;
clk100mhz <= '1';
wait for 5ns;
end loop;
end process;
input_changes: process begin
loop
inputSignal <= '0';
wait for 100us;
inputSignal <= '1';
wait for 100us;
inputSignal <= '1';
wait for 100us;
inputSignal <= '1';
wait for 100us;
end loop;
end process;
end Behavioral;
To show the mapping for logic Analyzer
logic_analyzer(0) <= masterReset;
logic_analyzer(1) <= newClock -- 10Khz Clock;
logic_analyzer(2) <= outputZ;
--FSM States
logic_analyzer(3) <= '1' when y = A ELSE '0';
logic_analyzer(4) <= '1' when y = B ELSE '0';
logic_analyzer(5) <= '1' when y = C ELSE '0';
logic_analyzer(6) <= '1' when y = D ELSE '0';
logic_analyzer(7) <= '1' when y = E ELSE '0';
If anyone could direct to what I am doing wrong on the test bench and how to replicate to get similar results as the first image as it shows that in simulation, it always stays at state A and the new clock is not toggling meaning that clk100mhz is somehow not connected but I can't figure out why.
Any help is greatly appreciated, thanks guys
edit:
I wrote a simple program to test my scalar clock
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity scaler_clk is
Port (
pushButton : in std_logic;
indicator : out std_logic;
clk100mhz : in STD_LOGIC;
clk10khz: out STD_LOGIC
);
end scaler_clk;
architecture Behavioral of scaler_clk is
signal clockScalers : std_logic_vector (12 downto 0):= (others => '0') ;
signal prescaler: std_logic_vector(12 downto 0) := "1001110001000";
signal newClock: std_logic := '0';
signal masterReset : std_logic;
begin
clk10khz <= newClock;
masterReset <= pushButton;
process (clk100mhz,masterReset) begin
if(masterReset <= '1') then <--- error occurs here
clockScalers <= "0000000000000";
newClock <= '0';
indicator <= '1';
elsif (clk100mhz'event and clk100mhz = '1')then
indicator <= '0';
clockScalers <= clockScalers + 1;
if(clockScalers > prescaler) then
newClock <= not newClock;
clockScalers <= (others => '0');
end if;
end if;
end process;
end Behavioral;
test bench code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity test_scaler_clk is
-- Port ( );
end test_scaler_clk;
architecture Behavioral of test_scaler_clk is
component scaler_clk Port (
pushButton : in std_logic;
indicator : out std_logic;
--input clock
clk100mhz : in STD_LOGIC;
clk10khz: out STD_LOGIC
);end component;
signal clk100mhz: std_logic := '0';
signal clk10khz : std_logic;
signal pushButton: std_logic;
signal indicator : std_logic;
begin
uut: scaler_clk port map(
pushButton => pushButton,
indicator => indicator,
clk100mhz => clk100mhz,
clk10khz => clk10khz
);
pushButton <= '0';
clock_tic: process begin
loop
clk100mhz <= '0';
wait for 5ns;
clk100mhz <= '1';
wait for 5ns;
end loop;
end process;
end Behavioral;
Even though I set pushButton to '0', it is still triggering masterReset, anyone knows why, that's why the 10 kHz clock isn't working
There are several things that you could (should) improve in your code. As Brian already explained, in your Behavioral architecture of scaler_clk, you should have:
if(masterReset = '1') then
instead of:
if(masterReset <= '1') then
Now, let's start with the most likely cause of your initial problem: unbound components. Your test benches instantiate the design to validate as components. VHDL components are kind of prototypes of actual entities. Prototypes are enough to compile because the compiler can perform all necessary syntax and type checking. But they are not enough to simulate because the simulator also needs the implementation behind the prototype. Some tools have a default binding strategy for unbound components: if they find an entity with the same name and if it has only one architecture, they use that. Your simulator apparently does not use such strategy (at least not by default, there is maybe an option for that but it is disabled). Note that most simulators I know issue warnings when they find unbound components. You probably missed these warnings.
Anyway, your component instances are unbound (they have no associated entity/architecture) and the simulator considers them as black boxes. Their outputs are not driven, except by the initial values you declared (1).
How to fix this? Two options:
Use a configuration to specify which entity/architecture pair shall be used for each component instance:
for all: scaler_clk use entity work.scaler_clk(Behavioral);
Use entity instantiations instead of components:
uut: entity work.scaler_clk(Behavioral) port map...
Now, let's go through some other aspects of your code that could be improved:
You are using non-standard packages, that are frequently not even compatible: IEEE.STD_LOGIC_ARITH and IEEE.STD_LOGIC_UNSIGNED. As they are not standard they should not even be in the standard IEEE library. You should use IEEE.NUMERIC_STD instead, and only that one. It declares the SIGNED and UNSIGNED types (with the same declaration as STD_LOGIC_VECTOR) and overloads the arithmetic operators on them.
Your test benches generate the 100MHz clock with:
clock_tic: process begin
loop
clk100mhz <= '0';
wait for 5ns;
clk100mhz <= '1';
wait for 5ns;
end loop;
end process;
The infinite loop is useless: a process is already an infinite loop:
clock_tic: process
begin
clk100mhz <= '0';
wait for 5ns;
clk100mhz <= '1';
wait for 5ns;
end process clock_tic;
would do the same. Same remark for your input_changes process.
Your input_changes process uses wait for <duration> statements. This is not a good idea because you do not know when the inputSignal signal toggles, compared to the clock. Is it just before, just after or exactly at the same time as the rising edge of clk100mhz? And if it is exactly at the same time, what will happen? Of course, you can carefully chose the <durations> to avoid such ambiguities but it is error prone. You should use the wait for <duration> only in the clock generating process. Everywhere else, it is better to synchronize with the clock:
input_changes: process
begin
inputSignal <= '0';
for i in 1 to 10000 loop
wait until rising_edge(clk100mhz);
end loop;
inputSignal <= '1';
for i in 1 to 10000 loop
wait until rising_edge(clk100mhz);
end loop;
inputSignal <= '1';
for i in 1 to 10000 loop
wait until rising_edge(clk100mhz);
end loop;
inputSignal <= '1';
for i in 1 to 10000 loop
wait until rising_edge(clk100mhz);
end loop;
end process input_changes;
This guarantees that inputSignal changes just after the rising edge of the clock. And you could rewrite it in a bit more elegant way (and probably a bit easier to maintain):
input_changes: process
constant values: std_logic_vector(0 to 3) := "0111";
begin
for i in values'range loop
inputSignal <= values(i);
for i in 1 to 10000 loop
wait until rising_edge(clk100mhz);
end loop;
end loop;
end process input_changes;
You are using resolved types (STD_LOGIC and STD_LOGIC_VECTOR). These types allow multiple drive, that is, having a hardware wire (VHDL signal) that is driven by several devices (VHDL processes). Usually you do not want this. Usually you even want to avoid this like the plague because it can cause short-circuits. In most cases it is wiser to use non-resolved types (STD_ULOGIC and STD_ULOGIC_VECTOR) because the compiler and/or the simulator will raise errors if you accidentally create a short circuit in your design.
One last thing: if, as its name suggests, you intend to use the clk10khz signal as a real clock, you should reconsider this decision. It is a signal that you generate with your custom logic. Clocks have very specific electrical and timing constraints that cannot really be fulfilled by regular signals. Before using clk10khz as a clock you must deal with clock skew, clock buffering... Not impossible but tricky. If you did use it as a clock your synthesizer probably issued critical warnings that you also missed (have a look maybe at the timing report). Moreover, this is probably useless in your case: an enable signal generated from clk100mhz could probably be used instead, avoiding all these problems. Instead of:
process (clk100mhz,masterReset) begin
if(masterReset = '1') then
clockScalers <= "0000000000000";
newClock <= '0';
indicator <= '1';
elsif (clk100mhz'event and clk100mhz = '1')then
indicator <= '0';
clockScalers <= clockScalers + 1;
if(clockScalers > prescaler) then
newClock <= not newClock;
clockScalers <= (others => '0');
end if;
end if;
end process;
use:
signal tick10khz: std_ulogic;
...
process(clk100mhz, masterReset) begin
if masterReset = '1') then
clockScalers <= "0000000000000";
tick10khz <= '0';
elsif rising_edge(clk100mhz) then
clockScalers <= clockScalers + 1;
tick10khz <= '0'
if(clockScalers > prescaler) then
tick10khz <= '1';
clockScalers <= (others => '0');
end if;
end if;
end process;
And then, instead of:
process(clk10khz)
begin
if rising_edge(clk10khz) then
register <= register_input;
end if;
end process;
use:
process(clk100mhz)
begin
if rising_edge(clk100mhz) then
if tick10khz = '1' then
register <= register_input;
end if;
end if;
end process;
The result will be the same but with only one single 100MHz clock, which avoids clock skew, clock buffering and clock domain crossing problems.
(1) This illustrates why declaring variables and signals with initial values is usually not a good idea: it hides potential problems. Without this your signals would have been stuck at 'U' (uninitialized) and it would maybe have helped understanding where the problem comes from.

D-latch with both asynchro and synchro resetting in VHDL

I have to implement a D-latch that follows asynchronnous resetting when aclrn=0 and synchronnous when sclrn=0. The implementation should be able to follow both methods of resetting.
Here's what I came up with in VHDL (I only include the process) based on basic D-latches.
process(aclrn,clock)
begin
if (aclrn='0') then
q <= '0';
elsif (rising_edge(clock)) then
if (sclrn='0') then
q <= '0';
else
q <= d;
end if;
end if;
end process;
where
clock, d, aclrn, sclrn : in std_logic; q : out std_logic
Am I correct that the process doesn't need to take in sclrn as an argument, but only aclrn and clock? Are there any other inconsistencies?
Thank you in advance.
You say D-latch but coded flipflop. Do you really need a D-latch or you are just using latch instead of register carelessly?
if you really need a flipflop, you have done it right.
You have put aclrn and clock in sensitivity list which is right. You don't need to put sclrn in list because it is synchronous.
Xilinx XST tutorial example for Flip-Flop With Positive-Edge Clock and Synchronous Set
architecture archi of registers_3 is
begin
process (C)
begin
if (C'event and C='1') then
if (S='1') then
Q <= '1';
else
Q <= D;
end if;
end if;
end process;
end archi;
and XST coding example for Flip-Flop With Positive-Edge Clock and Asynchronous Reset
architecture archi of registers_2 is
begin
process (C, CLR)
begin
if (CLR = '1')then
Q <= '0';
elsif (C'event and C='1')then
Q <= D;
end if;
end process;
end archi;
By mixing these two you get your answer. I see nothing wrong with your code. best way to know if you've code what you are asked is to simulate it.
If you need latch, notice that latches are sensitive to levels instead of edges. this is an example of LATCH with positive gate and async reset
architecture archi of latches_2 is
begin
process (CLR, D, G)
begin
if (CLR='1') then
Q <= '0';
elsif (G='1') then
Q <= D;
end if;
end process;
end archi;

Xilinx / ISim seem claims value to be X but it has been declared

Have JUST started learning how to use this tool so if my question seems silly i apologize in advance. I have searched the error in numerous forums (already answered posts , not mine) and couldn't understand what i was doing wrong so here is my question:
My Behavioral Code:
----------------------------------------------------------------------------- -----
-- Company:
-- Engineer:
--
-- Create Date: 01:47:22 07/07/2015
-- Design Name:
-- Module Name: Module_1 - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------- -----
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned valuessss
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity Module_1 is
port (A,B,WE,reset : in std_logic;
clk : in std_logic;
DIN : in signed(3 downto 0);
FULL,EMPTY,ERROR : out std_logic:= '0';
PARKFREE : out signed(3 downto 0)
);
end Module_1;
architecture Behavioral of Module_1 is
signal current_state,next_state:std_ulogic_vector(1 downto 0);
signal empty_bf, full_bf :std_ulogic;
signal enter, reset_b : std_ulogic := '0' ;
constant s0: std_ulogic_vector (1 downto 0):="00";
constant s1: std_ulogic_vector (1 downto 0):="10";
constant s2: std_ulogic_vector (1 downto 0):="11";
constant s3: std_ulogic_vector (1 downto 0):="01";
signal park_counter,buffr: signed(3 downto 0):="0000";
signal PARKTOTAL,free_park_counter: signed(3 downto 0):= "1111";
begin
p1: process (clk,reset,reset_b)
begin
if (reset = '1') then
current_state <= s0;
elsif clk'event and clk = '1' then
current_state <= next_state;
end if;
end process p1;
p2: process (current_state,A,B)
begin
next_state <= current_state;
case current_state is
when s0 =>
if A = '1' then
enter <= '1';
next_state <= s1;
elsif B = '1' then
next_state <= s3;
end if;
when s1 =>
if A = '0' then
enter <= '0';
next_state <= s0;
elsif B = '1' then
next_state <= s2;
end if;
when s2 =>
if A = '0' then
next_state <= s3;
elsif B = '0' then
next_state <= s1;
end if;
when s3 =>
if B = '0' then
enter <= '0';
next_state <= s0;
elsif A = '1' then
next_state <= s2;
end if;
when others =>
end case;
end process p2;
p3: process(current_state,A,B)
begin
case current_state is
when s1 =>
if enter = '0' and A = '0' and empty_bf = '0' then
park_counter <= park_counter - 1;
free_park_counter <= free_park_counter + 1;
ERROR <= '0';
end if;
when s3 =>
if enter = '1' and B = '0' and full_bf = '0' then
park_counter <= park_counter + 1;
free_park_counter <= free_park_counter - 1;
ERROR <= '0';
end if;
when others =>
end case;
end process p3;
max: process(WE)
begin
if clk'event and clk = '1' and WE = '1' then
PARKTOTAL <= DIN ;
buffr <= DIN ;
if (free_park_counter < buffr - park_counter) then
ERROR <= '1';
reset_b <= '1';
else free_park_counter <= buffr - park_counter;
end if;
end if;
end process max;
incr: process(free_park_counter,DIN)
begin
PARKFREE <= free_park_counter;
if (free_park_counter = 15) then
EMPTY <= '1';
empty_bf <= '1';
else EMPTY <= '0';
empty_bf <= '0';
end if;
if (free_park_counter = 0) then
FULL <= '1';
full_bf <= '1';
else FULL <= '0';
full_bf <= '0';
end if;
end process incr;
end Behavioral;
My Testbench
----------------------------------------------------------------------------- ---
-- Company:
-- Engineer:
--
-- Create Date: 02:17:07 07/11/2015
-- Design Name:
-- Module Name: D:/Users/ErgasiaFPGA/Testbench.vhd
-- Project Name: ErgasiaFPGA
-- Target Device:
-- Tool versions:
-- Description:
--
-- VHDL Test Bench Created by ISE for module: Module_1
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
-- Notes:
-- This testbench has been automatically generated using types std_logic and
-- std_logic_vector for the ports of the unit under test. Xilinx recommends
-- that these types always be used for the top-level I/O of a design in order
-- to guarantee that the testbench will bind correctly to the post-implementation
-- simulation model.
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY Testbench IS
END Testbench;
ARCHITECTURE behavior OF Testbench IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT Module_1
PORT(
A : IN std_logic;
B : IN std_logic;
WE : IN std_logic;
reset : IN std_logic;
clk : IN std_logic;
DIN : IN signed(3 downto 0);
FULL : OUT std_logic;
EMPTY : OUT std_logic;
ERROR : OUT std_logic;
PARKFREE : OUT signed(3 downto 0)
);
END COMPONENT;
--Inputs
signal A : std_logic := '0';
signal B : std_logic := '0';
signal WE : std_logic := '0';
signal reset : std_logic := '0';
signal clk : std_logic := '0';
signal DIN : signed(3 downto 0) := (others => '0');
--Outputs
signal FULL : std_logic;
signal EMPTY : std_logic;
signal ERROR : std_logic;
signal PARKFREE : signed(3 downto 0);
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: Module_1 PORT MAP (
A => A,
B => B,
WE => WE,
reset => reset,
clk => clk,
DIN => DIN,
FULL => FULL,
EMPTY => EMPTY,
ERROR => ERROR,
PARKFREE => PARKFREE
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
reset <= '1' ;
wait for 100 ns;
reset <= '0' ;
wait for clk_period*10;
-- insert stimulus here
A <= '1' ;
wait for clk_period*5;
B <= '1' ;
wait for clk_period*5;
A <= '0' ;
wait for clk_period*5;
B <= '0' ;
wait for clk_period*5;
B <= '1' ;
wait for clk_period*5;
A <= '1' ;
wait for clk_period*5;
B <= '0' ;
wait for clk_period*5;
A <= '0' ;
wait;
end process;
END;
I posted the whole code just in case i'm missing something in some part of it that i wouldn't think about. So , when i ISim it , with any "succesful" trigger of p3...
Referencing it again here:
p3: process(current_state,A,B)
begin
case current_state is
when s1 =>
if enter = '0' and A = '0' and empty_bf = '0' then
park_counter <= park_counter - 1;
free_park_counter <= free_park_counter + 1;
ERROR <= '0';
end if;
when s3 =>
if enter = '1' and B = '0' and full_bf = '0' then
park_counter <= park_counter + 1;
free_park_counter <= free_park_counter - 1;
ERROR <= '0';
end if;
when others =>
end case;
end process p3;
...the ISim says that in this part
"There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)."
and proceeds to make Xs of some of the values after that part , although all of the signals have been initialized (at least the ones in this part)
The "park_counter <= park_counter + 1;" part works correctly in the simulation but the "free_park_counter <= free_park_counter -1;" doesn't. This completely baffles me as they are declared as the same type and are both initialized the same way , even with different values.
So what am i missing or even doing blatantly wrong? Any help will be incredibly appreciated. Only looking for the error , if you could please contain optimizations since i'm looking to learn through trial and error and thought and would like to struggle to make it better myself
In addition , please be patient with my responses since i log on 2 to 3 times per day. Thanks in advance
Your design is non-workable per Brian's answer. Your testbench causes the messages when going from s3 or s1 to s0 before the clock edge. free_park_counter goes to 'U's. (Once it gets U's it won't loop further, no events occur without a signal value change).
Your counters should be clocked to prevent combinatorial looping, plus they likely won't synthesize a clock usefully due to uneven combinatorial delays. Sensitivity lists should likewise be complete, if for no other reason than the intent is to make simulation match the synthesized result.
Looking at the result of your testbench:
(clickable)
We can compare that with the messages from the arithmetic operators found in the Synopsys package std_logic_arith:
../../../src/synopsys/std_logic_arith.vhdl:315:20:#350ns:(assertion warning): There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
../../../src/synopsys/std_logic_arith.vhdl:315:20:#350ns:(assertion warning): There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
../../../src/synopsys/std_logic_arith.vhdl:315:20:#550ns:(assertion warning): There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
The signals displayed in the waveform are selected in order of importance and appearance a first pass selection and we immediately see we also get 'U's on free_park_counter as well as ERROR.
ERROR catches attention because you hadn't mentioned it previously. When asking 'where to the 'U' come from ?' it becomes apparent the issue is there are drivers on ERROR and free_park_counter in both processes p3 and max. The messages are a side effect.
Each process assigning a signal provides a driver. Signals with multiple drivers are either resolved or result in an error for non-resolved types.
The resolved value of free_park_counter with one or more elements having a metavalue will cause the diagnostic messages produced by package std_logic_arith. The 'U's in the waveform are caused by the resolution of the two drivers.
The difficulty your audience had in noticing the two drivers may be in part due to your strong insistence on focusing on process p3, which is not well specified. The title and focus of your question also seems a bit unclear. Without a Minimal Complete and Verifiable example there was also bound to be less scrutiny.
You might expect as a minimum to consolidate all the assignments to ERROR and free_park_counter into a single process. ERROR should likely be registered, and I'd expect something named park_counter would likely want to be registered, too.
There is some confusion in the question title : declaring a signal and setting its value are entirely separate.
Initialising a signal (in the declaration) will influence its value, but not fully determine it. If the initialisation and another driving value are different, the result probably will be 'X'. Likewise if the signal is driven from different processes which disagree on its value.
Now, you are using a multiple-process form of state machine, where the operations are split between clocked and combinational processes. These are recommended by more than one textbook. This is unfortunate because they are notoriously difficult to get right, and for example, a moment's inspection will show that the sensitivity list on process P3 is wrong.
Fixing P3's sensitivity list may not affect the problem, because P3 also drives its own inputs in what is known as a combinational loop. Consider that, if the process wakes up several times because of glitches on the combinational inputs in its sensitivity list, the additions will take place several times...
Rewriting these three processes in the form of a single clocked process P1, (which is, unfortunately, not well taught in several textbooks) will avoid all of these difficulties.
In ISim, if you browse the tree menu on the left you are able to add to then signals window any internal signal you want. Add all of them, rerun the simulation and look for the signals that have 'U'|'X'|'W'|'Z'|'-' values. This should give us a lead to track down the problem.
If you are really new to VHDL, this answer of mine should help you undersand some of the basic concepts of this description language :)
VHDL - iSIM output uninitialised, doesn't change states
Another advice that I learned the hard way, but you can think about it after we solved this problem: textbooks and even Xilinx describe how to implement finite state machines with two or even three distinct processes. This comes from an educational approach where FSM are splitted in synchronous logic and asynchronous logic. In practice, this is doing more harm than good: most of the FSM can be described with a single synchronous process. Google it (or if you are interested we can talk about it) and try it, you will get the hang of it really quickly and it will really simplify the code (you won't even need two separate signals for the states anymore!).

how to avoid delay in the output of simple process statement in VHDL

i am a beginner in VHDL. i want ot know why there is a delay of one cycle in the following code.and how to avoid it..at the same time in verilog the statement always #(posedge clk) dont have any delay.. how to do the same in VHDL
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity t_ff_s is
port ( T,S,CLK : in std_logic;
Q : out std_logic);
end t_ff_s;
-- entity
architecture my_t_ff_s of t_ff_s is
signal t_tmp : std_logic; -- intermediate signal declaration
begin
tff: process (S,rising_edge(clk))
begin
if (S = '0') then
t_tmp <= '1';
--elsif (rising_edge(CLK)) then
else
t_tmp <= T XOR t_tmp; -- temp output assignment
end if;
end process tff;
Q <= t_tmp; -- final output assignment
end my_t_ff_s;
Sensitivity lists in VHDL don't take an edge specification like in Verilog. VHDL is more flexible in that you can freely use the 'event signal attribute anywhere within a process to implement edge triggered behavior. You can mix level and edge sensitive logic without resorting to split blocks/processes or hacks like negedge for resets. Function calls like rising_edge(clk) (which implements a test for clk'event) are not permitted in a sensitivity list. It only contains signal names. Your code won't compile as is.
If some other syntactically correct version of your code compiles cleanly, the delays you see are artifacts of the simulation model or having a broken sensitivity list. If you want a synchronous clock driven process then you only need the clock signal and possibly an asynchronous reset in the sensitivity list.
Consider the following process:
tff: process(S, clk)
begin
if S = '0' then -- Asynchronous reset (level sensitive)
t_tmp <= '1';
elsif rising_edge(clk) then -- Synchronous logic (edge sensitive)
t_tmp <= T xor t_tmp;
end if;
end process;
Q <= t_tmp;
This process executes when an event occurs on S or clk. If S is '0' then the reset condition is executed with priority over the elsif clause (clk is a don't-care). The assignment to t_tmp takes effect on the next delta cycle which is still the same as the current simulation time. Otherwise, if rising_edge(clk) evaluates to true then an event occurred on clk and it's state changed from '0' (or 'L') to '1' (or 'H') indicating that the event was a rising edge. The synchronous assignment takes place and the new xored t_tmp takes effect on the next delta cycle. Changes in T don't cause the process to execute since it isn't (and shouldn't be) in the sensitivity list.
Because there is no unconditional else clause the t_tmp signal retains its last assigned value if both of the two if conditions are false. It will change the next time there is an event on S or clk that causes a new assignment to t_tmp. This will either be the next clock edge or a re-application of asynchronous reset.
The assignment to Q is continuous and is effectively the same as a process with t_tmp in its sensitivity list. As a consequence, the assignment to Q takes place a delta cycle after events on t_tmp which is two delta cycles after the rising edge. If Q is feeding into logic that updates earlier than the second delta cycle of an edge, it will appear to take an extra clock cycle for it to propagate.
The behavior surrounding delta cycles can sometimes create confusing results when inspecting waveforms. You may have a rising edge that should capture a data input that appears to transition simultaneously on the same time step when, in fact, the data is transitioning on a later delta cycle and will only be captured on the next clock edge.
Similarly, if you construct a simple gated clock without any time delay, its edges will occur at the same time but on later delta cycles than the ungated version of the clock. Data driven from the "earlier" ungated clock will be captured by the gated logic a clock cycle earlier than expected as a result. Data driven the other direction will appear to have an unexpected delay by a clock cycle.
It isn't clear what is causing the problem you see without more information on how you're driving the S, T, and clk signals but it is likely connected to the delta cycle behavior of the simulation engine in some way.
The problem
A little more succinctly than Kevin, rising_edge is an expression and not a signal, a sensitivity list requires a named signal, a transaction on which you resume execution of a suspended process. Put the elsif back in and have only S and clk in the sensitivity list.
Note that because t_tmp isn't in the sensitivity list, you won't see Q follow t_tmp until the next clock event causing the delay you noted.
The fixed syntax process:
tff: process (S,clk) -- was (S, risingedge(CLK)), a syntax error)
begin
if (S = '0') then
t_tmp <= '1';
elsif (rising_edge(CLK)) then -- put back
-- else
t_tmp <= T XOR t_tmp; -- temp output assignment
end if;
Q <= t_tmp; -- final output assignment
end process tff;
Which shows the delay between t_tmp and Q:
(clickable)
Fix it by making Q a concurrent signal assignment
To cure the half clock delay you could make the assignment to Q a concurrent signal assignment statement (move it outside of the process).
tff:
process (S, clk)
begin
if S = '0' then
t_tmp <= '1';
elsif rising_edge(clk) then
t_tmp <= T xor t_tmp;
end if;
end process;
Q <= t_tmp; -- concurrent signal assignment
Which gives:
(clickable)
And you can see above that t_tmp and Q are now in phase.
Fix it by making t_tmp a variable
You could also declare t_tmp as a variable in process dff instead of a signal and switching assignments to it as variable assignments will also cure the one clock delay between t_tmp and Q.
tff:
process (S, clk)
variable t_tmp: std_logic;
begin
if S = '0' then
t_tmp := '1';
elsif rising_edge(clk) then
t_tmp := T xor t_tmp;
end if;
Q <= t_tmp;
end process;
Which shows:
(clickable)
And ghdl using gtkwave doesn't output variables or show delta cycles. You can see Q occurs on the rising edge of the clock.
Making t_tmp a variable also has the effect of eliminating a delta cycle between a transaction on t_tmp and a transaction on Q.
Eliminating delta cycles makes your model execute faster (while occurring at the current simulation time). Signal assignments don't take effect while any process is executing and variable assignments take effect immediately.
Fix it by adding t_tmp to the sensitivity list
And alternatively you could just add t_tmp to the sensitivity list (along with S and clk).
tff:
process (S, clk, t_tmp)
begin
if S = '0' then
t_tmp <= '1';
elsif rising_edge(clk) then
t_tmp <= T xor t_tmp;
end if;
Q <= t_tmp;
end process;
(clickable)
And this is slower than all the rest of the fixes because the if statement is executed each time t_tmp has an event as well as S or CLK. rising_edge is a function call which dynamically elaborates it's interface list, a significant simulator performance penalty particularly if you use a lot of these primitives.
These were done with a test bench:
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity t_ff_s is
port ( T,S,CLK : in std_logic;
Q : out std_logic);
end entity t_ff_s;
architecture my_t_ff_s of t_ff_s is
signal t_tmp : std_logic; -- intermediate signal declaration
begin
tff: process (S,clk) -- was (S, risingedge(CLK)), a syntax error)
begin
if (S = '0') then
t_tmp <= '1';
elsif (rising_edge(CLK)) then -- put back
-- else
t_tmp <= T XOR t_tmp; -- temp output assignment
end if;
Q <= t_tmp; -- final output assignment
end process tff;
end my_t_ff_s;
architecture foe of t_ff_s is
signal t_tmp: std_logic;
begin
tff:
process (S, clk)
begin
if S = '0' then
t_tmp <= '1';
elsif rising_edge(clk) then
t_tmp <= T xor t_tmp;
end if;
end process;
Q <= t_tmp; -- concurrent signal assignment
end architecture;
architecture fie of t_ff_s is
begin
tff:
process (S, clk)
variable t_tmp: std_logic;
begin
if S = '0' then
t_tmp := '1';
elsif rising_edge(clk) then
t_tmp := T xor t_tmp;
end if;
Q <= t_tmp;
end process;
end architecture;
architecture fee of t_ff_s is
signal t_tmp: std_logic;
begin
tff:
process (S, clk, t_tmp)
begin
if S = '0' then
t_tmp <= '1';
elsif rising_edge(clk) then
t_tmp <= T xor t_tmp;
end if;
Q <= t_tmp;
end process;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
entity test_tff is
end entity;
architecture foo of test_tff is
signal CLK: std_logic := '0';
signal T: std_logic := '0';
signal S: std_logic := '0';
signal Q: std_logic;
component t_ff_s is
port (
signal CLK: in std_logic;
signal T: in std_logic;
signal S: in std_logic;
signal Q: out std_logic
);
end component;
begin
DUT:
t_ff_s
port map (
T => T,
S => S,
CLK => CLK,
Q => Q
);
CLOCK:
process
begin
wait for 10 ns;
CLK <= not CLK;
if Now > 250 ns then
wait;
end if;
end process;
SET:
process
begin
S <= '0';
wait for 20 ns;
S <= '1';
wait;
end process;
TOGGLE:
process
begin
wait for 20 ns;
T <= '1';
wait for 60 ns;
T <= '0';
wait for 40 ns;
T <= '1';
wait;
end process;
end architecture;
configuration my_t_ff_s_config of test_tff is
for foo
for DUT: t_ff_s
use entity work.t_ff_s(my_t_ff_s);
end for;
end for;
end configuration;
configuration concurrent_config of test_tff is
for foo
for DUT: t_ff_s
use entity work.t_ff_s(foe);
end for;
end for;
end configuration;
configuration variable_config of test_tff is
for foo
for DUT: t_ff_s
use entity work.t_ff_s(fie);
end for;
end for;
end configuration;
configuration sensitivity_config of test_tff is
for foo
for DUT: t_ff_s
use entity work.t_ff_s(fee);
end for;
end for;
end configuration;
note the use of configuration
Using VHDL's configuration declarations to allow the use of multiple architectures. (my_t_ff_s - the original, foe - with concurrent assignment to Q, fie - with t_tmp as a variable and fee - with t_tmp in the sensitivity list).
And amazingly enough ghdl's analyzer was quite helpful getting the configuration declarations syntax right. Once you get the first one, the others are easy.
We tend to get rusty using configuration, it wasn't generally supported historically by synthesis tools. But then again, this is simulation for verification.
And for those with ghdl and gtkwave this is how it was done:
ghdl -a t_ff.vhdl
ghdl -e my_t_ff_s_config
ghdl -e concurrent_config
ghdl -e concurrent_config
ghdl -e sensitivity_config
ghdl -r my_t_ff_s_config --wave=test_tff_my_t_ff_s.ghw
ghdl -r concurrent_config --wave=test_tff_foe.ghw
ghdl -r variable_config --wave=test_tff_fie.ghw
ghdl -r sensitivity_config --wave=test_tff_fee.ghw
GHW is ghdl's native waveform dump file format, understood by gtkwave.
In gtkwave:
open t_ff_s.gtkw (reads in test_tff_my_t_ff_s.ghw)
(otherwise read in test_tff_my_t_ff_s.ghw and add signals to
waveform display, format the window, save save file to t_ff_s.gtkw)
new tab open test_tff_foe.ghw
read save file open t_ff_s.gtkw
new tab open test_tff_fie.ghw
read save file open t_ff_s.gtkw
new tab open test_tff_fee.ghw
read save file open t_ff_s.gtkw
Note ghdl doesn't save variable state or delta cycles, t_tmp won't show up in the waveform for test_ff_fie.ghw.

VHDL variable check in clk cycle

I am trying to compare two values in a clk cycle
eg:
if(riding_edge(clk)) then
if (some signal = other) then
other<=other+1;
else other<=other;
if(other=3)then
flag=1;
end if;
end if;
The code compiles and runs fine but when I am seeing the simulation window, the flag gets set no matter what is the value of other. Am I doing something wrong or the value of other is fluctuating.
The above is a pseudo code and everything is correct syntactically.
Please Help
Thanks in advance
Without a minimal working example, I could only guess that you're inferring a latch by not specifying what happens to flag when other is not 3. To prevent this, you would specify all cases of any decision tree.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY example IS
PORT (some_signal : IN STD_LOGIC;
other : IN STD_LOGIC;
clk : IN STD_LOGIC;
flag : OUT STD_LOGIC;
);
END example;
ARCHITECTURE minimal OF example IS
BEGIN
minexample:PROCESS(clk)
BEGIN
IF (clk'EVENT and clk='1') THEN
IF some_signal = other THEN
other <= other + '1';
ELSE other <= other;
END IF;
IF(other = '1') THEN
flag <= '1';
ELSE flag <= '0'; -- always specify all cases
END IF;
END IF;
END PROCESS minexample;
END minimal;
I use the code of N8TRO and add an reset to set the signal to zero at the startup and change the signal other to integer (because you like to check on the value 3) and check on rising_edge (should be the better way).
Now the signal flag should raise to high after 4 clocks after the Reset is set to low. Is this the behavior you expect?
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY example IS
PORT (some_signal : IN STD_LOGIC;
other : IN integer range 0 to 3; --this should be an integer 2 bit widht
clk : IN STD_LOGIC;
reset : IN STD_LOGIC;
flag : OUT STD_LOGIC;
);
END example;
ARCHITECTURE minimal OF example IS
BEGIN
minexample:PROCESS(clk,reset)
BEGIN
IF (reset = '1') then --i think a reset is a good idea
flag <= '0';
other <= 0;
ELSIF (rising_edge(clk)) THEN
IF some_signal = other THEN
other <= other + 1;
ELSE
other <= other;
END IF;
IF(other = 3) THEN --other is now an integer, so you can check on 3
flag <= '1';
ELSE
flag <= '0'; -- always specify all cases
END IF;
END IF;
END PROCESS minexample;
END minimal;

Resources