No Output From Entity in ModelSim Simulator - VHDL - vhdl

I have written a simple entity in VHDL to blink an LED and am trying to simulate it in ModelSim but am getting no transitions on the output.
Here is my HDL file for the LED_Blink entity:
Library IEEE;
use IEEE.Std_logic_1164.all;
entity LED_Blink is
generic (
g_SYSTEM_CLOCK_PERIOD : in time := 10 ns; -- 100 MHz clock period
g_LED_ON_TIME : in time := 1 sec
);
port(
system_clock : in Std_logic;
reset_fpga_L : in Std_logic;
led_out : out Std_logic
);
end entity LED_Blink;
architecture RTL of LED_Blink is
signal led_state : Std_logic;
constant COUNTER_RELOAD_VAL : natural := g_LED_ON_TIME/g_SYSTEM_CLOCK_PERIOD;
begin
process(reset_fpga_L, system_clock)
variable counter : natural range 0 to COUNTER_RELOAD_VAL := COUNTER_RELOAD_VAL;
begin
if reset_fpga_L = '0' then
counter := COUNTER_RELOAD_VAL;
led_state <= '0';
elsif rising_edge(system_clock) then
if counter = 0 then
led_state <= not led_state;
counter := COUNTER_RELOAD_VAL;
else
counter := counter - 1;
end if;
end if;
led_out <= led_state;
end process;
end architecture RTL;
And here is my test-bench:
Library IEEE;
use IEEE.Std_logic_1164.all;
entity LED_Blink_TB is
end entity LED_Blink_TB;
architecture RTL of LED_Blink_TB is
signal reset_fpga_L : Std_logic := '0';
signal system_clock : Std_logic := '0';
signal led_out : Std_logic := '0';
begin
G1: entity work.LED_Blink(RTL) port map(reset_fpga_L, system_clock, led_out);
CLK: process
begin
while now <= 5 sec loop
system_clock <= not system_clock;
wait for 5 ns;
end loop;
wait;
end process CLK;
STIM: process
begin
reset_fpga_L <= '0';
wait for 100 ns;
reset_fpga_L <= '1';
wait for 4 sec;
reset_fpga_L <= '0';
wait for 50 ns;
reset_fpga_L <= '1';
wait;
end process STIM;
end architecture RTL;
I can't figure out why I'm not seeing any transitions on led_out when I run my test-bench in the simulator. I've taken care to add the waves for system_clock, reset_fpga_L, and led_out to the trace view. Do you see anything in my code that might be an issue? Thanks for your help.

A second form of the testbench can be used make generation of inputs to LED_Blink depend on the values supplied as generics:
library ieee;
use ieee.std_logic_1164.all;
entity led_blink_tb is
end entity;
architecture foo of led_blink_tb is
constant CLK_PERIOD: time := 100 ms;
constant LED_ON: time := 500 ms;
signal clk: std_logic := '0';
signal reset_n: std_logic;
signal led: std_logic;
begin
DUT:
entity work.led_blink
generic map ( CLK_PERIOD, LED_ON)
port map (
system_clock => clk,
reset_fpga_l => reset_n,
led_out => led
);
CLOCK:
process
begin
wait for CLK_PERIOD/2;
clk <= not clk;
if now > 2.5 sec then
wait;
end if;
end process;
STIMULI:
process
begin
reset_n <= '0';
wait for CLK_PERIOD * 2;
reset_n <= '1';
wait;
end process;
end architecture;
The idea, both the testbench and the model depend on constants supplied as generics making changing the parameters require less work.
Also note the association list in the port map uses named association.
If we take a look at the original testbench port map:
G1: entity work.LED_Blink(RTL) port map(reset_fpga_L, system_clock, led_out);
We see that the first positional association to the formal system_clock is associated with the actual reset_fpga_L while the second positional association representing formal reset_fpga_L is associated with the actual system_clock.
The two actual associations are in reversed order.

Related

VHDL: Button debouncing (or not, as the case may be)

I've read through the other posts but can't seem to fix mine. I'm new to VHDL so I'm sure it's a simple fix.
In short, the button isn't debouncing. The code compiles and the bitstream programs. In the testbench, button presses work, but the output LEDs don't change. On the board, pressing a button makes random LEDs light up (I presume because of bouncing). According to the schematic the inputs are going through the debouncers.
Can anyone identify the issue? And any other hints and tips are always appreciated :)
Thanks!
EDIT1: Added rising_edge(clk).
Also note, when I press either button, at the time it's depressed all the LEDs light up.
button_counter.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity button_counter is
port( clk : in std_logic;
btnU : in std_logic;
btnD : in std_logic;
led : out std_logic_vector (15 downto 0));
end button_counter;
architecture behavioral of button_counter is
component debouncer is
port( clk : in std_logic;
btn : in std_logic;
btn_clr : out std_logic);
end component;
signal btnU_clr : std_logic;
signal btnD_clr : std_logic;
begin
debouncer_btnU : debouncer port map (clk => clk, btn => btnU, btn_clr => btnU_clr);
debouncer_btnD : debouncer port map (clk => clk, btn => btnD, btn_clr => btnD_clr);
process(clk)
variable count : integer := 0;
begin
if (rising_edge(clk)) then
if(btnU_clr = '1') then count := count + 1;
elsif(btnD_clr = '1') then count := count - 1;
end if;
led <= std_logic_vector(to_unsigned(count, led'length));
end if;
end process;
end behavioral;
Debouncer.vhd
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity debouncer is
port( clk : in std_logic;
btn : in std_logic;
btn_clr : out std_logic);
end debouncer;
architecture behavioural of debouncer is
constant delay : integer := 650000; -- 6.5ms
signal count : integer := 0;
signal btn_tmp : std_logic := '0';
begin
process(clk)
begin
if rising_edge(clk) then
if (btn /= btn_tmp) then
btn_tmp <= btn;
count <= 0;
elsif (count = delay) then
btn_clr <= btn_tmp;
else
count <= count + 1;
end if;
end if;
end process;
end behavioural;
button_counter_tb.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity button_counter_tb is
end button_counter_tb;
architecture behavioral of button_counter_tb is
signal clk_tb : std_logic;
signal btnU_tb : std_logic;
signal btnD_tb : std_logic;
signal led_tb : std_logic_vector (15 downto 0);
component button_counter
port(clk : in std_logic;
btnU : in std_logic;
btnD : in std_logic;
led : out std_logic_vector (15 downto 0));
end component;
begin
UUT: button_counter port map (clk => clk_tb, btnU => btnU_tb, btnD => btnD_tb, led => led_tb);
process
begin
btnU_tb <= '0';
btnD_tb <= '0';
wait for 100ns;
btnU_tb <= '1';
wait for 100ns;
btnU_tb <= '0';
wait for 100ns;
btnU_tb <= '1';
wait for 100ns;
btnD_tb <= '1';
wait for 100ns;
btnU_tb <= '0';
wait for 100ns;
btnD_tb <= '0';
end process;
end behavioral;
After your code update there are several issues remaining:
The clock isn't being generated in the testbench
The stimuli (button presses) aren't adequately timed in the testbench
The debouncer doesn't produce an enable for a single clock
To facilitate simulation for design validation your design has been modified to allow a slower clock (it appears you're actually using a 100 MHz clock). The idea is to reduce the computation requirements and display waveform storage.
The first two points are addressed in the testbench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity button_counter_tb is
end entity button_counter_tb;
architecture behavioral of button_counter_tb is
-- NOTE: suffix _tb has been removed, it's annoying to type over and over
signal clk: std_logic := '0'; -- ADDED default value '0'
signal btnU: std_logic;
signal btnD: std_logic;
signal led: std_logic_vector (15 downto 0);
component button_counter
generic ( -- ADDED generic
CLKP: time := 10 ns;
DEBT: time := 6.5 ms -- debounce time supports different
); -- mechanical buttons/switches
port (
clk: in std_logic;
btnU: in std_logic;
btnD: in std_logic;
led: out std_logic_vector (15 downto 0)
);
end component;
constant CLKP: time := 12.5 us; -- ADDED just long enough to show debounce
constant DEBT: time := 6.5 ms; -- ADDED
begin
CLOCK: -- ADDED clock process
process
begin
wait for CLKP/2;
clk <= not clk;
if now > 2 sec then -- stop simulation
wait;
end if;
end process;
UUT:
button_counter
generic map ( -- ADDED generic map
CLKP => CLKP,
DEBT => DEBT
)
port map (
clk => clk,
btnU => btnU,
btnD => btnD,
led => led
);
-- STIMULI:
-- process
-- begin
-- btnU_tb <= '0';
-- btnD_tb <= '0';
-- wait for 100 ns;
-- btnU_tb <= '1';
-- wait for 100 ns;
-- btnU_tb <= '0';
-- wait for 100 ns;
-- btnU_tb <= '1';
-- wait for 100 ns;
-- btnD_tb <= '1';
-- wait for 100 ns;
-- btnU_tb <= '0';
-- wait for 100 ns;
-- btnD_tb <= '0';
-- wait; -- ADDED -- stops simulation
-- end process;
UP_BUTTON:
process
begin
btnU <= '0';
wait for 2 ms;
btnU <= '1'; -- first button press
wait for 0.5 ms;
btnU <= '0';
wait for 0.25 ms;
btnU <= '1';
wait for 7 ms;
btnU <= '0';
wait for 100 us;
btnU <= '1';
wait for 20 us;
btnU <= '0';
wait for 200 ms;
btnU <= '1'; -- second button press
wait for 20 us;
btnU <= '0';
wait for 20 us;
btnU <= '1';
wait for 6.6 ms;
btnU <= '0';
wait for 250 ms;
btnU <= '1'; -- third button press
wait for 20 us;
btnU <= '0';
wait for 20 us;
btnU <= '1';
wait for 6.6 ms;
btnU <= '0';
wait for 200 ms;
btnU <= '1'; -- second button press
wait for 20 us;
btnU <= '0';
wait for 20 us;
btnU <= '1';
wait for 6.6 ms;
btnU <= '0';
wait for 50 us;
btnU <= '1';
wait for 1 ms;
btnU <= '0';
wait;
end process;
DOWN_BUTTON:
process
begin
btnD <= '0';
wait for 800 ms;
btnD <= '1'; -- first button press
wait for 0.5 ms;
btnD <= '0';
wait for 0.25 ms;
btnD <= '1';
wait for 0.5 ms;
btnD <= '0';
wait for 1 ms;
btnD <= '1';
wait for 7 ms;
btnD <= '0';
wait for 100 us;
btnD <= '1';
wait for 20 us;
btnD <= '0';
wait for 200 ms;
btnD <= '1'; -- second button press
wait for 20 us;
btnD <= '0';
wait for 20 us;
btnD <= '1';
wait for 6.6 ms;
btnD <= '0';
wait for 250 ms;
wait;
end process;
end architecture behavioral;
The _tb suffix to signal names has been removed (it was painful to type in repetitively).
A clock period has been picked with a ratio of bounce period to clk period guaranteed to allow dropping 'bounces'. The stimului button presses can be extended as can the simulation which is arbitrary here.
Note the button press values are guaranteed to span one or more clock intervals.
These should tolerate the clock period being changed by modifying CLKP.
The debounce interval DEBT can be modified to reflect the use of different switches or buttons, including membrane switches with severe aging. The debounce interval is a consequence of mechanical characteristics of the particular switches or buttons. Passing these generic constants allows a degree of platform independence.
The third point is addressed by changes to the debouncer:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity debouncer is
generic ( -- ADDED GENERICS to speed up simulation
CLKP: time := 10 ns;
DEBT: time := 6.5 ms
);
port (
clk: in std_logic;
btn: in std_logic;
btn_clr: out std_logic
);
end entity debouncer;
architecture behavioural of debouncer is
-- constant delay: integer := 650000; -- 6.5ms
constant DELAY: integer := DEBT/CLKP;
signal count: integer := 0;
signal b_enab: std_logic := '0'; -- RENAMED, WAS btn_tmp
signal btnd0: std_logic; -- ADDED for clock domain crossing
signal btnd1: std_logic; -- DITTO
begin
CLK_DOMAIN_CROSS: -- ADDED process
process (clk)
begin
if rising_edge(clk) then
btnd0 <= btn;
btnd1 <= btnd0;
end if;
end process;
DEBOUNCE_COUNTER: -- ADDED LABEL
process (clk)
begin
if rising_edge(clk) then
-- if btn /= btn_tmp then -- REWRITTEN
-- btn_tmp <= btn;
-- count <= 0;
-- elsif count = DELAY then
-- btn_clr <= btn_tmp;
-- else
-- count <= count + 1;
-- end if;
btn_clr <= '0'; -- btn_clr for only one clock, used as enable
if btnd1 = '0' then -- test for btn inactive state
count <= 0;
elsif count < DELAY then -- while btn remains in active state
count <= count + 1;
end if;
if count = DELAY - 1 then -- why btn_clr '1' or 1 clock
btn_clr <= '1';
end if;
end if;
end process;
end architecture behavioural;
The debouncer has been modified to get a clock domain button value which is used to reset and enable the counter count. The output btn_clr name has been left intact and is true for only one clock and can be used as an enable.
CLKP and DEBT are used together to allow faster simulation execution while passing the same simulation time.
Note the active state of the button input is hard coded. These would be connected to device pins where the input polarity can be specified.
Modifications to button_counter pass generic constants CLKP and DEBT to the debouncers:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity button_counter is
generic (
CLKP: time := 10 ns; -- GENERIC CONSTANTS for faster simulation
DEBT: time := 6.5 ms -- supports diffeent switches/buttons
);
port (
clk: in std_logic;
btnU: in std_logic;
btnD: in std_logic;
led: out std_logic_vector (15 downto 0)
);
end entity button_counter;
architecture behavioral of button_counter is
component debouncer is
generic (
CLKP: time := 10 ns;
DEBT: time := 6.5 ms
);
port (
clk: in std_logic;
btn: in std_logic;
btn_clr: out std_logic
);
end component;
signal btnU_clr: std_logic;
signal btnD_clr: std_logic;
begin
debouncer_btnU:
debouncer
generic map (
CLKP => CLKP,
DEBT => DEBT
)
port map (
clk => clk,
btn => btnU,
btn_clr => btnU_clr
);
debouncer_btnD:
debouncer
generic map (
CLKP => CLKP,
DEBT => DEBT
)
port map (
clk => clk,
btn => btnD,
btn_clr => btnD_clr
);
process (clk)
variable count: integer := 0;
begin
if rising_edge(clk) then
if btnU_clr = '1' then
count := count + 1;
elsif btnD_clr = '1'then
count := count - 1;
end if;
led <= std_logic_vector(to_unsigned(count, led'length));
end if;
end process;
end architecture behavioral;
And when simulated we now see the LEDs count up and down:
Running the testbench and displaying the various waveforms would allow 'zooming in' to display glitch handling in the two debouncers.
The modifications to pass the clock period and debounce interval through the design hierarchy wouldn't be strictly essential. They facilitate simulation which is used as here for design validation. (The stimuli shown in the testbench don't exhaustively verify the design).
By using the generic defaults (with a 100MHz clock) there's a very good chance the design will function when implemented in a target platform. (The active polarity of button inputs is selected in the debouncer to support the original implementation. if you suspect button bounces while getting increments or decrements you can increase the DEBT value.)
If a particular synthesis tool can't handle value of type time passed as generic constants you can convert the various declarations of CLKP and DEBT to type integer or simply pass the maximum count.
You forget the rising_edge in your button_counter.vhd.
process(clk)
variable count : integer := 0;
begin
if(btnU_clr = '1') then count := count + 1;
elsif(btnD_clr = '1') then count := count - 1;
end if;
led <= std_logic_vector(to_unsigned(count, led'length));
end process;
So fix this and maybe it works (I don´t test the design, because of this obvious error):
process(clk)
variable count : integer := 0;
begin
if(rising_edge(clk)) then
...
end if;
end process;
I´m not sure, but I think the toolchain will produce some warnings for this. So check it please.
And your Testbench doesn´t contain any clock generation process, so you will not have a clock signal. Maybe this will let you believe that your design works (or did you forget the clock clk_tb signal in your post?).
The question has been answered well, but I would like to highlight different techniques for synchronising and debouncing.
Synchronising
For synchronising, a simple buffer or chain can be used which avoids creating separate signals/variables for each stage in the buffer or chain. A generic constant can be used to control the length of the chain (minimum of 2):
signal sync_buffer: std_logic_vector(SYNC_BUFFER_MSB downto 0); -- N-bit synchronisation buffer.
...
sync_buffer <= sync_buffer(SYNC_BUFFER_MSB - 1 downto 0) & input;
Debouncing
For debouncing, hysteresis (a fancy word for history or memory) can be used to create a kind of low pass filter that will debounce both the press and release of a button, and detect edges (both positive and negative) irrespective of whether the signal is active high or active low. The output will stay in its current state until the synchronised input remains in the opposite state for N consecutive clock cycles:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Debounce is
generic
(
CLOCK_PERIOD : time := 20 ns;
DEBOUNCE_PERIOD: time := 125 ms; -- 1/8th second as a rule of thumb for a tactile button/switch.
SYNC_BITS : positive := 3 -- Number of bits in the synchronisation buffer (2 minimum).
);
port
(
clock : in std_logic;
input : in std_logic; -- Asynchronous and noisy input.
output: out std_logic := '0'; -- Synchronised, debounced and filtered output.
edge : out std_logic := '0'; -- Goes high for 1 clock cycle on either edge of synchronised and debounced input.
rise : out std_logic := '0'; -- Goes high for 1 clock cycle on the rising edge of synchronised and debounced input.
fall : out std_logic := '0' -- Goes high for 1 clock cycle on the falling edge of synchronised and debounced input.
);
end entity;
architecture V1 of Debounce is
constant SYNC_BUFFER_MSB: positive := SYNC_BITS - 1;
signal sync_buffer: std_logic_vector(SYNC_BUFFER_MSB downto 0) := (others => '0'); -- N-bit synchronisation buffer (2 bits minimum).
alias sync_input: std_logic is sync_buffer(SYNC_BUFFER_MSB); -- The synchronised input is the MSB of the synchronisation buffer.
constant MAX_COUNT: natural := DEBOUNCE_PERIOD / CLOCK_PERIOD;
signal counter: natural range 0 to MAX_COUNT := 0; -- Specify the range to reduce number of bits that are synthesised.
begin
assert SYNC_BITS >= 2 report "Need a minimum of 2 bits in the synchronisation buffer.";
process(clock)
variable edge_internal: std_logic := '0';
variable rise_internal: std_logic := '0';
variable fall_internal: std_logic := '0';
begin
if rising_edge(clock) then
-- Synchronise the asynchronous input.
-- MSB of sync_buffer is the synchronised input.
sync_buffer <= sync_buffer(SYNC_BUFFER_MSB - 1 downto 0) & input;
edge <= '0'; -- Goes high for 1 clock cycle on either edge.
rise <= '0'; -- Goes high for 1 clock cycle on the rising edge.
fall <= '0'; -- Goes high for 1 clock cycle on the falling edge.
if counter = MAX_COUNT - 1 then -- If successfully debounced, notify what happened, and reset the counter.
output <= sync_input;
edge <= edge_internal; -- Goes high for 1 clock cycle on either edge.
rise <= rise_internal; -- Goes high for 1 clock cycle on the rising edge.
fall <= fall_internal; -- Goes high for 1 clock cycle on the falling edge.
counter <= 0;
elsif sync_input /= output then
counter <= counter + 1;
else
counter <= 0;
end if;
end if;
-- Edge detection.
edge_internal := sync_input xor output;
rise_internal := sync_input and not output;
fall_internal := not sync_input and output;
end process;
end architecture;
Button Counter
Much the same as the other answers, but I've used the rise outputs of the debouncers to trigger the counting. I also added a couple of LEDs for visual button feedback.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ButtonCounter is
generic
(
CLOCK_PERIOD : time := 20 ns;
DEBOUNCE_PERIOD: time := 125 ms
);
port
(
clock : in std_logic;
btn_up: in std_logic;
btn_dn: in std_logic;
led_up: out std_logic;
led_dn: out std_logic;
leds : out std_logic_vector(15 downto 0)
);
end entity;
architecture V1 of ButtonCounter is
signal count_up: std_logic;
signal count_dn: std_logic;
component Debounce is
generic
(
CLOCK_PERIOD : time := 20 ns;
DEBOUNCE_PERIOD: time := 125 ms
);
port
(
clock : in std_logic;
input : in std_logic;
output: out std_logic;
rise : out std_logic
);
end component;
begin
DEBOUNCE_BTN_UP:
Debounce
generic map
(
CLOCK_PERIOD => CLOCK_PERIOD,
DEBOUNCE_PERIOD => DEBOUNCE_PERIOD
)
port map
(
clock => clock,
input => btn_up,
output => led_up,
rise => count_up -- Goes high for 1 clock cycle on the rising edge of btn_up.
);
DEBOUNCE_BTN_DN:
Debounce
generic map
(
CLOCK_PERIOD => CLOCK_PERIOD,
DEBOUNCE_PERIOD => DEBOUNCE_PERIOD
)
port map
(
clock => clock,
input => btn_dn,
output => led_dn,
rise => count_dn -- Goes high for 1 clock cycle on the rising edge of btn_dn.
);
process(clock)
variable counter: natural range 0 to 2 ** leds'length - 1 := 0; -- Specify the range to reduce number of bits that are synthesised.
begin
if rising_edge(clock) then
if count_up then
counter := counter + 1;
elsif count_dn then
counter := counter - 1;
end if;
leds <= std_logic_vector(to_unsigned(counter, leds'length));
end if;
end process;
end architecture;
Test Bench
Some asynchronous and noisy input buttons are synchronised, debounced and filtered. The positive edges of the reformed input signals trigger the counting.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity ButtonCounter_TB is
end;
architecture V1 of ButtonCounter_TB is
constant CLOCK_PERIOD : time := 50 ns;
constant DEBOUNCE_PERIOD: time := 200 ns;
signal halt_sys_clock: boolean := false;
signal clock: std_logic := '0';
signal btn_up: std_logic;
signal btn_dn: std_logic;
signal leds: std_logic_vector(15 downto 0);
component ButtonCounter is
generic
(
CLOCK_PERIOD : time := 10 ns;
DEBOUNCE_PERIOD: time := 125 ms
);
port
(
clock : in std_logic;
btn_up: in std_logic;
btn_dn: in std_logic;
leds : out std_logic_vector(15 downto 0)
);
end component;
begin
ClockGenerator:
process
begin
while not halt_sys_clock loop
clock <= not clock;
wait for CLOCK_PERIOD / 2.0;
end loop;
wait;
end process ClockGenerator;
Stimulus:
process
constant NUM_NOISE_SAMPLES: positive := 10;
constant SWITCH_TIME: time := 2 * DEBOUNCE_PERIOD;
variable seed1: positive := 1;
variable seed2: positive := 1;
variable rrand: real;
variable nrand: natural;
-- Performs noisy transition of sig from current value to final value.
procedure NoisyTransition(signal sig: out std_logic; final: std_logic) is
begin
for n in 1 to NUM_NOISE_SAMPLES loop
uniform(seed1, seed2, rrand);
nrand := natural(round(rrand));
if nrand = 0 then
sig <= not final;
else
sig <= final;
end if;
wait for CLOCK_PERIOD / 5.0;
end loop;
sig <= final;
wait for SWITCH_TIME;
end;
begin
btn_up <= '0';
btn_dn <= '0';
wait for 3 ns;
--
-- Up Button
--
-- Perform 4 noisy presses and releases.
for n in 1 to 4 loop
NoisyTransition(btn_up, '1');
NoisyTransition(btn_up, '0');
end loop;
--
-- Down Button
--
-- Perform 1 noisy press and release.
NoisyTransition(btn_dn, '1');
NoisyTransition(btn_dn, '0');
halt_sys_clock <= true;
wait;
end process;
DUT:
ButtonCounter
generic map
(
CLOCK_PERIOD => CLOCK_PERIOD,
DEBOUNCE_PERIOD => DEBOUNCE_PERIOD
)
port map
(
clock => clock,
btn_up => btn_up,
btn_dn => btn_dn,
leds => leds
);
end architecture;
Simulation

I’m new to coding in VHDL and don’t understand why my code will not show an output when simulating on a VWF file

My code will not simulate an output when running the VWF file.
I have tried changing the code several different time and don't really understand what I'm doing wrong.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Counter_JM is
Port (
up_down : in std_logic;
LED : out std_logic;
Q : Buffer integer Range 0 to 7);
end Counter_JM;
architecture archi of Counter_JM is
Begin
-- up/down counter
process (up_down)
begin
if (Q=7) then
Q<=0;
end if;
if (up_down = '1') then
Q <= Q + 1;
else
Q<=0;
end if;
if (Q=0 or Q=1) then
LED <= '0';
else
LED <= '1';
end if;
end process;
end archi;
The LED output should show high for 4 cycles and low for 2 on the VWF file
I don't know why you use up_down. But as Oldfart said, you don't have a clock. I have simplified and modified your code (it works for me (in modelsim):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Counter_JM is
Port (
clk: in std_logic;
up_down : in std_logic;
LED : out std_logic
);
end Counter_JM;
architecture archi of Counter_JM is
Begin
process (clk)
variable Q: integer range 0 to 7;
begin
if rising_edge(clk) then
-- up/down counter
Q := Q + 1;
if Q=1 or Q=2 then
LED <= '0';
else
LED <= '1';
end if;
if Q = 7 then
Q := 0;
end if;
end if;
end process;
end archi;
and also created/generated a simple testbench here :
`-- Testbench automatically generated online
-- at http://vhdl.lapinoo.net
-- Generation date : 7.6.2019 11:22:53 GMT
library ieee;
use ieee.std_logic_1164.all;
entity tb_Counter_JM is
end tb_Counter_JM;
architecture tb of tb_Counter_JM is
component Counter_JM
port (clk : in std_logic;
up_down : in std_logic;
LED : out std_logic);
end component;
signal clk : std_logic;
signal up_down : std_logic;
signal LED : std_logic;
constant TbPeriod : time := 1000 ns; -- EDIT Put right period here
signal TbClock : std_logic := '0';
signal TbSimEnded : std_logic := '0';
begin
dut : Counter_JM
port map (clk => clk,
up_down => up_down,
LED => LED);
-- Clock generation
TbClock <= not TbClock after TbPeriod/2 when TbSimEnded /= '1' else '0';
-- EDIT: Check that clk is really your main clock signal
clk <= TbClock;
stimuli : process
begin
-- EDIT Adapt initialization as needed
up_down <= '0';
-- EDIT Add stimuli here
wait for 100 * TbPeriod;
-- Stop the clock and hence terminate the simulation
TbSimEnded <= '1';
wait;
end process;
end tb;
-- Configuration block below is required by some simulators. Usually no need to edit.
configuration cfg_tb_Counter_JM of tb_Counter_JM is
for tb
end for;
end cfg_tb_Counter_JM;`

How to find frequency of a clock divider ?

Supposing i have on my board a 100Mhz clock and the following clock divider:
entity div is
port(clk:in std_logic;
clk_out:out std_logic);
architecture ar of div is
begin
process(clk)
variable aux:integer := 0;
variable aux2:std_logic := '0';
begin
if clk = '1' and clk'event then
aux := aux + 1;
if aux = 1600500 and aux2='0' then
aux = 0;
aux2 = 1;
end if;
if aux = 1600500 and aux2 ='1' then
aux = 0;
aux2 = 1;
end if;
end if;
clk_out <= aux2;
end process;
end;
What will be the frequency of the new clock(clk_out) ?
Clock dividers come in many flavors.
If you are looking at high speed clocks, for instance when using dual-data rate (DDR) memory, you actually want to use the FPGA's clock manager. E.g. Xilinx Digital Clock Manager (DCM). These provide a very stable, edge synchronous clock output.
For lower speed clocks, you could use the divider you suggest. However, these also come in multiple flavors. If the division ratio is integer, you can use the simple counter like you do. For this next example, the clock divider will always divide the input frequency by 2 (e.g. 50 MHz-> 25 MHz) and then further divide by the ratio set (e.g. 25/3 = 8 1/3 MHz)
library ieee;
use ieee.std_logic_1164.all;
entity simp_clk_div is
generic(
half_clk_div_ratio : positive);
port(
input_clk : in std_logic;
output_clk : out std_logic);
end entity;
architecture rtl of simp_clk_div is
constant clk_div_cnt : natural := half_clk_div_ratio - 1;
signal cnt : natural := clk_div_cnt;
signal output_clk_i : std_logic := '0';
begin
divide : process(input_clk) begin
if rising_edge(input_clk) then
if cnt = 0 then
cnt <= clk_div_cnt;
output_clk_i <= not output_clk_i;
else
cnt <= cnt - 1;
end if;
end if;
end process;
output_clk <= output_clk_i;
end architecture;
entity simp_clk_div_tb is end entity;
library ieee;
architecture behavior of simp_clk_div_tb is
use ieee.std_logic_1164.all;
signal input_clk, output_clk : std_logic;
begin
DUT : entity work.simp_clk_div
generic map(
clk_div_ratio => 3)
port map(
input_clk => input_clk,
output_clk => output_clk);
clk_stim : process begin
input_clk <= '0', '1' after 1 ns;
wait for 2 ns;
if (now > 200 ns) then wait; end if;
end process;
end architecture;
If you want more freedom, e.g. convert 50MHz to 3 MHz, you can use a fractional clock divider. However, this component requires a lot more resources. Plus, there's a lot of jitter on the clock output, in the form of unequal length clock pulses. But that's usually not a big problem with low speed clocks.
library ieee;
use ieee.std_logic_1164.all;
entity frac_clk_div is
generic(
input_freq : positive;
output_freq : positive);
port(
input_clk : in std_logic;
output_clk : out std_logic);
end entity;
architecture rtl of frac_clk_div is
constant cnt_sub : positive := output_freq*2;
signal cnt : natural := input_freq;
signal output_clk_i : std_logic := '0';
begin
divide : process(input_clk) begin
if rising_edge(input_clk) then
if cnt < cnt_sub then
cnt <= input_freq - (cnt_sub - cnt);
output_clk_i <= not output_clk_i;
else
cnt <= cnt - cnt_sub;
end if;
end if;
end process;
output_clk <= output_clk_i;
end architecture;
entity frac_clk_div_tb is end entity;
library ieee;
architecture behavior of frac_clk_div_tb is
use ieee.std_logic_1164.all;
signal input_clk, output_clk : std_logic;
begin
DUT : entity work.frac_clk_div
generic map(
input_freq => 50_000_000,
output_freq => 3_000_000)
port map(
input_clk => input_clk,
output_clk => output_clk);
clk_stim : process begin
input_clk <= '0', '1' after 1 ns;
wait for 2 ns;
if (now > 200 ns) then wait; end if;
end process;
end architecture;

Simple VHDL clocked counter simulation confusion

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

digital circuit scheme to vhdl ring counter multiplexer

I have this circuit that I want to implement in vhdl. There is a clock input and which clock event changes the 1 pin output sequentially. 0001 -> 0010 -> 0100 -> 1000 ...
I wondering what is the correct approach to do that. I could do that with multiple ifs and elsifs and an integer counter signal. Sorry for the noob question, is there a name for this kind of circuit?
It appears from your description this intended to be a ring counter. Your gates seem superfluous:
library ieee;
use ieee.std_logic_1164.all;
entity ring_counter is
port (
clk: in std_logic;
q: out std_logic_vector (0 to 3)
);
end entity;
architecture your_representation of ring_counter is
signal qint: std_logic_vector (0 to 3) := "0000";
signal all_zero: std_logic;
begin
YOURS:
process(clk)
begin
if rising_edge(clk) then
qint(0) <= qint(3);
qint(1) <= all_zero or qint(0);
qint (2 to 3) <= qint(1 to 2);
end if;
end process;
all_zero <= '1' when qint = "0000" else
'0';
q <= (qint(0) or all_zero) & qint(1 to 3);
end architecture;
With a test bench:
library ieee;
use ieee.std_logic_1164.all;
entity ring_counter_tb is
end entity;
architecture foo of ring_counter_tb is
signal clk: std_logic := '0';
signal q: std_logic_vector(0 to 3);
begin
DUT:
entity work.ring_counter(your_representation)
port map (
clk => clk,
q => q
);
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if Now > 200 ns then
wait;
end if;
end process;
end architecture;
Gives:
(clickable)
While a classic ring counter:
architecture classic of ring_counter is
signal qint: std_logic_vector (0 to 3) := "1000";
begin
RING_CTR:
process(clk)
begin
if rising_edge(clk) then
qint <= qint(3) & qint(0 to 2);
end if;
end process;
q <= qint;
end architecture;
(and modified test bench):
entity work.ring_counter(classic)
gives:
(clickable)
And the starting phase is all in the initial condition.

Resources