FSM problem vhdl AES encryption not entering in third state? - encryption

I had to code the encryption of AES using VHDL and it should compile to succeed the course!!!
I'm having some troubles , FSM isn't entering in the third state!
THIS is the code of FSM:
-- MOORE
library ieee;
use ieee.std_logic_1164.all;
library LIB_RTL ;
library LIB_AES;
use LIB_AES.crypt_pack.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity FSM is
port (
resetb_i : in std_logic ;
clock_i : in std_logic ;
end_key_expander_i : in std_logic ;
start_i : in std_logic;
enableMixcolumns_o : out std_logic;
enableOutput_o : out std_logic;
enableRoundcomputing_o: out std_logic;
reset_key_expander_o: out std_logic;
round_key_expander_o : out std_logic_vector(3 downto 0);
start_key_expander_o : out std_logic;
done_o : out std_logic );
end entity FSM ;
architecture FSM_arch of FSM is
-- definition du type enumere
type state is (idle , keyexpander , initialround , mainround , lastround, ENCoutput );
-- definition des signaux
signal etat_present , etat_futur : state := idle;
signal init_input : std_logic;
signal count_output : bit4;
signal enable_input : std_logic;
component Counter
port (enable_i : in std_logic;
clock_i : in std_logic;
reset_i : in std_logic;
init_i : in std_logic;
count_o : out bit4);
end component;
begin -- moore_arch
DUT : Counter
port map(
enable_i => enable_input,
clock_i => clock_i,
reset_i => resetb_i,
init_i => init_input,
count_o => count_output
);
seq_0 : process (clock_i , resetb_i )
begin -- process seq_0
if resetb_i = '0' then
etat_present <= keyexpander ;
elsif clock_i' event and clock_i = '1' then
etat_present <= etat_futur ;
end if;
end process seq_0 ;
comb0 : process ( etat_present , start_i , end_key_expander_i ) is
begin -- process comb0
case etat_present is
when idle =>
if (start_i = '1') then
etat_futur <= keyexpander ;
else
etat_futur <= idle ;
end if;
when keyexpander =>
if end_key_expander_i = '1' then
etat_futur <= initialround ;
else
etat_futur <= keyexpander ;
end if;
when initialround =>
if (count_output = "0000") then --round0 : start round execution
etat_futur <= initialround ;
else if count_output > "0000" then
etat_futur <= mainround;
end if;
end if;
when mainround =>
if count_output < "1010" then --round1 to round9 : rounds execution
etat_futur <= mainround ;
else if count_output ="1001" then
etat_futur <= lastround ;
end if;
end if;
when lastround =>
if count_output < "1010" then --round10 : last round
etat_futur <= lastround ;
else if count_output ="1010" then
etat_futur <= ENCoutput ;
end if;
end if;
when ENCoutput =>
if start_i = '0' then
etat_futur <= ENCoutput ;
else
etat_futur <= keyexpander ;
end if;
end case ;
end process comb0 ;
-- Output logic of the VHDL MOORE FSM
comb1 : process ( etat_present )
begin -- proceenableMixcolumns_o : out std_logic;
case etat_present is
when idle => --repos
enableMixcolumns_o <= '0';
enableOutput_o <='0';
enableRoundcomputing_o <='0';
reset_key_expander_o <='0';
round_key_expander_o <=count_output;
start_key_expander_o <='0';
done_o <= '0';
when keyexpander => --start key expander
enableMixcolumns_o <= '0';
enableOutput_o <='0';
enableRoundcomputing_o <='0';
reset_key_expander_o <='0';
round_key_expander_o <= count_output;
start_key_expander_o <='1';
done_o <= '0';
when initialround =>
enableMixcolumns_o <= '0';
enableOutput_o <='0';
enableRoundcomputing_o <='1'; --1 for round0
reset_key_expander_o <='0';
round_key_expander_o <=count_output;
start_key_expander_o <='0';
done_o <= '0';
when mainround =>
enableMixcolumns_o <= '1';
enableOutput_o <='0'; --not done
enableRoundcomputing_o <='0'; --0 for round1-->round9
reset_key_expander_o <='0';
round_key_expander_o <=count_output; --start counting rounds
start_key_expander_o <='0'; --done
done_o <= '0';
when lastround =>
enableMixcolumns_o <= '0';
enableOutput_o <='0'; --not done
enableRoundcomputing_o <='0'; --0 for round10
reset_key_expander_o <='0';
round_key_expander_o <=count_output; --10 rounds
start_key_expander_o <='0'; --done
done_o <= '0';
when ENCoutput =>
enableMixcolumns_o <= '0'; --no mixcolumn last round
enableOutput_o <='1'; --done
enableRoundcomputing_o <='0';
reset_key_expander_o <='1';
round_key_expander_o <=count_output; --reset counting
start_key_expander_o <='0';
done_o <= '1';
end case ;
end process comb1 ;
end architecture FSM_arch;
library ieee;
use ieee.std_logic_1164.all;
library LIB_RTL ;
library LIB_AES;
use LIB_AES.crypt_pack.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity Counter is
port (enable_i : in std_logic;
clock_i : in std_logic;
reset_i : in std_logic;
init_i : in std_logic;
count_o : out bit4);
end Counter;
architecture Counter_arch of Counter is
signal counter_s : bit4;
begin
count_o <= counter_s;
seq_0 : process (clock_i, reset_i,enable_i,init_i) is
begin -- process seq_0
if reset_i = '0' then -- asynchronous reset (active-low)
counter_s <= X"0";
elsif clock_i'event and clock_i = '1' then -- rising clock
if (enable_i = '1') then
if (init_i = '1') then
counter_s <= X"0";
else
counter_s <= counter_s + 1;
end if;
else
counter_s <= counter_s;
end if;
end if;
end process seq_0;
end Counter_arch;
The problem appears in the simulation, I'm having start_key_expander_o <='1'; which means it's in the state keyexpander! And enableRoundcomputing_o <='0'; is always 0 which means it's not entering in state: initialround!
I can't understand my mistake...
library ieee;
use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;
Use ieee.std_logic_unsigned.all;
library LIB_RTL ;
library LIB_AES;
use LIB_AES.crypt_pack.all;
ENTITY FSM_tb IS
END FSM_tb;
ARCHITECTURE FSM_tb_arch OF FSM_tb IS
-- Component Declaration for the Moore FSM
COMPONENT FSM
port (
resetb_i : in std_logic ;
clock_i : in std_logic ;
end_key_expander_i : in std_logic ;
start_i : in std_logic;
enableMixcolumns_o : out std_logic;
enableOutput_o : out std_logic;
enableRoundcomputing_o: out std_logic;
reset_key_expander_o: out std_logic;
round_key_expander_o : out std_logic_vector(3 downto 0);
start_key_expander_o : out std_logic;
done_o : out std_logic );
END COMPONENT;
component Counter
port (enable_i : in std_logic;
clock_i : in std_logic;
reset_i : in std_logic;
init_i : in std_logic;
count_o : out bit4);
end component;
--Inputs
signal clock_input : std_logic := '0';
signal resetb_input : std_logic := '1';
signal end_key_expander_input : std_logic := '0';
signal start_input : std_logic := '1';
signal init_input : std_logic :='0';
signal enable_input : std_logic :='1';
--Outputs
signal enableMixcolumns_output : std_logic;
signal enableOutput_output : std_logic := '0';
signal enableRoundcomputing_output : std_logic := '0';
signal reset_key_expander_output : std_logic := '0';
signal round_key_expander_output : std_logic_vector(3 downto 0) := "0000";
signal start_key_expander_output : std_logic := '0';
signal done_output : std_logic := '0';
signal count_output : bit4;
BEGIN
-- Instantiate the Moore FSM
uut: FSM PORT MAP (
resetb_i => resetb_input,
clock_i => clock_input,
end_key_expander_i => end_key_expander_input,
start_i => start_input,
enableMixcolumns_o => enableMixcolumns_output,
enableOutput_o => enableOutput_output,
enableRoundcomputing_o => enableRoundcomputing_output,
reset_key_expander_o => reset_key_expander_output,
round_key_expander_o => round_key_expander_output,
start_key_expander_o => start_key_expander_output,
done_o => done_output
);
DUT : Counter
port map(
enable_i => enable_input,
clock_i => clock_input,
reset_i => resetb_input,
init_i => init_input,
count_o => count_output
);
-- Clock process definitions
clock_input <= not clock_input after 5 ns;
process
begin
wait until clock_input = '1';
resetb_input <= '0';
wait;
end process;
-- Stimulus process
stim_proc: process
begin
wait until clock_input = '1';
-- e2
end_key_expander_input <= '1' ;
start_input <= '0';
wait for 40 ns;
-- fin
end_key_expander_input <= '0' ;
enable_input <= '0';
init_input <= '1';
start_input <= '0';
wait for 20 ns;
done_output <='1';
-- insert stimulus here
wait;
end process;
END;

Related

Button debouncing circuit full count based:

i am trying to practice debouncing on FPGA following the approach (full count based), that introduced in the book from Volnei ("Circuit Design with VHDL third edition").
A very important feature of this circuit is the way the timer is constructed, which eliminates the need for a comparator (a large circuit).
For example, for the numeric values just given, $S = 50,MHz * 20,ms= 10e6$ results, where the number of bits (DFFs) in the counter is $N= log_2(S) = 20$ implying a counter running from zero to $10e6 - 1$ = 1 1 1 1_0100_0010_00 1 1_1 1 1 1, thus requiring a comparator that is at least 12 bits wide (only the s need to be monitored), which is indeed a large circuit. This can be avoided by taking into consideration that the time does not need to be exact in debouncers, so if an extra bit (flip-flop) is included in the counter, its MSB alone can play the role of comparator; when MSB= 1 occurs, it enables the output register, so y is updated, leading subsequently to clear= 1, which zeros the counter (and therefore the MSB too) at the next positive clock edge. In summary, the counter spans a total of $ S = 2^N+ 1$ states, leading to $T{deb} = 2^N/f_{clk (50MHz)} = 21 ms$ for the numeric values given above.
However, testing the code given from this Example not giving the expected result.
Debouncing
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE IEEE.math_real.ALL;
ENTITY E13_button_debouncer IS
GENERIC (
T_DEB_MS : NATURAL := 25;
f_clk : NATURAL := 50_000);
PORT (
clk : IN STD_LOGIC;
rst : IN STD_LOGIC;
b_in : IN STD_LOGIC;
b_out : OUT STD_LOGIC
);
END E13_button_debouncer;
ARCHITECTURE single_switch OF E13_button_debouncer IS
CONSTANT COUNTER_BITS : NATURAL := 1 + INTEGER(ceil(log2(real(T_DEB_MS * f_clk))));
-- ! Optional :
SIGNAL x_reg : STD_LOGIC;
BEGIN
proc_name : PROCESS (clk)
VARIABLE count : unsigned(COUNTER_BITS - 1 DOWNTO 0);
BEGIN
IF rising_edge(clk) THEN
IF rst = '0' THEN
count := (OTHERS => '0');
x_reg <= '0';
b_out <= '0';
ELSE
x_reg <= b_in;
IF b_out = x_reg THEN
count := (OTHERS => '0');
ELSE
count := count + 1;
END IF;
END IF;
END IF;
IF falling_edge(clk) THEN
IF count(COUNTER_BITS - 1) THEN
b_out <= NOT b_out;
END IF;
END IF;
END PROCESS proc_name;
END ARCHITECTURE;
Test Bench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY E13_button_debouncer_tb IS
END E13_button_debouncer_tb;
ARCHITECTURE sim OF E13_button_debouncer_tb IS
CONSTANT clk_hz : INTEGER := 50_000;
CONSTANT clk_period : TIME := 1 sec / clk_hz;
CONSTANT T_DEB_MS : NATURAL := 25;
SIGNAL clk : STD_LOGIC := '1';
SIGNAL rst : STD_LOGIC := '0';
SIGNAL b_in : STD_LOGIC := '0';
SIGNAL b_out : STD_LOGIC := '1';
BEGIN
clk <= NOT clk AFTER clk_period / 2;
bu_deboun : ENTITY work.E13_button_debouncer(single_switch)
GENERIC MAP(f_clk => clk_hz, T_DEB_MS => T_DEB_MS)
PORT MAP(
clk => clk,
rst => rst,
b_in => b_in,
b_out => b_out
);
SEQUENCER_PROC : PROCESS
BEGIN
WAIT FOR clk_period * 1;
rst <= '1';
b_in <= '1';
WAIT FOR 1 ms;
b_in <= '0';
WAIT FOR 1 ms;
b_in <= '1';
WAIT FOR 100 ms;
b_in <= '0';
WAIT FOR 1 ms;
b_in <= '1';
WAIT FOR 10 ms;
b_in <= '0';
WAIT FOR 10 ms;
END PROCESS;
END ARCHITECTURE;
Simulation
I expepct that the code work like photo below:
to solve the problem first to avoid errors when synthesize it need the changes to the code thanks to (#thebusybee, #user16145658,#MatthiasSchweikart):
BEGIN
IF rising_edge(clk) THEN
IF rst = '0' THEN
count := (OTHERS => '0');
x_reg <= '0';
ELSE
x_reg <= b_in;
IF b_out = x_reg THEN
count := (OTHERS => '0');
ELSE
count := count + 1;
END IF;
END IF;
END IF;
IF falling_edge(clk) THEN
IF rst = '0' THEN
b_out <= '0';
ELSE
REPORT "we are in falling edge and the counter value : " & INTEGER'image(to_integer(count));
IF count(COUNTER_BITS - 1) THEN
b_out <= NOT b_out;
END IF;
END IF;
END IF;
END PROCESS proc_name;
END ARCHITECTURE;
the problem was here:
GENERIC (
T_DEB_MS : NATURAL := 25;
f_clk : NATURAL := 50_000);
PORT (
clk : IN STD_LOGIC;
rst : IN STD_LOGIC;
b_in : IN STD_LOGIC;
b_out : OUT STD_LOGIC
);
END E13_button_debouncer;
ARCHITECTURE single_switch OF E13_button_debouncer IS
CONSTANT COUNTER_BITS : NATURAL := 1 + INTEGER(ceil(log2(real(T_DEB_MS * f_clk))));
which result in N=21 that mean the debounce time will be 41 Second. so to solve it i should do it like this : 0.025 * fclk = 1250 => result in N= 10 => +1 =11.
then the counter will count till 2048 resulting in debounce time von 40 ms. which is ok for my application.

Debounce Code Correction for a Decimal Counter Project in 1Hz counting Speed

I am completly new for the FPGA and basys3 development board.
I have a project for Counter on the 7 segment displays on the board.
We got 3 different layers as a design.
cntr /
cntr_rtl /
cntr_top /
cntr_top_struc /
io_ctrl /
io_ctrl_rtl /
And in the project it has to diplay on the 7 segment controlled by the switches : count up/count down / hold / reset options:
The priorities for these switches are:
reset
hold
count direction
top level VHDL file cntr_top.vhd
Port Name Direction Description
clk_i In System clock (100 MHz)
reset_i In Asynchronous high active reset
sw_i(15:0) In 16 switches
pb_i(3:0) In 4 buttons
ss_o(7:0) Out Contain the value for all 7-segment digits
ss_sel_o(3:0) Out Select a 7-segment digit
io_ctrl
clk_i In System clock (100 MHz)
reset_i In Asynchronous high active reset
cntr0_i(n:0) In Digit 0 (from internal logic)
cntr1_i(n:0) In Digit 1 (from internal logic)
cntr2_i(n:0) In Digit 2 (from internal logic)
cntr3_i(n:0) In Digit 3 (from internal logic)
sw_i(15:0) In 16 switches (from FPGA board)
pb_i(3:0) In 4 buttons (from FPGA board)
ss_o(7:0) Out to 7-segment displays of the FPGA board
ss_sel_o(3:0) Out Selection of a 7-segment digit
swclean_o(15:0) Out 16 switches (to internal logic)
pbclean_o(3:0) Out 4 buttons (to internal logic)
cntr.vhd
clk_i In System clock (100 MHz)
reset_i In Asynchronous high active reset
cntrup_i In Counts up if signal is ‘1’
cntrdown_i In Counts down if signal is ‘1’
cntrreset_i In Sets counter to 0x0 if signal is ‘1’
cntrhold_i In Holds count value if signal is ‘1’
cntr0_o(n:0) Out Digit 0 (from internal logic)
cntr1_o(n:0) Out Digit 1 (from internal logic)
cntr2_o(n:0) Out Digit 2 (from internal logic)
cntr3_o(n:0) Out Digit 3 (from internal logic)
I will attach also the file to the attachment. Now my code is working and do all the funcitionality correct but there is only one issue which is the DEBOUNCE code part.
I didnt use the clk signal for the code and i have to change it. The certain given clock signal has to be used.
So can any be give me suggestions how i can correct the debounce concept in the code.
io_ctrl_rtl.vhd -code down below:
library IEEE;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
architecture rtl of io_ctrl is
constant COUNTVALUE : std_logic_vector(16 downto 0):= "01100001101010000";
signal s_enctr : std_logic_vector(16 downto 0):="00000000000000000";
signal s_2khzen : std_logic :='0';
signal s_1hzen : std_logic :='0';
signal s_2khzcount : std_logic_vector(3 downto 0) := "0000";
signal swsync0 : std_logic_vector(15 downto 0):="0000000000000000";
signal pbsync0 : std_logic_vector(3 downto 0):="0000";
signal swsync1 : std_logic_vector(15 downto 0):="0000000000000000";
signal pbsync1 : std_logic_vector(3 downto 0):="0000";
signal swtmp : std_logic_vector(15 downto 0):="0000000000000000";
signal pbtmp : std_logic_vector(3 downto 0):="0000";
signal swdebounced : std_logic_vector(15 downto 0):="0000000000000000";
signal pbdebounced : std_logic_vector(3 downto 0):="0000";
signal s_ss_sel : std_logic_vector(3 downto 0) := "0000";
signal s_ss : std_logic_vector(7 downto 0) := "00000000";
begin -- rtl
-----------------------------------------------------------------------------
--
-- Synchronize the inputs
--
-----------------------------------------------------------------------------
p_sync: process (clk_i, reset_i)
begin
if reset_i = '1' then
swsync0 <= (others => '0');
pbsync0 <= (others => '0');
swsync1 <= (others => '0');
pbsync1 <= (others => '0');
elsif clk_i'event and clk_i = '1' then
swsync0 <= sw_i;
pbsync0 <= pb_i;
swsync1 <= swsync0;
pbsync1 <= pbsync0;
else null;
end if;
end process;
-----------------------------------------------------------------------------
--
-- Generate 1 KHz enable signal.
--
-----------------------------------------------------------------------------
p_slowen: process (clk_i, reset_i)
begin
if reset_i = '1' then
s_enctr <= (others => '0');
s_2khzen <= '0';
elsif clk_i'event and clk_i = '1' then
if s_enctr = COUNTVALUE then -- When the terminal counter is reached, set the release flag and reset the counter
s_enctr <= (others => '0');
s_2khzen <= '1';
s_2khzcount <= std_logic_vector(to_unsigned(to_integer(unsigned( s_2khzcount )) + 1, 4));
else
s_enctr <= std_logic_vector(to_unsigned(to_integer(unsigned( s_enctr )) + 1, 17)); -- As long as the terminal count is not reached: increment the counter.
if s_2khzen = '1' then
s_2khzen <= '0';
end if;
end if;
if s_2khzcount = "1010" then
s_1hzen <= not s_1hzen;
s_2khzcount <= "0000";
end if;
end if;
end process p_slowen;
-----------------------------------------------------------------------------
--
-- Debounce buttons and switches
--
-----------------------------------------------------------------------------
p_debounce: process (s_1hzen, reset_i)
variable dbouncecntr : integer:=0;
begin
if reset_i = '1' then
swdebounced <= "0000000000000000";
pbdebounced <= "0000";
dbouncecntr :=0; -- Change clocking the process with signal from sens list.
else
if (dbouncecntr = 0) then
swtmp <= swsync1;
pbtmp <= pbsync1;
dbouncecntr := dbouncecntr + 1;
elsif (dbouncecntr = 1) then
if (swtmp = swsync1) then
swdebounced <= swsync1;
end if;
if (pbtmp = pbsync1) then
pbdebounced <= pbsync1;
end if;
dbouncecntr := 0;
end if;
end if;
end process p_debounce;
swclean_o <= swdebounced;
pbclean_o <= pbdebounced;
-----------------------------------------------------------------------------
--
-- Display controller for the 7-segment display
--
-----------------------------------------------------------------------------
p_displaycontrol: process (clk_i, reset_i)
variable v_scancnt : std_logic_vector(1 downto 0):= "00";
variable v_output : std_logic_vector(3 downto 0):="0000";
begin
if reset_i = '1' then
v_scancnt := "00";
s_ss <= "00000000";
elsif clk_i'event and clk_i = '1' then
if s_2khzen = '1' then
case v_scancnt is
when "00" =>
v_output := cntr0_i;
s_ss_sel <= "0001";
when "01" =>
v_output := cntr1_i;
s_ss_sel <= "0010";
when "10" =>
v_output := cntr2_i;
s_ss_sel <= "0100";
when "11" =>
v_output := cntr3_i;
s_ss_sel <= "1000";
when others =>
v_output := "1111";
s_ss_sel <= "0001";
end case;
case v_output is --ABCDEFG,
when "0000" => s_ss <= "11111100"; --0
when "0001" => s_ss <= "01100000"; --1
when "0010" => s_ss <= "11011010"; --2
when "0011" => s_ss <= "11110010"; --3
when "0100" => s_ss <= "01100110"; --4
when "0101" => s_ss <= "10110110"; --5
when "0110" => s_ss <= "10111110"; --6
when "0111" => s_ss <= "11100000"; --7
when "1000" => s_ss <= "11111110"; --8
when "1001" => s_ss <= "11110110"; --9
when others => s_ss <= v_scancnt & "000000";
end case;
if v_scancnt = "11" then
v_scancnt := "00";
else
v_scancnt := std_logic_vector(to_unsigned(to_integer(unsigned( v_scancnt )) + 1, 2));
end if;
else null;
end if;
else null;
end if;
end process p_displaycontrol;
ss_o <= not s_ss;
ss_sel_o <= not s_ss_sel;
end rtl;
The code for : cntr_top_struc.vhd
library IEEE;
use IEEE.std_logic_1164.all;
architecture rtl of cntr_top is
component cntr -- component of cntr
port (clk_i: in std_logic; -- 100 MHz system clock
reset_i: in std_logic; -- async high active 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'
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;
component io_ctrl ---- component io_crtl
port (clk_i: in std_logic; -- 100 MHz system clock
reset_i: in std_logic; -- async high active reset
cntr0_i: in std_logic_vector(3 downto 0); -- Digit 0 (from internal logic)
cntr1_i: in std_logic_vector(3 downto 0); -- Digit 1 (from internal logic)
cntr2_i: in std_logic_vector(3 downto 0); -- Digit 2 (from internal logic)
cntr3_i: in std_logic_vector(3 downto 0); -- Digit 3 (from internal logic)
swclean_o: out std_logic_vector(15 downto 0);
pbclean_o: out std_logic_vector(3 downto 0);
ss_o: out std_logic_vector(7 downto 0); -- Contain the Value for All 7-Segment Digits
ss_sel_o: out std_logic_vector(3 downto 0); -- Select a 7-segment digits
pb_i: in std_logic_vector(3 downto 0); --4 Buttons
sw_i: in std_logic_vector(15 downto 0) ); --16 Switches
end component;
-- Declare the signals that are used to connect the submodules.
signal s_cntr0 : std_logic_vector(3 downto 0);
signal s_cntr1 : std_logic_vector(3 downto 0);
signal s_cntr2 : std_logic_vector(3 downto 0);
signal s_cntr3 : std_logic_vector(3 downto 0);
signal s_cntrup : std_logic;
signal s_cntrdown : std_logic;
signal s_cntrreset : std_logic;
signal s_cntrhold : std_logic;
signal s_overflow : std_logic_vector(11 downto 0);
begin
--Instantiate the counter that is connected to the IO-Control
i_cntr_top1 : cntr
port map
(clk_i => clk_i,
reset_i => reset_i,
-- cntrdir_i => s_cntrdir, --swsync_o(13);
cntrup_i => s_cntrup, --swsync_o(13);
cntrdown_i => s_cntrdown, --swsync_o(12);
cntrreset_i => s_cntrreset, --swsync_o(15),
cntrhold_i => s_cntrhold, --swsync_o(14),
cntr0_o => s_cntr0,
cntr1_o => s_cntr1,
cntr2_o => s_cntr2,
cntr3_o => s_cntr3);
--Instantiate the IO control to which it is connected
i_io_ctrl : io_ctrl
port map
(clk_i => clk_i,
reset_i => reset_i,
swclean_o(12) => s_cntrdown,
swclean_o(13) => s_cntrup,
swclean_o(15) => s_cntrreset,
swclean_o(14) => s_cntrhold,
swclean_o(11 downto 0) => s_overflow(11 downto 0),
cntr0_i => s_cntr0,
cntr1_i => s_cntr1,
cntr2_i => s_cntr2,
cntr3_i => s_cntr3,
ss_o => ss_o,
ss_sel_o => ss_sel_o,
sw_i => sw_i,
pb_i => pb_i);
end rtl;
cntr_top.vhd
library IEEE;
use IEEE.std_logic_1164.all;
entity cntr_top is
port (clk_i : in std_logic; -- First Data Bit
reset_i : in std_logic; -- Second Data Bit
sw_i : in std_logic_vector (15 downto 0); -- 16 Switches Input
pb_i : in std_logic_vector(3 downto 0); -- 4 Buttons Input
ss_o : out std_logic_vector(7 downto 0); -- Contain the Value for All 7-Segment Digits
ss_sel_o : out std_logic_vector(3 downto 0)); -- Select a 7-segment digits
end cntr_top;
io_ctrl.vhd
library IEEE;
use IEEE.std_logic_1164.all;
entity io_ctrl is
port (clk_i : in std_logic; -- System clock (100 MHZ)
reset_i : in std_logic; -- Asynchronous high active reset
cntr0_i : in std_logic_vector(3 downto 0); -- Digit 0 from internal logic
cntr1_i : in std_logic_vector(3 downto 0); -- Digit 1 from internal logic
cntr2_i : in std_logic_vector(3 downto 0); -- Digit 2 from internal logic
cntr3_i : in std_logic_vector(3 downto 0); -- Digit 3 from internal logic
sw_i : in std_logic_vector(15 downto 0); -- 16 switches (from FPGA board)
pb_i : in std_logic_vector(3 downto 0); -- 4 buttons (from FPGA board)
ss_o : out std_logic_vector(7 downto 0); -- to 7 segment displays of the FPGA board
ss_sel_o : out std_logic_vector(3 downto 0); -- Selection of a 7 segment digit
swclean_o: out std_logic_vector(15 downto 0); -- 16 switches (to internal logic)
pbclean_o : out std_logic_vector(3 downto 0)); -- 4 buttons
end io_ctrl;
cntr_rtl.vhd
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
architecture rtl of cntr is
constant COUNTVALUE : std_logic_vector(26 downto 0):= "000000000000000001111101000";
--constant COUNTVALUE : std_logic_vector(26 downto 0):= "101111101011110000100000000";
signal s_enctr : std_logic_vector(26 downto 0) := "000000000000000000000000000";
signal s_1hzen : std_logic :='0';
signal s_cntr0 : std_logic_vector(3 downto 0) :="0000"; -- All digits set to zero.
signal s_cntr1 : std_logic_vector(3 downto 0) :="0000";
signal s_cntr2 : std_logic_vector(3 downto 0) :="0000";
signal s_cntr3 : std_logic_vector(3 downto 0) :="0000";
type s_state is (reset, hold, up, down);
signal s_present_state : s_state;
signal s_next_state : s_state;
begin
p_cntr: process(clk_i, reset_i)
variable v_digit0 : std_logic_vector(3 downto 0):= "0000";
variable v_digit1 : std_logic_vector(3 downto 0):= "0000";
variable v_digit2 : std_logic_vector(3 downto 0):= "0000";
variable v_digit3 : std_logic_vector(3 downto 0):= "0000";
begin
if reset_i = '1' then
v_digit0 := "0000";
v_digit1 := "0000";
v_digit2 := "0000";
v_digit3 := "0000";
s_enctr <= (others => '0');
elsif (clk_i'event and clk_i = '1') then
s_present_state <= s_next_state;
if s_enctr = COUNTVALUE then --When the number of terminals is reached, set the release flag and reset the counter
s_enctr <= (others => '0');
s_1hzen <= '1';
case s_present_state is
when up => --counting up.
if v_digit0 /= "1001" then
v_digit0 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit0 )) + 1, 4)); -- incrementing the bits.
elsif v_digit0 = "1001" and v_digit1 /= "1001" then
v_digit0 := "0000";
v_digit1 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit1 )) + 1, 4));
elsif v_digit0 = "1001" and v_digit1 = "1001" and v_digit2 /= "1001" then
v_digit0 := "0000";
v_digit1 := "0000";
v_digit2 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit2 )) + 1, 4));
elsif v_digit0 = "1001" and v_digit1 = "1001" and v_digit2 = "1001" and v_digit3 /= "1001"then
v_digit0 := "0000";
v_digit1 := "0000";
v_digit2 := "0000";
v_digit3 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit3 )) + 1, 4));
else
v_digit0 := "0000";
v_digit1 := "0000";
v_digit2 := "0000";
v_digit3 := "0000";
end if;
when down => --counting down.
if v_digit0 /= "0000" then
v_digit0 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit0 )) - 1, 4)); -- decrementing the bits.
elsif v_digit0 = "0000" and v_digit1 /= "0000" then
v_digit0 := "1001";
v_digit1 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit1 )) - 1, 4));
elsif v_digit0 = "0000" and v_digit1 = "0000" and v_digit2 /= "0000" then
v_digit0 := "1001";
v_digit1 := "1001";
v_digit2 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit2 )) - 1, 4));
elsif v_digit0 = "0000" and v_digit1 = "0000" and v_digit2 = "0000" and v_digit3 /= "0000"then
v_digit0 := "1001";
v_digit1 := "1001";
v_digit2 := "1001";
v_digit3 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit3 )) - 1, 4));
else
v_digit0 := "1001";
v_digit1 := "1001";
v_digit2 := "1001";
v_digit3 := "1001";
end if;
when hold => null; -- holding the counting.
when reset => -- reset all the values to zero.
v_digit0 := "0000";
v_digit1 := "0000";
v_digit2 := "0000";
v_digit3 := "0000";
end case;
else
s_enctr <=std_logic_vector(to_unsigned(to_integer(unsigned( s_enctr )) + 1, 27));
if s_1hzen = '1' then
s_1hzen <= '0';
end if;
end if;
s_cntr0 <= v_digit0;
s_cntr1 <= v_digit1;
s_cntr2 <= v_digit2;
s_cntr3 <= v_digit3;
end if;
end process p_cntr;
cntr0_o <= s_cntr0;
cntr1_o <= s_cntr1;
cntr2_o <= s_cntr2;
cntr3_o <= s_cntr3;
----------------------------------------------------------------------------------------------------------------
-- State machine
----------------------------------------------------------------------------------------------------------------
p_states: process(s_present_state, cntrup_i, cntrdown_i, cntrreset_i, cntrhold_i,reset_i)
begin
case s_present_state is
when reset => -- reset state conditions
if cntrreset_i = '1' then
s_next_state <= reset;
elsif cntrhold_i = '1' then
s_next_state <= hold;
elsif cntrup_i = '1' then
s_next_state <= up;
elsif cntrdown_i = '1' then
s_next_state <= down;
else s_next_state <= hold;
end if;
when hold => -- hold state conditions
if cntrreset_i = '1' then
s_next_state <= reset;
elsif cntrhold_i = '1' then
s_next_state <= hold;
elsif cntrup_i = '1' then
s_next_state <= up;
elsif cntrdown_i = '1' then
s_next_state <= down;
else s_next_state <= hold;
end if;
when up => -- up count state conditions
if cntrreset_i = '1' then
s_next_state <= reset;
elsif cntrhold_i = '1' then
s_next_state <= hold;
elsif cntrup_i = '1' then
s_next_state <= up;
elsif cntrdown_i = '1' then
s_next_state <= down;
else s_next_state <= hold;
end if;
when down => -- down count conditions
if cntrreset_i = '1' then
s_next_state <= reset;
elsif cntrhold_i = '1' then
s_next_state <= hold;
elsif cntrup_i = '1' then
s_next_state <= up;
elsif cntrdown_i = '1' then
s_next_state <= down;
else s_next_state <= hold;
end if;
when others => s_next_state <= reset;
end case;
end process p_states;
end rtl;
cntr.vhd
library IEEE;
use IEEE.std_logic_1164.all;
entity cntr is
port (clk_i : in std_logic; -- System clock (100 MHZ)
reset_i : in std_logic; -- Asysnchronous high active 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'
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;
Please waiting for your suggestions.
Any help would be great appricated thanks for all.
here down below example for debounce but couldnt find to way to implement.
-----------------------------------------------------------------------------
--
-- Debounce buttons and switches
--
-----------------------------------------------------------------------------
p_debounce: process (clk_i, reset_i)
begin -- process debounce
if reset_i = '1' then -- asynchronous reset (active high)
elsif clk_i'event and clk_i = '1' then -- rising clock edge
end if;
end process p_debounce;
swsync_o <= swsync;
pbsync_o <= pbsync;
------------------------------------------------------------
You're on the right track in that you need to synchronise the asynchronous inputs and debounce them.
But your debounce code needs to use a separate debouncer for each input with a timeout value of around 100 for a 1 kHz clock.
Here is a generic synchroniser and debouncer which uses parameters to specify the bus width, number of sync registers and timeout value.
Synchroniser.vhd
--
-- Synchronise an asynchronous bus input to avoid metastability problems
--
--
-- Signal Synchroniser (1 bit)
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity SynchroniserBit is
generic
(
reg_size: integer := 3 -- Default number of bits in sync register.
);
port
(
clock: in std_logic;
async_in: in std_logic := '0';
sync_out: out std_logic := '0';
rise: out std_logic := '0';
fall: out std_logic := '0'
);
end;
architecture V1 of SynchroniserBit is
constant MSB: integer := reg_size - 1;
signal sync_reg: std_logic_vector(MSB downto 0) := (others => '0');
begin
process (clock)
begin
if rising_edge(clock) then
rise <= not sync_reg(MSB) and sync_reg(MSB - 1);
fall <= sync_reg(MSB) and not sync_reg(MSB - 1);
sync_reg <= sync_reg(MSB - 1 downto 0) & async_in;
end if;
end process;
sync_out <= sync_reg(MSB);
end;
--
-- Bus Synchroniser (many bits)
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Synchroniser is
generic
(
reg_size: integer := 3; -- Default number of bits in sync register.
bus_size: integer := 8 -- Default bus width.
);
port
(
clock: in std_logic;
async_bus_in: in std_logic_vector(bus_size - 1 downto 0);
sync_bus_out: out std_logic_vector(bus_size - 1 downto 0);
rise_bus_out: out std_logic_vector(bus_size - 1 downto 0);
fall_bus_out: out std_logic_vector(bus_size - 1 downto 0)
);
end;
architecture V1 of Synchroniser is
component SynchroniserBit is
generic
(
reg_size: integer := 3 -- Default number of bits in sync register.
);
port
(
clock: in std_logic;
async_in: in std_logic;
sync_out: out std_logic;
rise: out std_logic;
fall: out std_logic
);
end component;
begin
SyncGen: for i in 0 to bus_size - 1 generate
begin
Sync: SynchroniserBit
generic map
(
reg_size => reg_size
)
port map
(
clock => clock,
async_in => async_bus_in(i),
sync_out => sync_bus_out(i),
rise => rise_bus_out(i),
fall => fall_bus_out(i)
);
end generate;
end;
Debouncer.vhd
--
-- Debounce a bus.
--
--
-- Signal Debouncer (1 bit)
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity DebouncerBit is
port
(
clock: in std_logic;
counter: in integer;
input: in std_logic;
output: out std_logic := '0'
);
end;
architecture V1 of DebouncerBit is
begin
process(clock)
variable counter_snapshot: integer := 0;
variable previous_input: std_logic := '0';
begin
if rising_edge(clock) then
-- If counter wraps around to counter_snapshot,
-- a full debounce period has elapsed without a change in input,
-- so output the debounced value.
if counter_snapshot = counter then
output <= previous_input;
end if;
-- If the input has changed, save a snapshot of the counter.
if not(input = previous_input) then
counter_snapshot := counter;
end if;
previous_input := input;
end if;
end process;
end;
--
-- Bus Debouncer (many bits)
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Debouncer is
generic
(
timeout: integer := 100; -- Default timeout value.
bus_size: integer := 8 -- Default bus width.
);
port
(
clock: in std_logic;
bus_in: in std_logic_vector(bus_size - 1 downto 0);
bus_out: out std_logic_vector(bus_size - 1 downto 0)
);
end;
architecture V1 of Debouncer is
component DebouncerBit is
port
(
clock: in std_logic;
counter: in integer;
input: in std_logic;
output: out std_logic
);
end component;
-- One counter to be shared by all debouncers.
-- Each debouncer takes a snapshot of the count value when its input changes value.
signal counter: integer := 0;
begin
-- Create the debounce period.
process(clock)
begin
if rising_edge(clock) then
if counter = timeout then
counter <= 0;
else
counter <= counter + 1;
end if;
end if;
end process;
DebouncerGen: for i in 0 to bus_size - 1 generate
begin
Debounce: DebouncerBit
port map
(
clock => clock,
counter => counter,
input => bus_in(i),
output => bus_out(i)
);
end generate;
end;
SynchroniseDebounce.vhd
--
-- SynchroniseDebounce
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity SynchroniseDebounce is
generic
(
reg_size: integer := 3; -- Default number of bits in sync register.
timeout: integer := 100; -- Default timeout value.
bus_size: integer := 8 -- Default bus width.
);
port
(
clock: in std_logic;
async_bus_in: in std_logic_vector(bus_size - 1 downto 0);
db_sync_bus_out: out std_logic_vector(bus_size - 1 downto 0) := (others => '0')
);
end;
architecture V1 of SynchroniseDebounce is
component Synchroniser is
generic
(
reg_size: integer := 3; -- Default number of bits in sync register.
bus_size: integer := 8 -- Default bus width.
);
port
(
clock: in std_logic;
async_bus_in: in std_logic_vector(bus_size - 1 downto 0);
sync_bus_out: out std_logic_vector(bus_size - 1 downto 0) := (others => '0');
rise_bus_out: out std_logic_vector(bus_size - 1 downto 0) := (others => '0');
fall_bus_out: out std_logic_vector(bus_size - 1 downto 0) := (others => '0')
);
end component;
component Debouncer is
generic
(
timeout: integer := 100; -- Default timeout value.
bus_size: integer := 8 -- Default bus width.
);
port
(
clock: in std_logic;
bus_in: in std_logic_vector(bus_size - 1 downto 0);
bus_out: out std_logic_vector(bus_size - 1 downto 0)
);
end component;
signal sync_bus_out: std_logic_vector(bus_size - 1 downto 0);
signal rise_bus_out: std_logic_vector(bus_size - 1 downto 0);
signal fall_bus_out: std_logic_vector(bus_size - 1 downto 0);
begin
Synchroniser_Inst: Synchroniser
generic map
(
reg_size => REG_SIZE, -- Override default value.
bus_size => BUS_SIZE -- Override default value.
)
port map
(
clock => clock,
async_bus_in => async_bus_in,
sync_bus_out => sync_bus_out, -- Goes to Debouncer_Inst
rise_bus_out => rise_bus_out,
fall_bus_out => fall_bus_out
);
Debouncer_Inst: Debouncer
generic map
(
timeout => TIMEOUT, -- Override default value.
bus_size => BUS_SIZE -- Override default value.
)
port map
(
clock => clock,
bus_in => sync_bus_out, -- From Synchroniser_Inst
bus_out => db_sync_bus_out
);
end;
Testbench.vhd
--
-- Test Bench
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity testbench is
end;
architecture V1 of testbench is
component SynchroniseDebounce is
generic
(
reg_size: integer := 3; -- Default number of bits in sync register.
timeout: integer := 100; -- Default timeout value.
bus_size: integer := 8 -- Default bus width.
);
port
(
clock: in std_logic;
async_bus_in: in std_logic_vector(bus_size - 1 downto 0);
db_sync_bus_out: out std_logic_vector(bus_size - 1 downto 0)
);
end component;
constant NUM_SWITCHES: integer := 16;
constant NUM_PUSH_BUTTONS: integer := 4;
signal switches_async, switches_db_sync: std_logic_vector(NUM_SWITCHES - 1 downto 0) := (others => '0');
signal push_buttons_async, push_buttons_db_sync: std_logic_vector(NUM_PUSH_BUTTONS - 1 downto 0) := (others => '0');
constant REG_SIZE: integer := 3;
constant BUS_SIZE: integer := NUM_SWITCHES + NUM_PUSH_BUTTONS;
signal async_bus_in, db_sync_bus_out, rise_bus_out, fall_bus_out: std_logic_vector(BUS_SIZE - 1 downto 0) := (others => '0');
constant TIMEOUT: integer := 10; -- Number of clock cycles in debounce period.
signal clock: std_logic;
constant PERIOD: time := 10 ns; -- System clock frequency.
signal stop_clock: boolean := false;
begin
ClockGenerator: process
begin
while not stop_clock loop
clock <= '0';
wait for PERIOD / 2;
clock <= '1';
wait for PERIOD / 2;
end loop;
wait;
end process ClockGenerator;
Stimulus: process
variable seed1, seed2: positive;
variable rrand: real;
variable irand: integer;
begin
switches_async <= (others => '0');
push_buttons_async <= (others => '0');
wait for 23 ns;
-- Some noisy inputs.
seed1 := 1;
seed2 := 1;
for n in 1 to 500 loop
for i in 0 to NUM_PUSH_BUTTONS - 1 loop
uniform(seed1, seed2, rrand);
irand := integer(round(rrand));
if irand = 0 then
push_buttons_async(i) <= '0';
else
push_buttons_async(i) <= '1';
end if;
end loop;
for i in 0 to NUM_SWITCHES - 1 loop
uniform(seed1, seed2, rrand);
irand := integer(round(rrand));
if irand = 0 then
switches_async(i) <= '0';
else
switches_async(i) <= '1';
end if;
end loop;
wait for 1 ns;
end loop;
-- Pulse the push buttons.
for i in 0 to NUM_PUSH_BUTTONS - 1 loop
push_buttons_async(i) <= '1';
wait for (REG_SIZE + TIMEOUT + 1) * PERIOD;
push_buttons_async(i) <= '0';
end loop;
-- Pulse the switches.
for i in 0 to NUM_SWITCHES - 1 loop
switches_async(i) <= '1';
wait for (REG_SIZE + TIMEOUT + 1) * PERIOD;
switches_async(i) <= '0';
end loop;
wait for (REG_SIZE + TIMEOUT + 1) * PERIOD;
stop_clock <= true;
wait;
end process Stimulus;
DUT: SynchroniseDebounce
generic map
(
reg_size => REG_SIZE, -- Override default value.
timeout => TIMEOUT, -- Override default value.
bus_size => BUS_SIZE -- Override default value.
)
port map
(
clock => clock,
async_bus_in => async_bus_in,
db_sync_bus_out => db_sync_bus_out
);
-- Connect the input switches and input push buttons to the asynchronous bus input.
async_bus_in <= switches_async & push_buttons_async;
-- Connect the debounced and synchronised output bus to the debounced synchronised switches and push buttons.
switches_db_sync <= db_sync_bus_out(NUM_SWITCHES + NUM_PUSH_BUTTONS - 1 downto NUM_PUSH_BUTTONS);
push_buttons_db_sync <= db_sync_bus_out(NUM_PUSH_BUTTONS - 1 downto 0);
end;
Testbench Waveforms
Bit 2 of the debounced synchronous bus (db_sync_bus_out) goes high only when a long enough pulse is applied to the input (async_bus_in).

Continuous sequence in VHDL

This is what i am required to do. - Show the following repeating sequence on the onboard LEDs (Leftmost LED is MSB):
o 0x00 -> 0x03 -> 0x40 -> 0xE8 -> 0x00 -> …
- LED transitions must be visible
- Command the sequence to start/pause upon pressing BTN0
- Upon power up the sequence is paused
This is what i have so far:
entity vhdl_primer is
port ( clk, rst_n, btn0: in std_logic;
LED: out std_logic_vector (7 downto 0)
);
end vhdl_primer;
architecture behavior of vhdl_primer is
type statetype is (S0, S1, S2, S3);
signal currentstate, nextstate: statetype;
begin
statereg: process(clk, rst)
begin
if (rst='0') then
currentstate <= S0; --initial state
elsif rising_edge(clk) then
currentstate <= nextstate;
end if;
end process;
comblogic: process(currentstate, btn0)
begin
LED <= '0';
case currentstate is
when S0 =>
LED <= '0'; -- led off
nextstate <= S1;
when S1 =>
if (btn0='1') then
nextstate <= S2;
else
nextstate <= S1;
end if;
when S2 =>
LED <= '1'; -- led 0x40
nextstate <= S3;
when S3 =>
LED <= '1'; -- led 0xE8
if (btn0='1') then
nextstate <= S0;
else
nextstate <= S3;
end if;
when others =>
end case;
end process;
end behavior;

Incrementing Seven Segment by Using Push Buttons

My fpga is spartan 3E-100 Cp132. I have four push buttons as my inputs and I want to increment the four digits on 7-segment of the board by using them. The VHDL code is below:
entity main is
port(b1,b2,b3,b4 : in STD_LOGIC;
clk : in STD_LOGIC;
sseg : out STD_LOGIC_VECTOR(0 to 6);
anodes : out STD_LOGIC_VECTOR(3 downto 0);
reset : in STD_LOGIC
);
end main;
architecture Behavioral of main is
signal bcd1, bcd2, bcd3, bcd4 : STD_LOGIC_VECTOR (3 downto 0);
signal clk2 : STD_LOGIC;
signal pushbuttons : STD_LOGIC_VECTOR(3 downto 0);
signal db_pushbuttons : STD_LOGIC_VECTOR(3 downto 0);
signal counter : STD_LOGIC_VECTOR(1 downto 0);
signal clk_divider : STD_LOGIC_VECTOR(20 downto 0);
component Debounce is
port( cclk : in STD_LOGIC;
inp : in STD_LOGIC_VECTOR(3 downto 0);
cclr : in STD_LOGIC;
db : out STD_LOGIC_VECTOR(3 downto 0)
);
end component;
begin
pushbuttons <= b4 & b3 & b2 & b1;
Db : Debounce port map
( cclk => clk2,
inp => pushbuttons,
cclr => reset,
db => db_pushbuttons);
process (clk)
begin
if rising_edge(clk) then
if clk_divider <= "1100001101010000" then
clk_divider <= clk_divider + 1;
clk2 <= '0';
else
clk_divider <= (others => '0');
clk2 <= '1';
end if;
end if;
end process;
process (clk2, reset)
begin
if reset = '1' then
-- do something here
bcd1 <= "0000";
bcd2 <= "0000";
bcd3 <= "0000";
bcd4 <= "0000";
elsif rising_edge(clk2) then
counter <= counter + 1;
if db_pushbuttons(0) = '1' then -- db_b1
if bcd1 <= "1000" then
bcd1 <= bcd1 + 1;
else
bcd1 <= "0000";
end if;
elsif db_pushbuttons(1) = '1' then -- db_b2
if bcd2 <= "1000" then
bcd2 <= bcd2 + 1;
else
bcd2 <= "0000";
end if;
elsif db_pushbuttons(2) = '1' then -- db_b3
if bcd3 <= "1000" then
bcd3 <= bcd3 + 1;
else
bcd3 <= "0000";
end if;
elsif db_pushbuttons(3) = '1' then --db_b4
if bcd4 <= "1000" then
bcd4 <= bcd4 + 1;
else
bcd4 <= "0000";
end if;
end if;
end if;
end process;
process (counter, bcd1, bcd2, bcd3, bcd4)
variable display : STD_LOGIC_VECTOR(3 downto 0);
begin
case counter is
when "00" => anodes <= "1110"; display := bcd1;
when "01" => anodes <= "1101"; display := bcd2;
when "10" => anodes <= "1011"; display := bcd3;
when "11" => anodes <= "0111"; display := bcd4;
when others => null;
end case;
case display is
when "0000" => sseg <= "0000001"; --0
when "0001" => sseg <= "1001111"; --1
when "0010" => sseg <= "0010010"; --2
when "0011" => sseg <= "0000110"; --3
when "0100" => sseg <= "1001100"; --4
when "0101" => sseg <= "0100100"; --5
when "0110" => sseg <= "0100000"; --6
when "0111" => sseg <= "0001111"; --7
when "1000" => sseg <= "0000000"; --8
when "1001" => sseg <= "0000100"; --9
when others => sseg <= "0010000"; --e, represents error
end case;
end process;
end Behavioral;
Every pushbutton should increment the corresponding 7-segment digit (b1 --> rightmost digit and b4--> leftmost digit) by one. The problem is when I push the button, it does the job but not increment it by one but some arbitrary number. The reason is that it increments by one at every rising edge of the clock 2 and it happens too quickly due to the frequency of this clock. How can I manage to get rid of this problem? I tried several debouncing code for the push buttons but they weren't helpful so much. I am totally stuck here. I mean there should be a way to do it, but how? By the way, the debouncing code that I have been using with the code above is
entity Debounce is
port(cclk : in STD_LOGIC;
inp : in STD_LOGIC_VECTOR(3 downto 0);
cclr : in STD_LOGIC;
db : out STD_LOGIC_VECTOR(3 downto 0)
);
end Debounce;
architecture Behavioral of Debounce is
signal delay1, delay2, delay3 : STD_LOGIC_VECTOR(3 downto 0);
begin
process (cclk, cclr)
begin
if cclr = '1' then
delay1 <= "0000";
delay2 <= "0000";
delay3 <= "0000";
elsif rising_edge(cclk) then
delay1 <= inp;
delay2 <= delay1;
delay3 <= delay2;
end if;
end process;
db <= delay1 and delay2 and delay3;
end Behavioral;
So any help will be appreciated, thanks in advance!
If the intended function of the button is that you will only increment once, no matter how long you hold it down, you need to implement an "edge detect" on the debounced switch output. That is, only allow the bcd count to increment/update on the rising edge of the debounced switch signal. For example:
...
elsif rising_edge(clk2) then
counter <= counter + 1;
db_pushbuttons_previous <= db_pushbuttons;
if db_pushbuttons(0) = '1' and db_pushbuttons_previous(0) = '0' then --rising edge detect
if bcd1 <= "1000" then
bcd1 <= bcd1 + 1;
else
bcd1 <= "0000";
end if;
...
This way, no matter how long db_pushbuttons(0) is asserted, the bcd value will only be incremented once.
Testing with GHDL I have the following code.
file: sevensegns.vhdl
-----------------------------------------
---- SevenSegNS.vhdl
---- Seven segment driver with 4 input
---- buttons
---- Author: Derby Russell
---- Date: 12-13-2013
-----------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.ALL;
entity main_7_seg is
port(b1,b2,b3,b4 : in std_logic;
clk : in std_logic;
sseg : out std_logic_vector(0 to 6);
anodes : out std_logic_vector (3 downto 0);
reset : in std_logic
);
end main_7_seg;
architecture behavioral of main_7_seg is
signal bcd1, bcd2, bcd3, bcd4 : unsigned (3 downto 0) := "0000";
signal clk2 : std_logic := '0';
signal pushbuttons : std_logic_vector(3 downto 0) := "0000";
signal db_pushbuttons : std_logic_vector(3 downto 0) := "0000";
signal counter : unsigned (1 downto 0) := "00";
component Debounce is
port( cclk : in std_logic;
inp : in std_logic_vector(3 downto 0);
cclr : in std_logic;
db : out std_logic_vector(3 downto 0)
);
end component;
begin
pushbuttons <= b4 & b3 & b2 & b1;
Db : Debounce port map
( cclk => clk2,
inp => pushbuttons,
cclr => reset,
db => db_pushbuttons);
process (clk)
begin
if rising_edge(clk) then
clk2 <= '1';
else
clk2 <= '0';
-- FOR RUNNING ON ACTUAL HARDWARE:
-- RESTORE NEXT 6 LINES AND COMMENT OUT ABOVE 4 LINES.
-- if clk_divider <= "1100001101010000" then
-- clk_divider <= clk_divider + 1;
-- clk2 <= '0';
-- else
-- clk_divider <= (others => '0');
-- clk2 <= '1';
end if;
end process;
P2: process (clk2, reset)
begin
if reset = '1' then
-- do something here
bcd1 <= "0000";
bcd2 <= "0000";
bcd3 <= "0000";
bcd4 <= "0000";
elsif rising_edge(clk2) then
counter <= counter + 1;
if db_pushbuttons(0) = '1' then -- db_b1
if bcd1 <= "0010" then
if bcd1 = "0000" then
bcd1 <= bcd1 + 1;
end if;
else
bcd1 <= "0000";
end if;
elsif db_pushbuttons(1) = '1' then -- db_b2
if bcd2 <= "0010" then
if bcd2 = "0000" then
bcd2 <= bcd2 + 1;
end if;
else
bcd2 <= "0000";
end if;
elsif db_pushbuttons(2) = '1' then -- db_b3
if bcd3 <= "0010" then
if bcd3 = "0000" then
bcd3 <= bcd3 + 1;
end if;
else
bcd3 <= "0000";
end if;
elsif db_pushbuttons(3) = '1' then --db_b4
if bcd4 <= "0010" then
if bcd4 = "0000" then
bcd4 <= bcd4 + 1;
end if;
else
bcd4 <= "0000";
end if;
end if;
end if;
end process P2;
P3: process (counter, bcd1, bcd2, bcd3, bcd4)
-- variable display : std_logic_vector(3 downto 0);
variable display : unsigned (3 downto 0);
begin
case counter is
when "00" => anodes <= "1110"; display := bcd1;
when "01" => anodes <= "1101"; display := bcd2;
when "10" => anodes <= "1011"; display := bcd3;
when "11" => anodes <= "0111"; display := bcd4;
when others => null;
end case;
case display is
when "0000" => sseg <= "0000001"; --0
when "0001" => sseg <= "1001111"; --1
when "0010" => sseg <= "0010010"; --2
when "0011" => sseg <= "0000110"; --3
when "0100" => sseg <= "1001100"; --4
when "0101" => sseg <= "0100100"; --5
when "0110" => sseg <= "0100000"; --6
when "0111" => sseg <= "0001111"; --7
when "1000" => sseg <= "0000000"; --8
when "1001" => sseg <= "0000100"; --9
when others => sseg <= "0010000"; --e, represents error
end case;
end process P3;
end behavioral;
file: debounce.vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.ALL;
entity Debounce is
port(cclk : in std_logic;
inp : in std_logic_vector(3 downto 0);
cclr : in std_logic;
db : out std_logic_vector(3 downto 0)
);
end Debounce;
architecture behavioral_2 of Debounce is
signal delay1, delay2, delay3 : std_logic_vector(3 downto 0);
begin
process (cclk, cclr)
begin
if cclr = '1' then
delay1 <= "0000";
delay2 <= "0000";
delay3 <= "0000";
elsif rising_edge(cclk) then
delay1 <= inp;
delay2 <= delay1;
delay3 <= delay2;
end if;
end process;
db <= delay1 and delay2 and delay3;
end behavioral_2;
I processed these two files with a data file sevensegns_tb.vhdl
Then I ran the files and observed the data with gtkwave
here is the output:
(source: googlecode.com)
And I have posted all the code and results to:
Google Code sevenseg
Click on the Source tab to see all the files created.

std_logic vector (15 downto 0) value doesn't get assigned

So, long story short, I'm trying to make a processor of sorts ('of sorts' is put there for a reason, but let's not go into details), and I'm running into one problem which pretty much ruins the whole thing.
Namely, in this piece of code :
programmProcess: process (clk,rst) is
variable counter : natural;
begin
if (rst = '1') then
counter := 0;
elsif (clk'event and clk = '1' and pm_nEn= '1') then
RAM(counter) <= data; --This is where the issue is
counter := counter + 1;
if (counter = 1024) then
counter := 0;
end if;
end if;
data <= "ZZZZZZZZZZZZZZZZ";
end process programmProcess;
... and this is the testbench process :
stim_proc1: process
begin
rst <= '1';
pm_nEn <= '1';
wait for clk_period;
rst <= '0' ;
data <="0000111110111001";
wait for clk_period;
data <="0000111010111001";
wait for clk_period;
data <= "ZZZZZZZZZZZZZZZZ";
pm_nEn <= '0';
wait for 10*clk_period;
wait;
end process;
... where RAM is an array of 1024 vectors of 16 bits, data is a 16 bit inout vector and pm_nEn is a single bit which basically allows the RAM to be filled with values.
The idea is that RAM(counter) gets values from the data vector, which is manually fed values in the testbench, but this doesn't happen. Namely, all of RAM's values just stay "UUUUUUUUUUUUUUUU", despite data having the required values. Even when it's first evaluated and counter is 0, RAM(0) is undefined.
I'm using the ISE suite, and I tried simulating, and then just tracing through all the steps, and the step where RAM(counter) should get assigned a value is shown, the data vector does have the value which is added manually from the testbench, but RAM still doesn't get any values.
So, the question is basically - why does this happen? Why doesn't RAM get its values assigned?
Also, here's the full VHDL and testbench (which was conveniently generated by ISE) in google doc form -
VHDL
Testbench
Assigning "zzzz" to Data within the main process should do no harm (although in the current code fragment, it is redundant).
One thing that may lead to problems in synthesis is:
elsif (clk'event and clk = '1' and pm_nEn= '1') then
... actions
end if;
To match the pattern a synthesis tool expects for a clocked process, it is better to write
elsif clk'event and clk = '1' then
if pm_nEn= '1' then
... actions
end if;
end if;
though I would expect the two versions to be equivalent in simulation.
There isn't another driver on RAM in another process, is there?
EDIT: apparently there IS a separate driver setting RAM in another process.
Now from a software perspective, you might think that is OK because one process drives when en = '0' and the other when en = '1'. However you can't make the driver hardware appear and disappear at the flick of a boolean; there are always two drivers on the RAM signal. And the one you aren't explicitly using is holding the value as "UUUU".
The best thing to do is to eliminate one of them. Make one process or the other responsible for writing to RAM. I'll use this process; you may find the design is cleaner and tidier using the other process; that's OK too.
It's easy : just reorganise this process along these lines:
elsif clk'event and clk = '1' then
if pm_nEn= '1' then
... actions
else -- or elsif external_enable then
RAM(external_address) <= external_data;
end if;
end if;
Incidentally, when you see an expression like RAM(to_integer(unsigned(R(to_integer(unsigned(IR(5 downto 3))))))) <= std_logic_vector(signed(OP1) + signed(OP2));
it's usually a clue that some things have been declared as the wrong types in the first place : for example, OP1 and OP2 should possibly be signed, R should be an array of integers, and so on. If you can't eliminate all the ugliness, you can at least stop it interfering with the main program flow using helper functions (possibly in a package):
function gen_reg_addr(IR : Register) return natural is ...
RAM(gen_reg_addr(IR)) <= ...
I imagine that the problem is with the multitude of places where you write to data. It wouldn't surprise me if you are having multiple statements write to the same variable, and that should cause the simulator to give it a value of Z.
For example, one of your processes looks like this:
glavenProcess: process (clk,rst) is
begin
data <= "ZZZZZZZZZZZZZZZZ";
...
end process;
Sorry for the delay, i found your problem, change RAM to variable instead of Signal, check VHDL manual to see the differences between Signals and variables:
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
entity mp is
port(
clk, rst, pm_nEn : in std_logic;
data : inout std_logic_vector(15 downto 0);
adr : out std_logic_vector(15 downto 0);
rd_nwr : out std_logic
);
end entity mp;
architecture beh of mp is
signal PC, IR, OP1, OP2 : std_logic_vector(15 downto 0);
type csignals is array(7 downto 0) of std_logic_vector(15 downto 0);
signal R: csignals;
type memory_array is array(1024 downto 0) of std_logic_vector(15 downto 0);
shared variable RAM: memory_array;
begin
glavenProcess: process (clk,rst) is
begin
data <= "ZZZZZZZZZZZZZZZZ";
if (rst = '1') then
PC <= "0000000000000000";
R(0) <= "0000000000000000";
R(1) <= "0000000000000000";
R(2) <= "0000000000000000";
R(3) <= "0000000000000000";
R(4) <= "0000000000000000";
R(5) <= "0000000000000000";
R(6) <= "0000000000000000";
R(7) <= "0000000000000001";
elsif (clk'event and clk = '1' and pm_nEn= '0') then
IR <= RAM(to_integer(unsigned(PC)));
if (IR(15) = '0') then
if (IR(14) = '0') then
OP1 <= R(to_integer(unsigned(IR(11 downto 9))));
else
OP1 <= RAM(to_integer(unsigned(R(to_integer(unsigned(IR(11 downto 9)))))));
end if;
if (IR(13) = '0') then
OP2 <= R(to_integer(unsigned(IR(8 downto 6))));
else
if (IR(0) = '0') then
adr <= R(to_integer(unsigned(IR(8 downto 6))));
OP2 <= data;
rd_nwr <= '1' ;
else
OP2 <= RAM(to_integer(unsigned(R(to_integer(unsigned(IR(8 downto 6)))))));
end if;
end if;
if (IR(2) = '1') then OP2 <= not OP2 ; end if;
if (IR(1) = '1') then OP1 <= not OP1 ; end if;
if (IR(0) = '0') then
if (IR(12) = '0') then
R(to_integer(unsigned(IR(5 downto 3)))) <= std_logic_vector(signed(OP1) + signed(OP2));
else
RAM(to_integer(unsigned(R(to_integer(unsigned(IR(5 downto 3))))))) := std_logic_vector(signed(OP1) + signed(OP2));
end if;
else
if (IR(12) = '0') then
adr <= R(to_integer(unsigned(IR(5 downto 3))));
else
adr <= RAM(to_integer(unsigned(R(to_integer(unsigned(IR(5 downto 3)))))));
end if;
data <= std_logic_vector(signed(OP1) + signed(OP2));
rd_nwr <= '0' ;
end if;
PC <= std_logic_vector(unsigned(PC) + 1);
else
if (IR(8 downto 7) = "00") then
if (R(to_integer(unsigned(IR(11 downto 9)))) = R(to_integer(unsigned(IR(6 downto 4))))) then
PC <= R(to_integer(unsigned(IR(14 downto 12))));
end if;
elsif (IR(8 downto 7) = "01") then
if (R(to_integer(signed(IR(11 downto 9)))) > R(to_integer(signed(IR(6 downto 4))))) then
PC <= R(to_integer(unsigned(IR(14 downto 12))));
end if;
elsif (IR(8 downto 7) = "10") then
if (R(to_integer(signed(IR(11 downto 9)))) < R(to_integer(signed(IR(6 downto 4))))) then
PC <= R(to_integer(unsigned(IR(14 downto 12))));
end if;
elsif (IR(8 downto 7) = "11") then
if ( not R(to_integer(signed(IR(11 downto 9)))) = R(to_integer(signed(IR(6 downto 4))))) then
PC <= R(to_integer(unsigned(IR(14 downto 12))));
end if;
end if;
end if;
end if;
end process glavenProcess;
programmProcess: process (clk,rst) is
variable counter : natural;
begin
if (rst = '1') then
counter := 0;
else
if (clk'event and clk = '1' and pm_nEn= '1') then
RAM(counter) := data;
counter := counter + 1;
if (counter = 1024) then counter := 0; end if;
end if;
end if;
end process programmProcess;
end architecture beh;
Testbench:
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
-- Add your library and packages declaration here ...
entity mp_tb is
end mp_tb;
architecture TB_ARCHITECTURE of mp_tb is
-- Component declaration of the tested unit
component mp
port(
clk : in STD_LOGIC;
rst : in STD_LOGIC;
pm_nEn : in STD_LOGIC;
data : inout STD_LOGIC_VECTOR(15 downto 0);
adr : out STD_LOGIC_VECTOR(15 downto 0);
rd_nwr : out STD_LOGIC );
end component;
-- Stimulus signals - signals mapped to the input and inout ports of tested entity
signal clk : STD_LOGIC;
signal rst : STD_LOGIC;
signal pm_nEn : STD_LOGIC;
signal data : STD_LOGIC_VECTOR(15 downto 0);
-- Observed signals - signals mapped to the output ports of tested entity
signal adr : STD_LOGIC_VECTOR(15 downto 0);
signal rd_nwr : STD_LOGIC;
-- Add your code here ...
begin
-- Unit Under Test port map
UUT : mp
port map (
clk => clk,
rst => rst,
pm_nEn => pm_nEn,
data => data,
adr => adr,
rd_nwr => rd_nwr
);
clock:process is
begin
clk<='0';
wait for 10 ns;
clk<='1';
wait for 10 ns;
end process;
process is
begin
rst <= '1';
pm_nEn <= '1';
wait for 25 ns;
rst <= '0' ;
data <="0000111110111001";
wait for 45 ns;
data <="0000111010111001";
wait for 55 ns;
data <= "ZZZZZZZZZZZZZZZZ";
pm_nEn <= '0';
wait;
end process;
end TB_ARCHITECTURE;
configuration TESTBENCH_FOR_mp of mp_tb is
for TB_ARCHITECTURE
for UUT : mp
use entity work.mp(beh);
end for;
end for;
end TESTBENCH_FOR_mp;

Resources