I'm starting out trying to learn VHDL after doing a little bit of Verilog.
This is my attempt at creating a clock divider:
(largely taken from Making a clock divider)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity clock_192 is
Port ( clk : in STD_LOGIC;
clr : in STD_LOGIC;
clk_out : out STD_LOGIC);
end clock_192;
architecture Behavioral of clock_192 is
signal q : std_logic_vector (23 downto 0);
begin
clk_out <= q(23);
process(clk,clr)
begin
if clr = '1' then
q <= "000000000000000000000000";
elsif clk'event and clk = '1' then
q <= std_logic_vector(unsigned(q)+1);
end if;
end process;
end Behavioral;
And here is the test bench I'm using:
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 test_clock_192 IS
END test_clock_192;
ARCHITECTURE behavior OF test_clock_192 IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT clock_192
PORT(
clk : IN std_logic;
clr : IN std_logic;
clk_out : OUT std_logic
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal clr : std_logic := '0';
--Outputs
signal clk_out : std_logic;
-- Clock period definitions
constant clk_period : time := 10 ns;
constant clk_out_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: clock_192 PORT MAP (
clk => clk,
clr => clr,
clk_out => clk_out
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
clk_out_process :process
begin
clk_out <= '0';
wait for clk_out_period/2;
clk_out <= '1';
wait for clk_out_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
clr <= '1';
wait for 97 ns;
clr <= '0';
wait for clk_period*10;
-- insert stimulus here
wait;
end process;
END;
The trouble is my clk_out signal keeps flipping between 0 and X with every cycle of clk. As seen here:
Does anyone have an idea of what is going on?
EDIT:
To fix the problem I had to change my test bench to look like this:
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 test_clock_192 IS
END test_clock_192;
ARCHITECTURE behavior OF test_clock_192 IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT clock_192
PORT(
clk : IN std_logic;
clr : IN std_logic;
clk_out : OUT std_logic
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal clr : std_logic := '0';
--Outputs
signal clk_out : std_logic;
-- Clock period definitions
constant clk_period : time := 10 ns;
constant clk_out_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: clock_192 PORT MAP (
clk => clk,
clr => clr,
clk_out => clk_out
);
-- 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.
clr <= '1';
wait for 97 ns;
clr <= '0';
wait for clk_period*10;
-- insert stimulus here
wait;
end process;
END;
The test bench drives the clk_out signal both from the uut instance and the clk_out_process process, and this makes the resolution function for the std_logic take effect.
When both sources drive '0' then the resulting clk_out value will be '0', but if one source drives '0' and the other drives '1' then the resolution function will return 'X', as you see.
You can look here for some description of "VHDL resolution function", or try google it.
Related
I'm new on StackOverflow and I'm sorry for eventual error.
I'm workin on VHDL and I have a problem with the Post-Place & Route. While behavioral works correctly, Post-Place & Route has problem and the result remain UNDEFINED for the all the time.
entity step1 is
port ( d: in std_logic_vector (0 to 5);
clk : in std_logic;
RESET: in std_logic;
q: out std_logic_vector (0 to 5)
);
end step1;
architecture Behavioral of step1 is
begin
ff: process (clk)
begin
if (clk'event and clk='1') then
if (RESET = '1') then
q <= "000000";
else
q <= d;
end if;
end if;
end process;
end Behavioral;
I place here the code. It should be a flip flop D that I use to make a pipeline architecture. Thanks for your reply, and please excuse me for any mistake.
Here's the test bench:
entity test_step1 is
end test_step1
ARCHITECTURE behavior OF test_step1 IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT step1
PORT(
input : IN std_logic_vector(0 to 5);
clk : IN std_logic;
RESET : IN std_logic;
output : OUT std_logic_vector(0 to 5)
);
END COMPONENT;
--Inputs
signal input : std_logic_vector(0 to 5) := (others => '0');
signal clk : std_logic := '0';
signal RESET : std_logic := '0';
--Outputs
signal output : std_logic_vector(0 to 5);
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: step1 PORT MAP (
input => input,
clk => clk,
RESET => RESET,
output => output
);
-- 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 10 ns;
RESET <= '0';
input <= "111111";
wait for clk_period*10;
input <= "101010";
-- insert stimulus here
wait;
end process;
END;
The first warning messages for HDL Compiler 89 and 648 found on the internet are:
WARNING:HDLCompiler:89 - "my_module" remains a black-box since it has no binding entity.
WARNING:Simulator:648 - "Top_LCD_test.vhd" Line 35. Instance top_lcd is unboundCompiling architecture behavior of entity testbench
This means that the compiler has not fount any entity corresponding to the component used in your testbench.
In your case, the port names of your entity and component didn't match !
Try to use the same names in port for the component and entity :
entity test_step1 is
end test_step1;
ARCHITECTURE behavior OF test_step1 IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT step1
PORT(
d : IN std_logic_vector(0 to 5);
clk : IN std_logic;
RESET : IN std_logic;
q : OUT std_logic_vector(0 to 5)
);
END COMPONENT;
--Inputs
signal input : std_logic_vector(0 to 5) := (others => '0');
signal clk : std_logic := '0';
signal RESET : std_logic := '0';
--Outputs
signal output : std_logic_vector(0 to 5);
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: step1 PORT MAP (
d => input,
clk => clk,
RESET => RESET,
q => output
);
-- 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 10 ns;
RESET <= '0';
input <= "111111";
wait for clk_period*10;
input <= "101010";
-- insert stimulus here
wait;
end process;
I am currently slightly confused about my simple counter.
It is implemented as follows:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity simple_counter is
port(
DOUT : out std_logic_vector(3 downto 0);
CE : in std_logic;
CLK : in std_logic;
RSTN : in std_logic
);
end simple_counter;
architecture behavioral of simple_counter is
signal temp : unsigned(3 downto 0);
begin
process(CLK)
begin
if RSTN = '0' then
temp <= (others => '0');
elsif(rising_edge(CLK)) then
if CE = '1' then
if std_logic_vector(temp) = (temp'range => '1') then
temp <= (others => '0');
else
temp <= temp + 1;
end if;
end if;
end if;
end process;
DOUT <= std_logic_vector(temp);
end behavioral;
I use the following testbench for simulation:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library std;
use std.textio.all;
use work.tools_pkg.all;
library work;
--! #class tools_tb
--! #brief Test bench for the tools_tb design
entity counter_tb is
generic (
VOID : integer := 0);
port (
void_i : in std_logic);
end entity counter_tb;
--! #brief
--! #details
architecture sim of counter_tb is
-- Clock period definitions
-- Clock, reset and baud rate definitions
constant CLK_FREQ : integer := 100_000_000;
constant clk_period : time := (1.0 / real(CLK_FREQ)) * (1 sec);
signal end_sim : boolean := false;
signal rstn : std_logic;
signal clk : std_logic;
signal s_en : std_logic := '0';
------------------------------------------------------------------------------
-- DUT signals
------------------------------------------------------------------------------
signal s_dout : std_logic_vector(3 downto 0) := (others => '0');
signal s_ce : std_logic := '0';
begin -- architecture
fifo : entity work.simple_counter
port map (
DOUT => s_dout,
CE => s_ce,
RSTN => rstn,
CLK => clk
);
-- Clock process definitions (clock with 50% duty cycle is generated here).
clk_process : process
begin
if end_sim = false then
clk <= '1';
wait for clk_period/2;
clk <= '0';
wait for clk_period/2;
else
wait;
end if;
end process;
-- Stimulus process
stim_proc: process
begin
-- startup and wait for some time
rstn <= '0';
wait for clk_period;
rstn <= '1';
wait for clk_period;
wait for clk_period;
wait for clk_period;
s_ce <= '1';
wait;
end process;
end architecture sim;
I am confused why the counter increases instantly when I set CE <= '1
(see the attached simulation).
Since the counter is implemented in a synchrous process, shouldn't it take a single clock cycle until it is increased from '0' to '1'?
Thanks a lot!
You most likely have a race condition between s_ce and clk. If you will generate the s_ce on the rising edge of clk then you should see that counter works correctly.
I don't know this simulator but to check the race you can expand deltas when counter changes 0->1
I'm a newbie in VHDL and hardware world.
I'm trying to make a Count&Compare example using Top Level Hierarchy and test it with testbench and see the results on ISIM.
Here is my block diagram sketch:
So I end up these 3 vhd source files:
Counter.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Count_src is
Port ( CLK : in STD_LOGIC;
Reset : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (3 downto 0));
end Count_src;
architecture Behavioral of Count_src is
signal count : STD_LOGIC_VECTOR (3 downto 0);
begin
process (Reset, CLK)
begin
if Reset = '1' then -- Active high reset
count <= "0000"; -- Clear count to 0
elsif (rising_edge(CLK)) then -- Positive edge
count <= count + "0001"; -- increment count
end if;
end process;
S <= count; -- Export count
end Behavioral;
Compare
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Compare_src is
Port ( A : in STD_LOGIC_VECTOR (3 downto 0);
B : in STD_LOGIC_VECTOR (3 downto 0);
S : out STD_LOGIC);
end Compare_src;
architecture Behavioral of Compare_src is
begin
S <= '1' when (A = B) else -- Test if A and B are same
'0'; -- Set when S is different
end Behavioral;
CountCompare (Top Level)
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;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity CountCompare_src is
Port ( Clock : in STD_LOGIC;
Reset : in STD_LOGIC;
Value : in STD_LOGIC_VECTOR (3 downto 0);
Flag : out STD_LOGIC);
end CountCompare_src;
architecture Behavioral of CountCompare_src is
-- COMPONENT DECLERATIONS
component counter is
port ( CLK : in std_logic;
Reset : in std_logic;
S : out std_logic_vector(3 downto 0)
);
end component;
component compare is
port (A : in std_logic_vector(3 downto 0);
B : in std_logic_vector(3 downto 0);
S : out std_logic
);
end component;
-- Component Spesification and Binding
for all : counter use entity work.Count_src(behavioral);
for all : compare use entity work.Compare_src(behavioral);
-- Internal Wires
signal count_out : std_logic_vector(3 downto 0);
begin
-- Component instantiation
C1: counter PORT MAP ( Reset => Reset,
CLK => Clock,
S => count_out
);
C2: compare PORT MAP ( A => count_out,
B => Value,
S => Flag
);
end Behavioral;
To test the design I wrote a testbench as follows:
TestBench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY TopLevelTester_tb IS
END TopLevelTester_tb;
ARCHITECTURE behavior OF TopLevelTester_tb IS
--Input and Output definitions.
signal Clock : std_logic := '0';
signal Reset : std_logic := '0';
signal Value : std_logic_vector(3 downto 0) := "1000";
signal Flag : std_logic;
-- Clock period definitions
constant clk_period : time := 1 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: entity work.CountCompare_src PORT MAP
(
Clock => Clock,
Reset => Reset,
Value => Value
);
proc: process
begin
Clock <= '0';
wait for clk_period/2;
Clock <= '1';
wait for clk_period/2;
end process;
END;
When I simulate behavioral model, the ISIM pops up, but I see no changes on the Compare Flag. Here is the ss of the ISIM:
What am I missing here? Why does'nt the Flag change?
My best regards.
You have two problems, both in your testbench.
The first is that you never reset count in the counter, it will always be 'U's or 'X's (after you increment it).
The second is that the directly entity instantiation in the testbench is missing an association for the formal flag output to the actual flag signal:
begin
uut:
entity work.countcompare_src
port map (
clock => clock,
reset => reset,
value => value,
flag => flag
);
proc:
process
begin
clock <= '0';
wait for clk_period/2;
clock <= '1';
wait for clk_period/2;
if now > 20 ns then
wait;
end if;
end process;
stimulus:
process
begin
wait for 1 ns;
reset <= '1';
wait for 1 ns;
reset <= '0';
wait;
end process;
Fix those two things and you get:
--
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity D_flip_flop is
port (
D : in STD_LOGIC;
Q : inout STD_LOGIC;
Q_tonos : out STD_LOGIC;
CLK : in STD_LOGIC;
RST : in STD_LOGIC
);
end D_flip_flop;
architecture Behavioral of D_flip_flop is
begin
process_flip_flip: process
begin
wait until CLK'EVENT AND CLK = '1';
if(RST='1') then
Q <= '0';
else
Q <= D;
end if;
Q_tonos <= not Q;
end process process_flip_flip;
end Behavioral;
-------------------------
--testbench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY test_flip_flop IS
END test_flip_flop;
ARCHITECTURE tb OF test_flip_flop IS
COMPONENT D_flip_flop
PORT(
D : IN std_logic;
Q : INout std_logic;
Q_tonos : OUT std_logic;
CLK : IN std_logic;
RST : IN std_logic
);
END COMPONENT;
signal D : std_logic ;
signal CLK : std_logic ;
signal RST : std_logic ;
signal Q : std_logic;
signal Q_tonos : std_logic;
constant CLK_period : time := 10 ns;
signal stopClk : boolean;
BEGIN
-- Instantiate the Unit Under Test (UUT)
dut: D_flip_flop PORT MAP (
D => D,
Q => Q,
Q_tonos => Q_tonos,
CLK => CLK,
RST => RST
);
CLK_process :process
begin
while not stopClk loop
CLK <= '0';
wait for CLK_period/2;
CLK <= '1';
wait for CLK_period/2;
end loop;
wait;
end process CLK_process;
-- Stimulus process
stim_proc: process
begin
-- insert stimulus here
D <= '0';
RST <= '1';
wait for 100 ns;
D <= '0';
RST <= '0';
wait for 100 ns;
D <= '1';
RST <= '0';
wait for 100 ns;
D <= '1';
RST <= '0';
wait for 100 ns;
wait;
end process;
END;
You are missing one line in your testbench, I think:
D <= '1';
RST <= '0';
wait for 100 ns;
stopClk <= TRUE; -- add this line
wait;
end process;
END;
http://www.edaplayground.com/x/56Mm
That way, when the test is finished, the clock stopClk signal turns off the clock generator and the simulation finishes. It finishes because it reaches a state called event starvation. Every time a line of code containing a signal assignment is executed, an event is added to the simulators event queue (its "to do list"). If you create a situation where no such lines continue to be executed, then the event queue becomes empty. This is event starvation. The simulator detects that and the simulation stops. (If you think about, what else could it do?)
Without this extra line, the simulation runs forever, because the clock generation process executes signal assignments forever, so the event queue is never empty.
Not really an answer, but: consider using if rising_edge(CLK) or maybe if CLK='1' and CLK'event instead of wait until. Not all synhtesis tools support that kind of code and anyway it's rare to see it in professional world ;)
p.s. stopClk signal is not driven (or was it?) Your TB clock is enably by that, yet I guess it remains 'u' for the whole simulation. Unless forced in the simulation.
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.