Entity has no architecture problem in Modelsim - vhdl

I'm new to FPGA design using VHDL and I'm stucked in a problem of testbench simulation: each time I try to simulate my model (which testbench was given by the testbench writer) I get the following error that's driving me crazy:
Error: (vsim-3173) Entity >'C:/intelFPGA_lite/progetto_dsp/simulation/modelsim/rtl_work.progetto_dsp_top_vhd_t>st' has no architecture.
My model is a simple Phase Frequency Detector (PFD) and all I'd like is to simulate its behavior at different input signals.
Following I post my testbench code, the only thing that I changed from the auto-generated code is the addition of the A and B signals (which I made like clock signals with different frequency).
-- Generated on "05/02/2021 16:58:30"
-- Vhdl Test Bench template for design : progetto_dsp_top
--
-- Simulation tool : ModelSim-Altera (VHDL)
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY progetto_dsp_top_vhd_tst IS
END progetto_dsp_top_vhd_tst;
ARCHITECTURE progetto_dsp_top_arch OF progetto_dsp_top_vhd_tst IS
-- constants
constant period_A : time := 10 ps;
constant period_B : time := 20 ps;
-- signals
SIGNAL A : STD_LOGIC := '0';
SIGNAL B : STD_LOGIC := '0';
SIGNAL High : STD_LOGIC : '1';
SIGNAL QA : STD_LOGIC;
SIGNAL QB : STD_LOGIC;
COMPONENT progetto_dsp_top
PORT (
A : IN STD_LOGIC;
B : IN STD_LOGIC;
High : IN STD_LOGIC;
QA : OUT STD_LOGIC;
QB : OUT STD_LOGIC
);
END COMPONENT;
BEGIN
--signal A generation
process
begin
A <= '1';
wait for period_A/2;
A <= '0';
wait for period_A/2;
if end_sim_s = true then
wait; -- end of simulation
end if;
end process;
signal B generation
process
begin
B <= '1';
wait for period_B/2;
B <= '0';
wait for period_B/2;
if end_sim_s = true then
wait; -- end of simulation
end if;
end process;
i1 : progetto_dsp_top
PORT MAP (
-- list connections between master ports and signals
A => A,
B => B,
High => High,
QA => QA,
QB => QB
);
init : PROCESS
-- variable declarations
BEGIN
-- code that executes only once
WAIT;
END PROCESS init;
always : PROCESS
-- optional sensitivity list
-- ( )
-- variable declarations
BEGIN
-- code executes for every event on sensitivity list
WAIT;
END PROCESS always;
END progetto_dsp_top_arch;

Related

Testbench for a reaction timer design VHDL

I have to test using modelsim this component:
COMPONENT part5
PORT ( CLOCK_50,KEY0,KEY3 : IN STD_LOGIC;
SW: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
HEX3,HEX2,HEX1,HEX0: OUT STD_LOGIC_VECTOR (6 DOWNTO 0);
LEDR : OUT STD_LOGIC_VECTOR (1 DOWNTO 0)
);
END COMPONENT;
It will be implemented on altera DE2.
It is supposed to work with the clock (CLOCK_50),after KEY0 goes to logic level 1, counting clock periods till it reach the numeber inserted on SW(7 DOWNTO 0),at this point it turns on a red led : LEDR. From the time LEDR is ON the four hexadecimal displays (HEX0, HEX1,HEX2 and HEX3) start to count at 1 ms interval. I have to push a button KEY3 (on the DE2 board) as quickly as possible till I reach the value rappresented in SW(7 DOWNTO 0) : the red light turns off and displays stop counting.
I tried with this:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;`
ENTITY tb_part5 IS
END ENTITY;
ARCHITECTURE beha OF tb_part5 IS
COMPONENT part5
PORT ( CLOCK_50,KEY0,KEY3 : IN STD_LOGIC;
SW: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
HEX3,HEX2,HEX1,HEX0: OUT STD_LOGIC_VECTOR (6 DOWNTO 0);
LEDR : OUT STD_LOGIC_VECTOR (1 DOWNTO 0)
);
END COMPONENT;
SIGNAL clk,key,rst: STD_LOGIC:='0';--inputs
SIGNAL switch: STD_LOGIC_VECTOR (7 DOWNTO 0);
SIGNAL led,led1: STD_LOGIC;--outputs
SIGNAL dec0,dec1,dec2,dec3 : STD_LOGIC_VECTOR (6 DOWNTO 0);
BEGIN
switch<="00001010";
PROCESS --clock
BEGIN
clk<='1' AFTER 10 ns ;
clk<='0' AFTER 20 ns ;
END PROCESS;
PROCESS --reset
BEGIN
rst<='0';
WAIT FOR 20 ns;
rst<='1';
WAIT;
END PROCESS;
PROCESS
BEGIN
IF led='1' THEN
key<= '1';
WAIT FOR 20 ns;
key<='0';
WAIT FOR 20 ns;
ELSE
key<='0';
END IF;
END PROCESS;
DUT : part5 PORT MAP (CLOCK_50=>clk, KEY0=>rst,KEY3=>key,SW=>switch,HEX3=>dec3,HEX2=>dec2,HEX1=>dec1,HEX0=>dec0,LEDR(0)=>led,LEDR(1)=>led1);
END beha;
But the simulation don't show any results. I'm not very good at testbenches, I really want to understand how they works, specially with the generation of the clock, and insertion of wave vectors! Maybe I've could explain my doubts better, but if someone could show me a testbench example for beginners it would be very helpful!
Thanks
A beginners architecture for test bench can be really simple. You can test a lot of components with just 5 process (including clk and reset process). When you create a test bench you will usually generate at least one clock and a reset for your design under test (DUT). For those process you can keep the following and this should work for all single clock design (does not matter if reset is synchronous or asynchronous). Then you will create a stimulus process. This process will allow you to generate data for your DUT (you will affect signals connected to your DUT). This process can define the end of your simulation. You can set some signals and wait for 100000 ns if you want to test a sequence without modify signals (DUT inputs).
After generate stimulus you can launch simulation and manually verify your DUT outputs but this in not the best way to do (maybe in your case but not in a bigger design). The easiest way to control the integrity of your outputs is to generate a reference. This reference is the expected reaction of your design. E.g : if you want to realize a design that wait 100 clock cycles. You will create a reference signal of the output but you do not have to use VHDL that you can synthesize. You have access to all VHDL function (wait for, wait until, etc...).
At the end you will have the last process, the checker. This one will compare dut outputs and reference to define if there is some errors or not in your design.
Do not forget to put a wait statement in all process (depending on end_sim_s per exemple) to stop your simulation when everthing has been simulated
Here is an empty test bench structure :
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity tb_part5 is
port (
-- no IO for test bench
);
end entity;
architecture beha of tb_part5 is
---------------
-- Constants --
---------------
constant CLOCK_PERIOD : time := 10 ns; -- e.g.
------------------------
-- Test bench signals --
------------------------
signal clk_sti : std_logic := '0';
signal rst_sti : std_logic := '1'; -- !!! activ high !!!
-- end of sim flag
signal end_sim_s : boolean := false;
begin
----------------------
-- Clock generation --
----------------------
process
begin
clk_sti <= '1';
wait for CLOCK_PERIOD/2;
clk_sti <= '0';
wait for CLOCK_PERIOD/2;
if end_sim_s = true then
wait; -- end of simulation
end if;
end process;
--------------------
-- Reset sequence --
--------------------
process
begin
rst <= '1';
wait for 2*CLOCK_PERIOD;
rst <= '0';
wait;
end process;
----------------------
-- Stimulus process --
----------------------
process
begin
-- default values for DUT inputs
-- wait end of reset sequence
wait until (rst_sti = '0');
-- do something
-- end of simulation
end_sim_s <= true;
wait;
end process;
-----------------------
-- Reference process --
-----------------------
-------------------
-- Check process --
-------------------
-----------------------
-- DUT instanciation --
-----------------------
end beha;
For your test bench I propose you the following architecture. But you have to be conscious your test bench does not verify anything.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity tb_part5 is
port (
-- no IO in test bench
);
end entity;
architecture beha of tb_part5 is
---------------
-- Constants --
---------------
constant CLOCK_PERIOD : time := 10 ns; -- e.g.
-----------------------
-- Internals signals --
-----------------------
signal clk, key, rst : std_logic := '0'; --inputs
signal switch : std_logic_vector (7 downto 0);
signal led, led1 : std_logic; --outputs
signal dec0, dec1, dec2, dec3 : std_logic_vector (6 downto 0);
-- test bench signals
signal end_sim_s : boolean := false;
begin
switch <= "00001010";
----------------------
-- Clock generation --
----------------------
process
begin
clk <= '0';
wait for CLOCK_PERIOD/2;
clk <= '1';
wait for CLOCK_PERIOD/2;
if end_sim_s = true then
wait; -- end of simulation
end if;
end process;
--------------------
-- Reset sequence --
--------------------
process
begin
-- TIPS : if you want to be more efficient you should us a norm to
-- define your signal. A reset signal activ low can be called nRst for
-- exemple. Maybe actually you have an activ low reset but maybe not.
-- This exemple show a reset activ low sequence
rst <= '0';
wait for 2*CLOCK_PERIOD;
rst <= '1';
wait;
end process;
---------------------
-- Your TEST bench --
---------------------
-- this part do the same thing that you were asking.
process
begin
-- the if statement in the previous version is not a good thing to do.
-- in fact, you want your process to wait until an event.
-- initial state (default value)
key <= '0';
-- wait until the end of reset sequence (just in case)
wait until (rst = '1'); -- e.g.
-- wait until DUT assert led
wait until (led = '1'); -- e.g.
-- start your sequence
key <= '1';
wait for 20 ns;
key <= '0';
wait for 20 ns;
-- here you have 2 choices. let the process iterate a second time or just
-- end the simulation at this moment
-- stop here
-- notify the others process the end of simulation
end_sim_s <= true;
-- block process
wait;
end process;
-----------------------
-- DUT instanciation --
-----------------------
DUT : part5 port map (
CLOCK_50 => clk,
KEY0 => rst,
KEY3 => key,
SW => switch,
HEX3 => dec3,
HEX2 => dec2,
HEX1 => dec1,
HEX0 => dec0,
LEDR(0) => led,
LEDR(1) => led1
);
end beha;
Hope this will help you.
Regards.
Mike

Stop VHDL simulation with wait statements

When testing a simple counter implementation, the VHDL simulation is not exiting the simulation. My intention is to stop both concurrent processes using the shared variable changed by the main process. But the main process is not stopping the clock process.
My counter implementation is:
entity dff is
port(
direction, reset, clk, load : in std_logic;
din : in std_logic_vector(3 downto 0);
dout : out std_logic_vector(3 downto 0));
end dff;
architecture behav of dff is
signal temp : std_logic_vector(3 downto 0);
begin
process(clk, reset)
begin
if (reset='1') then
temp <= "0000";
elsif rising_edge(clk) then
if (load='1') then
temp <= din;
else
if (direction='0') then
temp <= std_logic_vector(unsigned(temp) + 1);
else
temp <= std_logic_vector(unsigned(temp) - 1);
end if;
end if;
end if;
dout <= temp;
end process;
end behav;
And my testbench:
architecture behav of test_tb is
component dff port(
direction, reset, clk, load : in std_logic;
din : in std_logic_vector(3 downto 0);
dout : out std_logic_vector(3 downto 0));
end component;
signal direction, reset, clk, load : std_logic := '1';
signal din, dout : std_logic_vector(3 downto 0) := x"7";
shared variable simend : boolean := false;
begin
clkk : process
begin
if simend=false then
clk <= not clk after 50 ns;
else
wait;
end if;
end process clkk;
uut : dff port map(
direction, reset, clk, load, din, dout);
stim : process
begin
reset <= '0';
wait for 1 us;
load <= '0';
wait for 2 us;
direction <= '0';
wait for 2 us;
load <= '1';
wait for 1 us;
reset <= '1';
wait for 0.5 us;
simend := true;
wait;
end process stim;
end behav;
An alternative way to end the simulation if you have a VHDL2008-compliant simulator is to:
use std.env.stop;
you can then end the simulation by calling stop:
stop;
This seems to me to be more elegant than waiting for a lack of clock transitions to cause the simulator iteration limit to be reached.
I would code your clock generator more like this:
clkk : process
begin
while simend=false loop
clk <= not clk;
wait for 50 ns;
end loop;
wait;
end process clkk;
It is possible to execute your clkk process without ever executing a wait statement. (The line clk <= not clk after 50 ns does not wait or block - <= is a non-blocking assignment.) Therefore, you have an infinite loop that will never stop. You can see this by running this example on EDA Playground where the simulation time never advances and, because the maximum runtime on EDA Playground is 1 minute, times out after 1 minute.
Also, I would recommend not using a shared variable for simend. Instead, why not use a signal? You code would not even be compiable in VHDL-2000 onwards, because after VHDL-2000, shared variables had to be protected types. You can see that a warning is produced on EDA Playground unless you set the option to compile VHDL-93. Compiling for VHDL-93, would prevent you using the stop (or finish) procedures.
I agree with #scary_jeff, std.env.stop is a great answer here. If I am just calling it in one place, my preference is to leave off the package reference and just call it:
std.env.stop;
In the event you are stuck with an older simulator, you can use
report "Just Kidding. Test Done." severity failure ;
OTOH if you need to coordinate ending a simulation between multiple processes and add a watch dog timer to your simulation run, you might consider the procedure Osvvm.TbUtilPkg.WaitForBarrier. It is used as shown below. The first call to WaitForBarrier(TestDone, 5 ms) will wake up in 5 ms in the event that TestDone does not happen before then and stop the simulation at that time.
signal TestDone : integer_barrier := 1 ;
ControlProc : process
begin
-- initialize test
SetAlertLogName("Uart1_Rx") ;
. . .
WaitForBarrier(TestDone, 5 ms) ; -- control process uses timeout
AlertIf(now >= 5 ms, "Test finished due to Time Out") ;
ReportAlerts ;
std.env.stop ;
end process ControlProc ;
CpuProc : process
begin
InitDut(. . . )_;
Toggle(CpuReady) ;
-- run numerous Cpu test transactions
. . .
WaitForBarrier(TestDone) ;
wait ;
end process CpuProc ;
UartTxProc : process
Begin
WaitForToggle(CpuReady) ;
-- run numerous Uart Transmit test transactions
. . .
WaitForBarrier(TestDone) ;
wait ;
end process UartTxProc ;
. . .
You can find the OSVVM library at both osvvm.org and on github. There is also a complete user guide in for this package in the download.

ISim shows U for all outputs

I have a simple VHDL design and test bench that does not produce the expected output. ISim shows 'U' for all the outputs until the 'running' state is achieved (myState='1'). Then they show 0 and X values. The first PROCESS block should set all outputs to '0' when ENABLE is '0'. The test bench toggles ENABLE 0-1-0 to insure an event triggers the process, but the outputs stay at 'U'. Is the problem in the design, the test, or both?
VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity TestHarness1 is
port (
ADAT_WDCLK : in std_logic;
ADAT_BCLK: in std_logic;
ADAT_OUT12: in std_logic;
ENABLE: in std_logic;
PCM_FS : out std_logic;
PCM_CLK : out std_logic;
PCM_DIN : out std_logic
);
end TestHarness1;
architecture Behavioral of TestHarness1 is
--type state is (STOPPED, RUNNING);
signal tmp : std_logic;
signal myState : std_logic;
begin
PCM_DIN <= tmp;
-- State management process
process (ENABLE, ADAT_WDCLK) begin -- Eval on input changes
if (ENABLE = '0') then
myState <= '0'; --STOPPED;
PCM_FS <= '0'; -- All outputs muted
PCM_CLK <= '0';
tmp <= '0';
else
if (myState = '0' and rising_edge(ADAT_WDCLK)) then
-- Move to running state only at start of a frame
myState <= '1'; --RUNNING;
end if;
end if;
end process;
-- Output process
process (ADAT_WDCLK, ADAT_BCLK, myState) variable counter: integer := 0; begin
-- Only do something if we are in running state, process above
-- sets outputs when stopped.
if (myState = '1') then
-- Pass the clocks through, inverting the bit clock
PCM_FS <= ADAT_WDCLK;
PCM_CLK <= not ADAT_BCLK;
-- Generate fixed bit pattern data '11000101'
if rising_edge(ADAT_WDCLK) then
-- This would happen naturally since there are 4 bytes per word clock
counter := 0;
end if;
if falling_edge(ADAT_WDCLK) then
-- This would happen naturally since there are 4 bytes per word clock
counter := 0;
end if;
if rising_edge(ADAT_BCLK) then -- Change data state only on falling edge of output PCM_CLK
if counter = 0 or counter = 1 or counter = 5 or counter = 7 then
tmp <= '1';
else
tmp <= '0';
end if;
if (counter = 7) then
counter := 0; -- Reset counter
else
counter := counter + 1; -- Just inc counter
end if;
end if;
end if;
end process;
end Behavioral;
Test Bench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY TH1TestBench3 IS
END TH1TestBench3;
ARCHITECTURE behavior OF TH1TestBench3 IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT TestHarness1
PORT(
ADAT_WDCLK : IN std_logic;
ADAT_BCLK : IN std_logic;
ADAT_OUT12 : IN std_logic;
ENABLE : IN std_logic;
PCM_FS : OUT std_logic;
PCM_CLK : OUT std_logic;
PCM_DIN : OUT std_logic
);
END COMPONENT;
--Inputs
signal ADAT_WDCLK : std_logic := '0';
signal ADAT_BCLK : std_logic := '0';
signal ADAT_OUT12 : std_logic := '0';
signal ENABLE : std_logic := '0';
--Outputs
signal PCM_FS : std_logic;
signal PCM_CLK : std_logic;
signal PCM_DIN : std_logic;
-- Clock period definitions. Note WDCLK is defined in terms of the bit clock
-- to insure they are exactly in sync.
constant ADAT_BCLK_period : time := 326 ns; -- About 3.072MHz (https://www.sensorsone.com/frequency-to-period-calculator/)
constant ADAT_WDCLK_period : time := ADAT_BCLK_period * 64; -- 48KHz
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: TestHarness1 PORT MAP (
ADAT_WDCLK => ADAT_WDCLK,
ADAT_BCLK => ADAT_BCLK,
ADAT_OUT12 => ADAT_OUT12,
ENABLE => ENABLE,
PCM_FS => PCM_FS,
PCM_CLK => PCM_CLK,
PCM_DIN => PCM_DIN
);
-- Clock process definitions
ADAT_WDCLK_process :process
begin
ADAT_WDCLK <= '0';
wait for ADAT_WDCLK_period/2;
ADAT_WDCLK <= '1';
wait for ADAT_WDCLK_period/2;
end process;
ADAT_BCLK_process :process
begin
ADAT_BCLK <= '1';
wait for ADAT_BCLK_period/2;
ADAT_BCLK <= '0';
wait for ADAT_BCLK_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
wait for 100 ns;
ENABLE <= '1';
wait for 100 ns;
ENABLE <= '0';
wait for 7500 ns;
ENABLE <= '1';
wait for ADAT_WDCLK_period*10;
-- insert stimulus here
wait;
end process;
END;
ISim shows the ENABLE pulse early in the simulation, but the outputs remain 'U' until the rising edge of the WCLK with ENABLE=1. Then they start to change (as designed) but they show some X values.
Modified VHDL
For reference, here is the modified VHDL that resolves the problem of U's and X's in the simulation output. However, there is a functional problem with the PCM_DIN output... seems like it is delayed one (BCLK) cycle. I expected it to be '1' as soon as ADAT_WDCLK goes high the first time after ENABLE. But it does not go to '1' until a BLCK cycle later.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity TestHarness1 is
port (
ADAT_WDCLK : in std_logic;
ADAT_BCLK: in std_logic;
ADAT_OUT12: in std_logic;
ENABLE: in std_logic;
PCM_FS : out std_logic;
PCM_CLK : out std_logic;
PCM_DIN : out std_logic
);
end TestHarness1;
architecture Behavioral of TestHarness1 is
--type state is (STOPPED, RUNNING);
signal tmp : std_logic;
signal myState : std_logic;
begin
PCM_DIN <= tmp;
-- State management process
process (ENABLE, ADAT_WDCLK) begin -- Eval on input changes
if (ENABLE = '0') then
myState <= '0'; --STOPPED;
else
if (myState = '0' and rising_edge(ADAT_WDCLK)) then
-- Move to running state only at start of a frame
myState <= '1'; --RUNNING;
end if;
end if;
end process;
-- Output process
process (ADAT_WDCLK, ADAT_BCLK, myState) variable counter: integer := 0; begin
-- Only do something if we are in running state
if (myState = '0') then
PCM_FS <= '0'; -- All outputs muted
PCM_CLK <= '0';
tmp <= '0';
elsif (myState = '1') then
-- Pass the clocks through, inverting the bit clock
PCM_FS <= ADAT_WDCLK;
PCM_CLK <= not ADAT_BCLK;
if rising_edge(ADAT_BCLK) then -- Generate fixed serial bit pattern
if counter = 0 or counter = 1 or counter = 5 or counter = 7 then
tmp <= '1';
else
tmp <= '0';
end if;
if (counter = 7) then
counter := 0; -- Reset counter
else
counter := counter + 1; -- Just inc counter
end if;
end if;
end if;
end process;
end Behavioral;
ISim of the above (including the internal myState signal)... why is PCM_DIN delayed one BCLK cycle?
Regarding the 'X' (Forcing Unknown) values you are seeing:
You are driving the signals PCM_FS, PCM_CLK and tmp from multiple processes, which results in the simulator being unable to resolve the value being driven. You need to fix this such that they are only being driven from one process, or drive 'Z' when they are not in use.
Regarding the 'U' values, they exist because you have no initial values for the signals. Once you write the signals for the first time (after the enable), they will be assigned for the first time.

Unexpected behavior of simple VHDL circuit

What the cause of different delays of signals Q_VLD1 and Q_VLD2 in simulator?
Result of simulation. Is it expected behaviour of simulator or not?
I use Xilinx Isim.
There is the code and testbench for it:
entity assign_test is
port(CLK : in STD_LOGIC;
D_VLD : in STD_LOGIC;
Q_VLD1 : out STD_LOGIC;
Q_VLD2 : out STD_LOGIC
);
end assign_test;
architecture Behavioral of assign_test is
signal D_VLD_i : std_logic;
signal d_vld_dly1 : std_logic;
signal d_vld_dly2 : std_logic;
begin
D_VLD_i <= D_VLD;
process (clk) is
begin
if rising_edge(clk) then
d_vld_dly1 <= D_VLD;
d_vld_dly2 <= D_VLD_i;
end if;
end process ;
Q_VLD1 <= d_vld_dly1;
Q_VLD2 <= d_vld_dly2;
end Behavioral;
ENTITY tb_assign_test IS
END tb_assign_test;
ARCHITECTURE behavior OF tb_assign_test IS
COMPONENT assign_test
PORT(
CLK : IN std_logic;
D_VLD : IN std_logic;
Q_VLD1 : OUT std_logic;
Q_VLD2 : OUT std_logic
);
END COMPONENT;
--Inputs
signal CLK : std_logic := '0';
signal D_VLD : std_logic := '0';
--Outputs
signal Q_VLD1 : std_logic;
signal Q_VLD2 : std_logic;
constant CLK_period : time := 10 ns;
BEGIN
uut: assign_test PORT MAP (
CLK => CLK,
D_VLD => D_VLD,
Q_VLD1 => Q_VLD1,
Q_VLD2 => Q_VLD2
);
CLK_process :process
begin
CLK <= '0';
wait for CLK_period/2;
CLK <= '1';
wait for CLK_period/2;
end process;
stim_proc: process
begin
wait for 100 ns;
wait for 5 ns;
wait for CLK_period*10;
D_VLD <= '1';
wait for CLK_period*3;
D_VLD <= '0';
wait;
end process;
END;
So if you look at the internal signals in the assign_test module, based on simulation time only, it may look as in figure below (d_vld_dly* is before assign to Q_VLD*).
But the figure is misleading, since that figure does not show the VHDL concept of delta delay. If the waveform is expanded to show delta delays (using ModelSim in this case), it looks like below.
So this reveals that the D_VLD_i <= D_VLD; in the assign_test actually delays the D_VLD_i a delta delay, whereby the new value is not seen at the clock until next rising clock edge.
The reason for this problem, is that the test bench does not generate input data as a cause of the clock, which would make data one delta delay after the clock, but independently and at the same simulation time and same delta delay as the clock.
The test bench can be updated to generate data as a cause of the clock, if wait for clock is changed from:
wait for CLK_period*10;
to:
for i in 1 to 10 loop
wait until rising_edge(CLK);
end loop;
which will then give a waveform as:
So based on this, a rule for good test bench design is to generate stimuli the same way as generating data in synthesized modules, so the stimuli from the test bench is like data between modules in general, in order to get expected and reliable and test bench behavior.

VHDL MUX Test Bench Issue

I'm trying to learn VHDL through P. Ashenden's book: Designer's Guide to VHDL. Chapter one's exercise 10 asks you to write 2-to-1 (I'm assuming 1 bit wide) MUX in VHDL and simulate it. I apologize in advance for being a complete noob. This is my first VHDL code.
My MUX didn't produce any errors or warnings in synthesis. My test bench doesn't produce errors or warnings, either. However, the simulation comes up completely blank, except for the names of the signals.
I've tried looking at a multitude of other MUX examples online (as well as a bench test example from the book), all of which gave errors when I tried sythesizing them, so I wasn't confident enough to use them as guides and didn't get much out of them. I'm not sure what I'm doing wrong here. I'd include an image of the simulation, but I don't have enough rep points :(
Also, I realize that a good MUX should also have cases for when it receives no select input/high impedance values, ect.. In this case, I'm just trying to get the toy model working.
The MUX code is:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity MUXtop is
Port (a, b, sel: in bit;
z: out bit);
end MUXtop;
architecture behav of MUXtop is
begin
choose: process is
begin
if sel = '0' then
z <= b;
else
z <= a;
end if;
end process choose;
end architecture behav;
The test bench code is:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY MUXtest IS
END MUXtest;
ARCHITECTURE behavior OF MUXtest IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT MUXtop
PORT(
a : IN bit;
b : IN bit;
sel : IN bit;
z : OUT bit
);
END COMPONENT MUXtop;
--Inputs
signal a : bit := '0';
signal b : bit := '0';
signal sel : bit := '0';
--Outputs
signal z : bit;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: MUXtop PORT MAP (
a => a,
b => b,
sel => sel,
z => z
);
-- Stimulus process
stimulus: process
begin
wait for 10 ns;
a <= '1';
wait for 10 ns;
sel <= '1';
wait for 10 ns;
b <= '1';
wait;
end process stimulus;
END architecture behavior;
You don't need a use clause for package std_logic_1164 when using type bit (declared in package standard).
Your process statement choose in MUXtop has no sensitivity clause which cause the process to continually execute in simulation. (It won't do anything until you trip over a delta cycle iteration limit which might be set to infinity).
I added a sensitivity list, commented out the superfluous use clauses in the two design units and added some more stimulus steps as well as a final wait for 10 ns; to allow the last action to be seen in your testbench:
library IEEE;
-- use IEEE.STD_LOGIC_1164.ALL;
entity MUXtop is
Port (a, b, sel: in bit;
z: out bit);
end MUXtop;
architecture behav of MUXtop is
begin
choose: process (a, b, sel) -- is
begin
if sel = '0' then
z <= b;
else
z <= a;
end if;
end process choose;
end architecture behav;
LIBRARY ieee;
-- USE ieee.std_logic_1164.ALL;
ENTITY MUXtest IS
END MUXtest;
ARCHITECTURE behavior OF MUXtest IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT MUXtop
PORT(
a : IN bit;
b : IN bit;
sel : IN bit;
z : OUT bit
);
END COMPONENT MUXtop;
--Inputs
signal a : bit := '0';
signal b : bit := '0';
signal sel : bit := '0';
--Outputs
signal z : bit;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: MUXtop PORT MAP (
a => a,
b => b,
sel => sel,
z => z
);
-- Stimulus process
stimulus: process
begin
wait for 10 ns;
a <= '1';
wait for 10 ns;
sel <= '1';
wait for 10 ns;
sel <= '0'; -- added
wait for 10 ns; -- added
b <= '1';
wait for 10 ns; -- added
wait;
end process stimulus;
END architecture behavior;
And that gives:
(clickable)

Resources