UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Visitor monah
Visitor
322 Views
Registered: ‎01-06-2020

Simulation of a Counter (1kHz, hex)

Jump to solution

Hi,

I'm new to this forum (and also new to VHDL) and would really appreciate any kind of help because i'm struggling with a problem since two days. I programmed a counter (with a Basys 3 board, the counter counts from "0000" to "FFFF" up and down implemented via switches, there is also one switch to hold the counter and also a synchronous reset). It is realized on a 7-segment via Vivado.  I crated the .vhd file as well as a testbench. And this is where the problem is: the code works so am able to realize it on the 7-segment display (and it counts!) but not able to simulate it with a testbench. The compilation and the simulation works but the counter is not counting. It just show "0000" for the counter. (on ModelSim 10.5)

 

Does anyone know where the problem is? (probably in the testbench because it is working on the board but maybe i'm just lucky)

I'm really thankful for any kind of help!

This is my code so far (separated in the .vhd file and the testbench:


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity cntr is
port (clk_i : in std_logic; -- 100 MHz clock
reset_i : in std_logic; -- asynchronous reset
cntrup_i : in std_logic; -- counts up if signal is '1'
cntrdown_i : in std_logic; -- counts down if signal is '1'
cntrreset_i : in std_logic; -- sets counter to 0x0 if signal is '1'
cntrhold_i : in std_logic; -- holds count value if signal is '1'
cntr_1khZ_i : in std_logic; -- counter frequenz 1kHz
cntr0_o : out std_logic_vector(3 downto 0); -- digit 0 (from internal logic)
cntr1_o : out std_logic_vector(3 downto 0); -- digit 1 (from internal logic)
cntr2_o : out std_logic_vector(3 downto 0); -- digit 2 (from internal logic)
cntr3_o : out std_logic_vector(3 downto 0)); -- digit 3 (from internal logic)
end cntr;

architecture rtl of cntr is
-- signals declared for interconnection
signal s_cntr_hex_i : std_logic_vector(15 downto 0) := x"0000"; -- hex counter type so memory variable
signal s_helpcntr : std_logic_vector(15 downto 0); -- help counter to separate 100MhZ clock (100MHz/1kHz)
signal s_frequactive : std_logic; -- signal is 1 after reaching freuqence

-- constant for frequenc (1kHz) declared
constant c_1kHz : std_logic_vector(16 downto 0) := "11000011010100000";
-- constant c_1kHz : std_logic_vector(27 downto 0) := "0000000000011000011010100000"; -- constant for Simulation (Testbench)
begin
-- generate 1kHz clock signal (let counter count until it reache value c_1kHz and then starts counter)
p_clk_gen: process(clk_i, reset_i)
begin
if(reset_i = '1') then -- if reset active
s_helpcntr <= "0000000000000000"; -- set value to 0
s_frequactive <= '0'; -- set 1kHz signal low
elsif(clk_i'event and clk_i = '1') then -- rising egde
s_frequactive <= '1';
if(s_helpcntr >= c_1kHz) then -- when count has been reach
s_frequactive <= '0'; -- enable clock
s_helpcntr <= "0000000000000000";
else
s_helpcntr <= std_logic_vector(unsigned (s_helpcntr)+1); -- increment the counter
end if;
end if;
end process p_clk_gen;

p_counter: process(clk_i, reset_i)
begin
if(reset_i = '1') then -- asynchronous reset to 0
s_cntr_hex_i <= "0000000000000000"; -- reset internal hex counter
elsif (clk_i'event and clk_i = '1') then -- rising clock edge
if(s_frequactive = '1') then -- if counter active
if(cntrreset_i = '1') then -- counter auf 0 setzen
s_cntr_hex_i <= "0000000000000000";
elsif(cntrup_i = '1' and cntrhold_i = '0') then -- counter up
if(s_cntr_hex_i = "1111111111111111") then -- if the signal is 1kHz
s_cntr_hex_i <= "0000000000000000"; -- reset internal counter
else
s_cntr_hex_i <= std_logic_vector(unsigned (s_helpcntr)+1); -- count up
end if;
elsif(cntrdown_i = '1' and cntrhold_i = '0' and cntrhold_i = '0') then -- counter down
if(s_cntr_hex_i = "0000000000000000") then
s_cntr_hex_i <= "1111111111111111";
else
s_cntr_hex_i <= std_logic_vector(unsigned (s_helpcntr)-1); -- count down
end if;
end if;
end if;
end if;
end process p_counter;
cntr0_o <= s_cntr_hex_i(3 downto 0); -- 1. hex
cntr1_o <= s_cntr_hex_i(7 downto 4); -- 2. hex
cntr2_o <= s_cntr_hex_i(11 downto 8); -- 3. hex
cntr3_o <= s_cntr_hex_i(15 downto 12); -- 4. hex

end rtl;

 

The Testbench:

architecture sim of tb_cntr is

component cntr
port (clk_i : in std_logic; -- 100 MHz clock
reset_i : in std_logic; -- asynchronous reset
cntrup_i : in std_logic; -- counts up if signal is '1'
cntrdown_i : in std_logic; -- counts down if signal is '1'
cntrreset_i : in std_logic; -- sets counter to 0x0 if signal is '1'
cntrhold_i : in std_logic; -- holds count value if signal is '1'
cntr_1khZ_i : in std_logic; -- counter frequenz 1kHz
cntr0_o : out std_logic_vector(3 downto 0); -- digit 0 (from internal logic)
cntr1_o : out std_logic_vector(3 downto 0); -- digit 1 (from internal logic)
cntr2_o : out std_logic_vector(3 downto 0); -- digit 2 (from internal logic)
cntr3_o : out std_logic_vector(3 downto 0)); -- digit 3 (from internal logic)
end component;

signal s_cntr_1khZ_i : std_logic := '1';
signal s_clk_i : std_logic := '0';
signal s_reset_i : std_logic := '1';
signal s_cntrup_i : std_logic := '1';
signal s_cntrdown_i : std_logic := '0';
signal s_cntrreset_i : std_logic := '0';
signal s_cntrhold_i : std_logic := '1';
signal s_cntr0_o : std_logic_vector(3 downto 0) := x"0";
signal s_cntr1_o : std_logic_vector(3 downto 0) := x"0";
signal s_cntr2_o : std_logic_vector(3 downto 0) := x"0";
signal s_cntr3_o : std_logic_vector(3 downto 0) := x"0";

begin

i_cntr : cntr
port map
(clk_i => s_clk_i,
reset_i => s_reset_i,
cntrup_i => s_cntrup_i,
cntrdown_i => s_cntrdown_i,
cntrreset_i => s_cntrreset_i,
cntrhold_i => s_cntrhold_i,
cntr_1khZ_i => s_cntr_1khZ_i,
cntr0_o => s_cntr0_o,
cntr1_o => s_cntr1_o,
cntr2_o => s_cntr2_o,
cntr3_o => s_cntr3_o);

s_clk_i <= not s_clk_i after 50 ns;
s_reset_i <= '0' after 150 ms;

p_test : process
begin
-- count up
s_cntrreset_i <= '0';
s_cntrup_i <= '1';
s_cntrhold_i <= '0';
s_cntrdown_i <= '0';
s_cntr_1khZ_i <= '1';
wait for 10 ms;
-- count down
s_cntrreset_i <= '0';
s_cntrhold_i <= '0';
s_cntrup_i <= '0';
s_cntrdown_i <= '1';
s_cntr_1khZ_i <= '1';
wait for 10 ms;
-- count hold
s_cntrreset_i <= '0';
s_cntrup_i <= '1';
s_cntrhold_i <= '1';
s_cntrdown_i <= '0';
s_cntr_1khZ_i <= '1';
wait for 10 ms;
-- reset
s_cntrreset_i <= '1';
s_cntrup_i <= '1';
s_cntrhold_i <= '0';
s_cntrdown_i <= '0';
s_cntr_1khZ_i <= '1';
wait for 10 ms;
end process;
end sim;

 

 

0 Kudos
1 Solution

Accepted Solutions
Teacher drjohnsmith
Teacher
293 Views
Registered: ‎07-09-2009

Re: Simulation of a Counter (1kHz, hex)

Jump to solution
Id change to rising_edge now, as good practice,

line with s_helpcntr >= c_1kHz
VHDL is very pedantic.
you probably have a warning about this in the report.


Your comparing two different size vectors, this is not C, size matters.
You need to make them both the same size.

A tip or two.

instead of s_helpcntr <= "0000000000000000"
use s_helpcntr <= ( others => '0');
then you don't have to get the right number of '0',,,

Its also VERY 1980's style to have the entity and architecture in separate files , put them both in one file,

Also think carefully about the s_helpcntr >= c_1kHz statment in general.

A ">=" takes more logic than a simple compare,
or even less logic, make the counter count down, and check for zero. Thats an OR gate , which is very efficient logic.

Id also suggest , instead of this
std_logic_vector(16 downto 0) := "11000011010100000";

try

std_logic_vector(16 downto 0) := B"1_1000_0110_1010_0000";

its a good habit to get into, its explicit, which is the VHDL way, and by splinting into blocks of 4, is less likely you will get the wrong number of bits. ( a really common and annoying error )


<== If this was helpful, please feel free to give Kudos, and close if it answers your question ==>

View solution in original post

6 Replies
Teacher drjohnsmith
Teacher
313 Views
Registered: ‎07-09-2009

Re: Simulation of a Counter (1kHz, hex)

Jump to solution
Can you show us a snapshot of the simulation waveform please.

You have your reset active for 150 milli seconds, thats a long time to wait in the simulation, a few of the 100 MHz clock would be normal.

And on my hobby horse,

do not use (clk_i'event and clk_i = '1')
use rising_edge( clk_i)
Any teacher that teaches the 'event should be retired, and any book that teaches 'event should be put in bin, 'event has not been used for clocking for at least 20 years, and it just shows how little the source has kept up to date.

One other thing, if you post the code as attachment, then its much easier for us to look at it in an editor.



<== If this was helpful, please feel free to give Kudos, and close if it answers your question ==>
Visitor monah
Visitor
308 Views
Registered: ‎01-06-2020

Re: Simulation of a Counter (1kHz, hex)

Jump to solution

Hi John,

 

Thank you for your answer and your tips!

For future projects i will just use risingedge then.

I changed now the reset to 1 ms at the beginning and then i just put it to '0' after 1 ms.

Please find also a snapshot as well as the code in the attachment.

On the snapshot i cant recognize that the counter is counting...

 

 

picture.PNG
0 Kudos
Teacher drjohnsmith
Teacher
294 Views
Registered: ‎07-09-2009

Re: Simulation of a Counter (1kHz, hex)

Jump to solution
Id change to rising_edge now, as good practice,

line with s_helpcntr >= c_1kHz
VHDL is very pedantic.
you probably have a warning about this in the report.


Your comparing two different size vectors, this is not C, size matters.
You need to make them both the same size.

A tip or two.

instead of s_helpcntr <= "0000000000000000"
use s_helpcntr <= ( others => '0');
then you don't have to get the right number of '0',,,

Its also VERY 1980's style to have the entity and architecture in separate files , put them both in one file,

Also think carefully about the s_helpcntr >= c_1kHz statment in general.

A ">=" takes more logic than a simple compare,
or even less logic, make the counter count down, and check for zero. Thats an OR gate , which is very efficient logic.

Id also suggest , instead of this
std_logic_vector(16 downto 0) := "11000011010100000";

try

std_logic_vector(16 downto 0) := B"1_1000_0110_1010_0000";

its a good habit to get into, its explicit, which is the VHDL way, and by splinting into blocks of 4, is less likely you will get the wrong number of bits. ( a really common and annoying error )


<== If this was helpful, please feel free to give Kudos, and close if it answers your question ==>

View solution in original post

Teacher drjohnsmith
Teacher
290 Views
Registered: ‎07-09-2009

Re: Simulation of a Counter (1kHz, hex)

Jump to solution
this line looks wrong as well

cntrdown_i = '1' and cntrhold_i = '0' and cntrhold_i = '0')
<== If this was helpful, please feel free to give Kudos, and close if it answers your question ==>
Highlighted
Visitor monah
Visitor
266 Views
Registered: ‎01-06-2020

Re: Simulation of a Counter (1kHz, hex)

Jump to solution

Thank you very much for the useful tips.

The simulation is working now.

I will implement the better coding style and hopefully i will be a good programmer one day :)

 

Thank you again!

Teacher drjohnsmith
Teacher
150 Views
Registered: ‎07-09-2009

Re: Simulation of a Counter (1kHz, hex)

Jump to solution
Well done,
I can assure you my original coding was a lot worse than yours,
you will soon pick up a sub set that works for you,

VHDL is very picky about getting the basics right, but IMHO its the best way. That would have been a warning in your report, you need to always look over them, no matter how many the Xilinx IP blocks chuck up, As you have seen , the Verilog way, of finding things in simulation is IMHO a lot more risky,

SystemVerilog seems if you use a restricted set of instructions a good way forward.
<== If this was helpful, please feel free to give Kudos, and close if it answers your question ==>
0 Kudos