Can't assign value to integer signal in VHDL - vhdl

I am using a programmable-logic to decode a sequence of long or short impulses into latin letters according to morse code. I am using VHDL to describe our design, to be precise I'm using Quartus Prime for the design and ModelSim for the simulations. My CPLD is an ALTERA MAX-V 5M160ZE64C5.
Here is my code :
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all ;
use ieee.std_logic_arith.all;
entity SauvezLesMorses is
port
(
-- Input ports
clk : in std_logic;
message : in std_logic;
display : in std_logic;
start : in std_logic;
-- Output ports
seg14 : out std_logic_vector (13 downto 0);
lengthLED : out std_logic := '0'
);
end entity SauvezLesMorses;
architecture SauvezLesMorses_arch of SauvezLesMorses is
type state_t is (A, B, C);
signal state : state_t;
signal count : integer range 0 to 4 := 0;
signal clk_cnt : integer range 0 to 21 := 0;
signal morse : std_logic_vector (3 downto 0);
begin
process (clk, start)
variable vectorDummy : std_logic_vector (3 downto 0);
begin
if (start = '1') then
state <= A;
count <= 0;
seg14 <= "00000010001000";
morse <= "0000";
lengthLED <= '0';
elsif (rising_edge(clk)) then
case state is
-- Idle, listening
when A =>
if (display = '0') then
if (message = '1' and count < 4) then
state <= B;
seg14 <= "00000010001000";
count <= count;
morse <= morse;
lengthLED <= '0';
clk_cnt <= 0;
else
state <= A;
seg14 <= "00000010001000";
count <= count;
morse <= morse;
lengthLED <= '0';
end if;
else
state <= C;
count <= count;
morse <= morse;
lengthLED <= '0';
seg14 <= "00000010001000";
end if;
-- Measuring impulse length
when B =>
if (display = '0') then
if (message = '1') then
state <= B;
count <= count;
morse <= morse;
seg14 <= "00000010001000";
if (clk_cnt < 20) then
clk_cnt <= (1 + clk_cnt);
lengthLED <= '0';
else
clk_cnt <= 21;
lengthLED <= '1';
end if;
else
state <= A;
if (clk_cnt < 21) then
morse <= morse;
else
case count is
when 0 => vectorDummy := "1000";
when 1 => vectorDummy := "0100";
when 2 => vectorDummy := "0010";
when 3 => vectorDummy := "0001";
when others => vectorDummy := "0000";
end case;
morse <= morse or vectorDummy;
end if;
count <= count + 1;
lengthLED <= '0';
seg14 <= "00000010001000";
end if;
else
state <= C;
count <= count;
morse <= morse;
lengthLED <= '0';
seg14 <= "00000010001000";
end if;
-- Displaying converted character to user
when C =>
if (display = '0') then
state <= A;
count <= 0;
seg14 <= "00000010001000";
lengthLED <= '0';
morse <= "0000";
else
state <= C;
count <= count;
morse <= morse;
lengthLED <= '0';
if(count = 1) then
case morse is
when "0000" => seg14 <= "10011110001000"; --E
when "1000" => seg14 <= "10000000100010"; --T
when others => seg14 <= "11111111111111"; --unknown character
end case;
elsif(count = 2) then
case morse is
when "0100" => seg14 <= "11101110001000"; --A
when "1000" => seg14 <= "01101101000100"; --N
when "1100" => seg14 <= "01101101010000"; --M
when "0000" => seg14 <= "00000000100010"; --I
when others => seg14 <= "11111111111111"; --unknown character
end case;
elsif(count = 3) then
case morse is
when "0000" => seg14 <= "10110110001000"; --S
when "0010" => seg14 <= "01111100000000"; --U
when "0100" => seg14 <= "11001110001100"; --R
when "0110" => seg14 <= "01101100000101"; --W
when "1000" => seg14 <= "11110000100010"; --D
when "1010" => seg14 <= "00001110010100"; --K
when "1100" => seg14 <= "10111100001000"; --G
when "1110" => seg14 <= "11111100000000"; --O
when others => seg14 <= "11111111111111"; --unknown character
end case;
elsif(count = 4) then
case morse is
when "0000" => seg14 <= "01101110001000"; --H
when "0001" => seg14 <= "00001100010001"; --V
when "0010" => seg14 <= "10001110001000"; --F
when "0100" => seg14 <= "00011100000000"; --L
when "0110" => seg14 <= "11001110001000"; --P
when "0111" => seg14 <= "01111000000000"; --J
when "1000" => seg14 <= "11110000101010"; --B
when "1001" => seg14 <= "00000001010101"; --X
when "1010" => seg14 <= "10011100000000"; --C
when "1011" => seg14 <= "00000001010010"; --Y
when "1100" => seg14 <= "10010000010001"; --Z
when "1101" => seg14 <= "11111100000100"; --Q
when others => seg14 <= "11111111111111"; --unknown character
end case;
else
seg14 <= "11111111111111";
end if ;
end if;
end case;
end if;
end process;
end architecture SauvezLesMorses_arch ;
A modelsim simulation with parameters
force -freeze sim:/sauvezlesmorses/clk 1 0, 0 {25000000000 ps} -r {50 ms}
force -freeze sim:/sauvezlesmorses/display 0 0, 1 {9000000000000 ps} -r {18 sec}
force -freeze sim:/sauvezlesmorses/message 0 0, 1 {3200000000000 ps} -r {6.4 sec}
force -freeze sim:/sauvezlesmorses/start 1 0 -cancel {0.5 sec}
run 40 sec
which yields :
Modelsim Simulation
clearly shows that :
clk_cnt never increases but rather remains zero for 40 seconds
count is neither set to 0 by the activation of start nor from the desactivation of display (i.e. the transition of state from C to A).
Would you have any idea why?
P.S. I know that I am positively not running a proper testbench. So even if I should, please do not remind it to me unless you know it is part of the answer to my question.

A force updating a signal value doesn't generate an event.
See IEEE Std 1076-2008 14.7.3.4 Signal update, para 3
... If updating a signal causes the current value of that signal to change, then an event is said to have occurred on the signal, unless the update occurs by application of the vhpi_put_value function with an update mode of vhpiDeposit or vhpiForce to an object that represents the signal. ...
Likely the same mechanism used by Modelsim's force or FLI.
With a testbench:
library ieee;
use ieee.std_logic_1164.all;
entity slm_tb is
end entity;
architecture foo of slm_tb is
-- Input ports
signal clk: std_logic := '1';
signal message: std_logic := '0';
signal display: std_logic := '0';
signal start: std_logic := '1';
-- Output ports
signal seg14: std_logic_vector (13 downto 0);
signal lengthLED: std_logic;
begin
DUT:
entity work.sauvezlesmorses
port map (
clk => clk,
message => message,
display => display,
start => start,
seg14 => seg14,
lengthLED => lengthLED
);
-- force -freeze sim:/sauvezlesmorses/clk 1 0, 0 {25000000000 ps} -r {50 ms}
-- force -freeze sim:/sauvezlesmorses/display 0 0, 1 {9000000000000 ps} -r {18 sec}
-- force -freeze sim:/sauvezlesmorses/message 0 0, 1 {3200000000000 ps} -r {6.4 sec}
-- force -freeze sim:/sauvezlesmorses/start 1 0 -cancel {0.5 sec}
-- run 40 sec
-- stimulus generators:
CLOCK:
process
begin
wait for 25 ms;
clk <= not clk;
if now > 40 sec then
wait;
end if;
end process;
DISP:
process
begin
wait for 9 sec;
display <= not display;
if now > 35 sec then -- stop simulation at 40 sec
wait;
end if;
end process;
MSG:
process
begin
wait for 3.2 sec;
message <= not message;
if now > 35 sec then
wait;
end if;
end process;
ST:
process
begin
wait for 0.5 sec;
start <= 'U';
wait;
end process;
end architecture;
You do get events:

Related

vhdl invalid memory access (dangling accesses or stack size too small)

I'm trying to recreate a traffic light. And as it seems I have some kind of loop in my program since this message comes up whenever I run my testbench. I know for a fact that the loop in the testbench was okay, at least not the main problem, since once I commented it out, the error message came up again. Once I commented out the ampel (traffic light), the error wasn't there anymore. So my guess is that something is wrong with my ampel entity, but I can't find what it is.
Here the code:
library ieee;
use ieee.std_logic_1164.all;
entity ampel is
port (
clk, reset : in std_logic;
rot, gelb, gruen : out std_logic_vector(3 downto 0)
);
end ampel;
architecture rtl of ampel is
type t_zustand is (a,b,c,d,e,f,g,h);
signal zustand : t_zustand;
signal timer : integer;
begin
rot <= "1111";
process is
begin
wait on clk until clk = '1';
timer <= timer + 1;
if reset = '0' then
zustand <= a;
rot <= "1111";
gelb <= "0000";
gruen <= "0000";
timer <= 2;
else
case zustand is
when a =>
rot <= "1111";
gelb <= "0000";
gruen <= "0000";
if timer = 5 then
zustand <= b;
end if;
when b =>
rot <= "0101";
gelb <= "1010";
gruen <= "0000";
if timer = 10 then
zustand <= c;
end if;
when c =>
rot <= "0101";
gelb <= "0000";
gruen <= "1010";
if timer = 40 then
zustand <= d;
end if;
when d =>
rot <= "0101";
gelb <= "1010";
gruen <= "0000";
if timer = 45 then
zustand <= e;
end if;
when e =>
rot <= "1111";
gelb <= "0000";
gruen <= "0000";
if timer = 50 then
zustand <= b;
end if;
when f =>
rot <= "1010";
gelb <= "0101";
gruen <= "0000";
if timer = 55 then
zustand <= b;
end if;
when g =>
rot <= "1010";
gelb <= "0000";
gruen <= "0101";
if timer = 85 then
zustand <= b;
end if;
when h =>
rot <= "1010";
gelb <= "0101";
gruen <= "0000";
if timer = 90 then
zustand <= b;
end if;
end case;
end if;
end process;
end rtl ;
The testbench:
library ieee;
use ieee.std_logic_1164.all;
entity ampel_tb is
end ampel_tb;
architecture testbench of ampel_tb is
component ampel is
port(
clk, reset : in std_logic;
rot, gelb, gruen : out std_logic_vector(3 downto 0)
);
end component;
signal clk, reset : std_logic;
signal rot, gelb, gruen : std_logic_vector(3 downto 0);
begin
ampel0: ampel port map(clk => clk, reset => reset, rot => rot, gelb => gelb, gruen => gruen);
process begin
reset <= '0';
clk <= '0';
wait for 500 ms;
clk <= '1';
wait for 500 ms;
reset <= '1';
clk <= '0';
wait for 500 ms;
for I in 0 to 180 loop
clk <= '1';
wait for 500 ms;
clk <= '0';
wait for 500 ms;
end loop;
assert false report "End of test";
wait;
end process;
end testbench;

I'd like to display the segment according to differnet clocks, but I can't

stick shape is fixed to the left of the segment and dot segment want to be displayed separately according to the clock. But at the same time, it's displayed
this is an example pic https://imgur.com/LXGVUJO
++)) i want like this pic https://imgur.com/mco1q7P
library ieee;
use ieee.std_logic_1164.all;
entity adventure is
port(clk : in std_logic;
dot_seg : out std_logic;
select_seg : out std_logic_vector(7 downto 0);
player_in : in std_logic_vector(1 downto 0);
seg : out std_logic_vector(6 downto 0));
end adventure;
architecture behavior of adventure is
signal dot_clk : std_logic;
signal player_clk : std_logic;
begin
process(clk)
variable dot_cnt : integer := 0;
variable player_cnt : integer := 0;
begin
if rising_edge(clk) then
if dot_cnt >= 5000000 then -- dot_seg clk
dot_cnt := 0;
dot_clk <= not dot_clk;
else
dot_cnt := dot_cnt + 1;
end if;
if player_cnt >= 50005 then -- player_seg clk
player_cnt := 0;
player_clk <= not player_clk;
else
player_cnt := player_cnt + 1;
end if;
end process;
process(clk, dot_clk, player_clk)
begin
if player_clk = '1' then -- player
case player_in is
when "00" => seg <= "1000110";
when "01" => seg <= "1000011";
when "10" => seg <= "0010101";
when "11" => seg <= "1000110";
end case;
select_seg <= "01111111";
end if;
if dot_clk = '1' then -- dot(road) segment
dot_seg <= '1'; ---- put in seg <= "0000000"; ???
select_seg <= "01011111";
else
dot_seg <='1'; ---- put in seg <= "0000000"; ???
select_seg <= "10101111";
end if;
end process;
end behavior;
Try something like that for your second process
signal digit_display : std_logic := '0';
process(clk)
begin
if rising_edge(clk) then
digit_display <= not(digit_display);
if digit_display = '1' then
dot_seg <= '0';
if player_clk = '1' then -- player
case player_in is
when "00" => seg <= "1000110";
when "01" => seg <= "1000011";
when "10" => seg <= "0010101";
when "11" => seg <= "1000110";
select_seg <= "01111111";
end case;
end if;
else
seg <= "0000000"; -- Full off, I don't know polarity
if dot_clk = '1' then -- dot(road) segment
dot_seg <= '1';
select_seg <= "01011111";
else
dot_seg <='1';
select_seg <= "10101111";
end if;
end if;
end if;
end process;
If clk is too fast to blink digit_display, you can put a counter like that :
signal digit_display_count : unsigned(15 downto 0) := (others => '0');
if digit_display_count = 100 then -- Choose an appropriate value
digit_display <= not(digit_display);
digit_display_count <= (others => '0')
else
digit_display_count <= digit_display_count + 1;
end if;

Interface DHT22 to FPGA - elbert v2

Now i make a circuit to measure temperature and humidity, then display on LCD. This is my code for DHT22, i use Elbert V2.
After genarating my project, it did not go right.
I tested and my program did not to come to "end_sl"( last state). And i dont know why?. Any suggestions for me? thank you.
my code
----------------------------------------------------------------------------------------------------------------------------------------------------------------
entity DHT11 is
generic (
CLK_PERIOD_NS : positive := 83; -- 12MHz
N: positive:= 40);
port(
clk,rst : in std_logic ;
singer_bus: inout std_logic;
dataout: out std_logic_vector (N-1 downto 0);
tick_done: out std_logic
);
end DHT11;
architecture Behavioral of DHT11 is
constant DELAY_1_MS: positive := 1*10**6/CLK_PERIOD_NS+1;
constant DELAY_40_US: positive := 40*10**3/CLK_PERIOD_NS+1;
constant DELAY_80_US: positive := 80*10**3/CLK_PERIOD_NS+1;
constant DELAY_50_US: positive := 50*10**3/CLK_PERIOD_NS+1; --
constant TIME_70_US: positive := 80*10**3/CLK_PERIOD_NS+1; --bit > 70 us
constant TIME_28_uS: positive := 30*10**3/CLK_PERIOD_NS+1; -- bit 0 > 28 us
constant MAX_DELAY : positive := 5*10**6/CLK_PERIOD_NS+1; -- 5 ms
type state_type is (reset,start_m,wait_res_sl,response_sl,delay_sl,start_sl,consider_logic,end_sl);
signal index, next_index : natural range 0 to MAX_DELAY;
signal state, next_state : state_type;
signal data_out,next_data_out: std_logic_vector (N-1 downto 0);
signal bit_in, next_bit_in: std_logic;
signal number_bit,next_number_bit: natural range 0 to 40;
signal oe: std_logic; -- help to set input and output port.
begin
--register
regis_state:process (clk,rst) begin
if rst = '1' then
state <= reset;
index <= MAX_DELAY;
number_bit <= 0;
bit_in <= '1';
data_out <= (others => '0');
elsif rising_edge(clk) then
state <= next_state;
index <= next_index;
number_bit <= next_number_bit;
bit_in <= next_bit_in;
data_out <= next_data_out;
end if;
end process regis_state;
proces_state: process (singer_bus,index,state,bit_in,number_bit,data_out) begin
tick_done <= '0';
next_data_out <= data_out;
next_number_bit <= number_bit;
next_state <= state;
next_data_out <= data_out;
next_index <= index;
dataout <= (others => '0');
oe <= '0';
next_bit_in <= bit_in;
case(state) is
when reset => -- initial
if index = 0 then
next_state <= start_m;
next_index <= DELAY_1_MS;
next_number_bit <= N-1;
else
next_state <= reset;
next_index <= index - 1;
end if;
when start_m => -- master send '1' in 1ms
if index = 0 then
next_state <= wait_res_sl;
next_index <= DELAY_40_US;
else
oe <= '1';
next_state <= start_m;
next_index <= index -1;
end if ;
when wait_res_sl => -- wait for slave response in 40us --
next_bit_in <= singer_bus;
if bit_in ='1' and next_bit_in = '0' then --
next_state <= response_sl;
else
next_state <= wait_res_sl;
end if;
when response_sl => -- slave response in 80us
next_bit_in <= singer_bus;
if bit_in ='0' and next_bit_in = '1' then
next_state <= delay_sl;
else
next_state <= response_sl;
end if;
when delay_sl => -- wait for slave delay in 80us
if bit_in = '1' and next_bit_in ='0' then
next_state <= start_sl;
else
next_state <= delay_sl;
end if;
when start_sl => -- start to prepare in 50us
if (bit_in = '0') and (next_bit_in = '1') then
next_state <= consider_logic;
next_index <= 0;
elsif number_bit = 0 then
next_state <= end_sl;
next_index <= DELAY_50_US;
else
next_state <= start_sl;
end if;
when consider_logic => -- determine 1 bit-data of slave
next_index <= index + 1;
next_bit_in <= singer_bus;
if bit_in = '1' and next_bit_in = '0' then -- the end of logic state
next_number_bit <= number_bit -1;
if (index < TIME_28_uS) then -- time ~ 28 us - logic = '0'
next_data_out <= data_out(N-2 downto 0) & '0';
elsif (index < TIME_70_US) then -- time ~70 us - logic ='1'
next_data_out <= data_out(N-2 downto 0) & '1';
end if;
next_state <= start_sl;
next_index <= DELAY_50_US;
elsif bit_in ='1' and next_bit_in ='1' then
next_state <= consider_logic;
end if;
when end_sl => -- tick_done = '1' then dataout has full 40 bit.
if index = 0 then
next_index <= MAX_DELAY;
next_state <= reset;
else
tick_done <= '1';
dataout <= data_out;
next_index <= index -1;
next_state <= end_sl;
end if;
end case;
end process proces_state;
--tristate IOBUFFER
singer_bus <= '0' when oe ='1' else 'Z';
end Behavioral;
There are many errors in your code. How did you debug exactly? Because it seems like you did not.
Why wait for 60 ms after the reset? you waste (valuable) simulation time. 6 ms is more then enough.
Looking at the simulation output, you can see the state does not advance at all: it's stuck ini wait_res_sl. The problem is that you have not added all the signals read in the process to the sensitivity list. I.e.
bit_in ='1' and next_bit_in = '0'
Will not detect a change if next_bit_in is not in the sensitivity list.
A problem -a common mistake made- is that your 'test bench' only provides input stimuli.... But it does not actually test anything.
And then the counters. Why is the delay counter called index? It doesn't index anything.
Why do your time delays not match their label? 70us -> 80 us. 28us -> 30 us.
Small thing don't call a RTL architecture behavioral
I tried to clean your code, seems to work now.
library ieee;
use ieee.std_logic_1164.all;
entity dht2 is
generic (
clk_period_ns : positive := 83; -- 12mhz
data_width: positive:= 40);
port(
clk,rst : in std_logic ;
singer_bus: inout std_logic;
dataout: out std_logic_vector(data_width-1 downto 0);
tick_done: out std_logic
);
end entity;
architecture rtl of dht2 is
constant delay_1_ms: positive := 1*10**6/clk_period_ns+1;
constant delay_40_us: positive := 40*10**3/clk_period_ns+1;
constant delay_80_us: positive := 80*10**3/clk_period_ns+1;
constant delay_50_us: positive := 50*10**3/clk_period_ns+1; --
constant time_70_us: positive := 70*10**3/clk_period_ns+1; --bit > 70 us
constant time_28_us: positive := 28*10**3/clk_period_ns+1; -- bit 0 > 28 us
constant max_delay : positive := 5*10**6/clk_period_ns+1; -- 5 ms
signal input_sync : std_logic_vector(0 to 2);
type state_type is (reset,start_m,wait_res_sl,response_sl,delay_sl,start_sl,consider_logic,end_sl);
signal state : state_type;
signal delay_counter : natural range 0 to max_delay;
signal data_out : std_logic_vector (data_width-1 downto 0);
signal bus_rising_edge, bus_falling_edge : boolean;
signal number_bit : natural range 0 to data_width;
signal oe: std_logic; -- help to set input and output port.
begin
input_syncronizer : process(clk) begin
if rising_edge(clk) then
input_sync <= to_x01(singer_bus)&input_sync(0 to 1);
end if;
end process;
bus_rising_edge <= input_sync(1 to 2) = "10";
bus_falling_edge <= input_sync(1 to 2) = "01";
--register
regis_state:process (clk) begin
if rising_edge(clk) then
case(state) is
when reset => -- initial
if delay_counter = 0 then
number_bit <= data_width;
oe <= '1';
delay_counter <= delay_1_ms;
state <= start_m;
else
delay_counter <= delay_counter - 1;
end if;
when start_m => -- master send '1' in 1ms
if delay_counter = 0 then
oe <= '0';
delay_counter <= delay_40_us;
state <= wait_res_sl;
else
delay_counter <= delay_counter -1;
end if ;
when wait_res_sl => -- wait for slave response in 40us --
if bus_falling_edge then --
state <= response_sl;
end if;
when response_sl => -- slave response in 80us
if bus_rising_edge then
state <= delay_sl;
end if;
when delay_sl => -- wait for slave delay in 80us
if bus_falling_edge then
state <= start_sl;
end if;
when start_sl => -- start to prepare in 50us
if bus_rising_edge then
delay_counter <= 0;
state <= consider_logic;
elsif number_bit = 0 then
delay_counter <= delay_50_us;
state <= end_sl;
end if;
when consider_logic => -- determine 1 bit-data of slave
if bus_falling_edge then -- the end of logic state
number_bit <= number_bit - 1;
if (delay_counter < time_28_us) then -- time ~ 28 us - logic = '0'
data_out <= data_out(data_width-2 downto 0) & '0';
elsif (delay_counter < time_70_us) then -- time ~70 us - logic ='1'
data_out <= data_out(data_width-2 downto 0) & '1';
end if;
delay_counter <= delay_50_us;
state <= start_sl;
end if;
delay_counter <= delay_counter + 1;
when end_sl => -- tick_done = '1' then dataout has full 40 bit.
if delay_counter = 0 then
delay_counter <= max_delay;
state <= reset;
else
tick_done <= '1';
dataout <= data_out;
delay_counter <= delay_counter - 1;
end if;
end case;
if rst = '1' then
number_bit <= 0;
data_out <= (others => '0');
delay_counter <= max_delay;
state <= reset;
end if;
end if;
end process regis_state;
--tristate iobuffer
singer_bus <= '0' when oe ='1' else 'Z';
end architecture;
And test bench: I added one check, but you should make more checks: every time you do something, it should have an effect. You should test if that effect actually happens.
entity dht2_tb is end dht2_tb;
library ieee;
architecture behavior of dht2_tb is
use ieee.std_logic_1164.all;
--inputs
signal clk : std_logic := '0';
signal rst : std_logic := '0';
--bidirs
signal singer_bus : std_logic := 'H';
--outputs
signal tick_done : std_logic;
-- clock period definitions
constant clk_period : time := 83.33 ns; -- 12mhz
use ieee.math_real.all;
-- This function generates a 'slv_length'-bit std_logic_vector with
-- random values.
function random_slv(slv_length : positive) return std_logic_vector is
variable output : std_logic_vector(slv_length-1 downto 0);
variable seed1, seed2 : positive := 65; -- required for the uniform function
variable rand : real;
-- Assume mantissa of 23, according to IEEE-754:
-- as UNIFORM returns a 32-bit floating point value between 0 and 1
-- only 23 bits will be random: the rest has no value to us.
constant rand_bits : positive := 23;
-- for simplicity, calculate remaining number of bits here
constant end_bits : natural := slv_length rem rand_bits;
use ieee.numeric_std.all;
begin
-- fill sets of 23-bit of the output with the random values.
for i in 0 to slv_length/rand_bits-1 loop
uniform(seed1, seed2, rand); -- create random float
-- convert float to int and fill output
output((i+1)*rand_bits-1 downto i*rand_bits) :=
std_logic_vector(to_unsigned(integer(rand*(2.0**rand_bits)), rand_bits));
end loop;
-- fill final bits (< 23, so above loop will not work.
uniform(seed1, seed2, rand);
if end_bits /= 0 then
output(slv_length-1 downto slv_length-end_bits) :=
std_logic_vector(to_unsigned(integer(rand*(2.0**end_bits)), end_bits));
end if;
return output;
end function;
-- input + output definitions
constant test_data_length : positive := 32;
constant test_data : std_logic_vector(test_data_length-1 downto 0) := random_slv(test_data_length);
signal data_out : std_logic_vector(test_data_length-1 downto 0);
begin
-- instantiate the unit under test (uut)
uut: entity work.dht2 -- use entity instantiation: no component declaration needed
generic map (
clk_period_ns => clk_period / 1 ns,
data_width => test_data_length)
port map (
clk => clk,
rst => rst,
singer_bus => singer_bus,
dataout => data_out,
tick_done => tick_done
);
-- clock stimuli
clk_process: process begin
clk <= '0', '1' after clk_period/2;
wait for clk_period;
end process;
-- reset stimuli
rst_proc : process begin
rst <= '1', '0' after 100 us;
wait;
end process;
-- bidir bus pull-up
-- as you drive the bus from the uut and this test bench, it is a bidir
-- you need to simulate a pull-up ('H' = weak '1'). slv will resolve this.
singer_bus <= 'H';
-- stimulus process
bus_proc: process
-- we use procedures for stimuli. Increases maintainability of test bench
-- procedure bus_init initializes the slave device. (copied this from your code)
procedure bus_init is begin
-- singer_bus <= 'Z'; -- initial
wait for 6 ms;
-- singer_bus <= '0'; -- master send
-- wait for 1 ms;
singer_bus <= 'Z'; -- wait response for slave
wait for 40 us;
singer_bus <= '0'; -- slave pull low
wait for 80 us;
singer_bus <= 'Z'; -- slave pull up
wait for 80 us;
end procedure;
function to_string(input : std_logic_vector) return string is
variable output : string(1 to input'length);
variable j : positive := 1;
begin
for i in input'range loop
output(j) := std_logic'image(input(i))(2);
j := j + 1;
end loop;
return output;
end function;
-- procedure send_data
procedure send_data(data : std_logic_vector) is begin
-- we can now send a vector of data,length detected automatically
for i in data'range loop
singer_bus <= '0'; -- slave start data transmission
wait for 50 us;
singer_bus <= 'Z'; -- slave send bit;
-- I found the only difference between sending bit '0'
-- and '1' is the length of the delay after a '0' was send.
case data(i) is
when '0' => wait for 24 us;
when '1' => wait for 68 us;
when others =>
report "metavalues not supported for bus_proc send_data"
severity failure;
end case;
singer_bus <= '0';
end loop;
-- next is VHDL-2008 (else use ieee.std_logic_textio.all;)
report "transmitted: "&to_string(data);
end procedure;
begin
wait until rst = '0';
bus_init; -- call procedure
send_data(test_data); -- call procedure
wait for 100 us; -- final delay
singer_bus <= 'Z'; -- release bus
report "received: "&to_string(data_out);
-- test correctness of output
assert data_out = test_data
report "data output does not match send data"
severity error;
report "end of simulation" severity failure;
end process;
end architecture;

VHDL Traffic Light Controller

Here is a simple code for a traffic light controller. It cycles through the states according to the counter values. However I would like it stay an additional 10 seconds on the first state when a pushbutton is pressed any ideas how I would do that.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
entity TLC is
Port (
Trafficlights: out STD_LOGIC_Vector (5 downto 0);
Clck : in STD_LOGIC;
Reset : in STD_LOGIC;
P_B : in STD_LOGIC);
end TLC;
architecture Behavioral of TLC is
type state_type is (st0_R1_G2, st1_R1_A1_A2, st2_G1_R2, st3_A1_R2_A2);
signal state: state_type;
signal count : std_logic_vector (3 downto 0);
constant sec10 : std_logic_vector ( 3 downto 0) := "1010";
constant sec2 : std_logic_vector (3 downto 0 ) := "0010";
constant sec16: std_logic_vector (3 downto 0 ) := "1111";
begin
process (Clck,Reset)
begin
if Reset='1' then
state <= st0_R1_G2; --reset to initial state
count <= X"0"; -- reset counter
elsif Clck' event and Clck = '1' then --rising edge
case (state) is ---state transitions
when st0_R1_G2 =>
if count < sec10 then
state <= st0_R1_G2;
count <= count + 1;
else
state <= st1_R1_A1_A2;
count <= X"0";
end if;
when st1_R1_A1_A2 =>
if count < sec2 then
state <= st1_R1_A1_A2;
count <= count + 1;
else
state <= st2_G1_R2;
count <= X"0";
end if;
when st2_G1_R2 =>
if count < sec10 then
state <= st2_G1_R2;
count <= count + 1;
else
state <= st3_A1_R2_A2;
count <= X"0";
end if;
when st3_A1_R2_A2 =>
if count < sec2 then
state <= st3_A1_R2_A2;
count <= count + 1;
else
state <=st0_R1_G2;
count <= X"0";
end if;
when others =>
state <= st0_R1_G2;
end case;
end if;
end process;
OUTPUT_DECODE: process (state)
begin
case state is
when st0_R1_G2 => Trafficlights <= "100001"; -- Traffic Red 1, Pedestrian Green 1
when st1_R1_A1_A2 => Trafficlights <= "110010";
when st2_G1_R2 => Trafficlights <= "001100";
when st3_A1_R2_A2 => Trafficlights <= "010110";
when others => Trafficlights <= "100001";
end case;
end process;
end Behavioral;
I haven't simulated this.
The idea is to extend the count counter by a bit encompassing the extra 10 seconds. The input p_b is used to asynchronously set a pushbutton event latch which is used to start an extended count, presumably allowing crosswalk traffic to traverse in the first 10 seconds.
It's controlled by a JK Flip flop (crosstime). The noticeable feature here should be that the cross walk is enabled for the first 10 seconds of the extended 20 sec period only. You don't give permission out of the blue to cross.
All this assumes your push button is an on demand pedestrian crossing request, you don't explain your state names nor your lights.
I'm guessing you'd want to gate the pedestrian green light with crosstime.
(And if this doesn't work or isn't what you wanted, you got what you paid for.)
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity tlc is
port (
trafficlights: out std_logic_vector (5 downto 0);
clck: in std_logic;
reset: in std_logic;
p_b: in std_logic
);
end entity tlc;
architecture behavioral of tlc is
type state_type is (st0_r1_g2, st1_r1_a1_a2, st2_g1_r2, st3_a1_r2_a2);
signal state: state_type;
signal count: std_logic_vector (4 downto 0) ; -- (3 downto 0);
signal pb_event: std_logic;
signal crosstime: std_logic; -- JK FF
constant sec10 : std_logic_vector (4 downto 0) := "01010"; -- ( 3 downto 0) := "1010";
constant sec2 : std_logic_vector (4 downto 0) := "00010"; -- (3 downto 0 ) := "0010";
-- constant sec16: std_logic_vector (4 downto 0) := "01111"; -- (3 downto 0 ) := "1111";
constant sec20: std_logic_vector (4 downto 0) := "10100"; -- new
begin
process (clck, reset, p_b) -- added push button
begin
if p_b = '1' and reset = '0' then -- asynch set for push button
pb_event <= '1';
end if;
if reset = '1' then
state <= st0_r1_g2; -- reset to initial state
count <= (others => '0'); -- reset counter
pb_event <= '0';
crosstime <= '0';
elsif clck' event and clck = '1' then -- rising edge
if pb_event = '1' and count = "00000" then -- J input
crosstime <= '1';
end if;
case (state) is -- state transitions
when st0_r1_g2 =>
if (crosstime = '0' and count < 20) or
(crosstime = '1' and count < sec10) then
state <= st0_r1_g2;
count <= count + 1;
else
state <= st1_r1_a1_a2;
count <= "00000"; -- x"0";
if crosstime = '1' then -- K input
crosstime <= '0';
pb_event <= '0';
end if;
end if;
when st1_r1_a1_a2 =>
if count < sec2 then
state <= st1_r1_a1_a2;
count <= count + 1;
else
state <= st2_g1_r2;
count <= (others => '0');
end if;
when st2_g1_r2 =>
if count < sec10 then
state <= st2_g1_r2;
count <= count + 1;
else
state <= st3_a1_r2_a2;
count <= (others => '0');
end if;
when st3_a1_r2_a2 =>
if count < sec2 then
state <= st3_a1_r2_a2;
count <= count + 1;
else
state <=st0_r1_g2;
count <= (others => '0');
end if;
when others =>
state <= st0_r1_g2;
end case;
end if;
end process;
output_decode:
process (state)
begin
case state is
when st0_r1_g2 => trafficlights <= "100001"; -- traffic red 1, pedestrian green 1
when st1_r1_a1_a2 => trafficlights <= "110010";
when st2_g1_r2 => trafficlights <= "001100";
when st3_a1_r2_a2 => trafficlights <= "010110";
when others => trafficlights <= "100001";
end case;
end process;
end architecture behavioral;
* ... Ive tried to synthesize this and I get and error saying "Signal pb_event cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release." Any ideas do you thik this is because its asynch and not compatible with the rest of the synchronous design ?*
Without knowing the vendor complaining about pb_even it sort of ties our hands.
It appears to be complaining about having both an asynchronous set and asynchronous reset on pb_event. Removing the asynchronous reset would likely cure the problem (the set is needed to tell us someone wants to use the crosswalk).
Let's move the pb_event flip flop out of the present process to make that available. The consequence of only using the set input is that a reset will set pb_event and cause a first crosswalk event.
Note I still don't understand the trafficlights and the modification I made in state st0_r1_g2 anticipates the crosswalk light is enabled during the first 10 seconds of the longer 20 second interval. That isn't included here.
Also you could simply equality compare count to the end counts, "/=" instead of "<" which might result is less count comparison logic. This can happen because count is always between 0 and an end count inclusively. Equality is a lot easier than magnitude comparison. I didn't make those changes either (and I'd be tempted to have separate recognizers for the count terminal values).
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity tlc is
port (
trafficlights: out std_logic_vector (5 downto 0);
clck: in std_logic;
reset: in std_logic;
p_b: in std_logic
);
end entity tlc;
architecture behavioral of tlc is
type state_type is (st0_r1_g2, st1_r1_a1_a2, st2_g1_r2, st3_a1_r2_a2);
signal state: state_type;
signal count: std_logic_vector (4 downto 0) ;
signal pb_event: std_logic;
signal crosstime: std_logic; -- JK FF
constant sec10 : std_logic_vector (4 downto 0) := "01010";
constant sec2 : std_logic_vector (4 downto 0) := "00010";
constant sec20: std_logic_vector (4 downto 0) := "10100";
begin
pbevent:
process (clck, reset, p_b)
begin
if p_b = '1' or reset = '1' then -- async set for push button
pb_event <= '1'; -- reset will give crosswalk event
elsif clck'event and clck = '1' then
if state = st0_r1_g2 and
(( crosstime = '1' and count = sec10) or count = sec20) then
pb_event <= '0';
end if;
end if;
end process;
unlabelled:
process (clck, reset)
begin
if reset = '1' then
state <= st0_r1_g2; -- reset to initial state
count <= (others => '0'); -- reset counter
crosstime <= '0';
elsif clck'event and clck = '1' then
if pb_event = '1' and count = "00000" then -- J input
crosstime <= '1';
end if;
case (state) is
when st0_r1_g2 =>
if (crosstime = '0' and count < sec20) or
(crosstime = '1' and count < sec10) then
state <= st0_r1_g2;
count <= count + 1;
else
state <= st1_r1_a1_a2;
count <= "00000";
if crosstime = '1' then -- K input
crosstime <= '0';
end if;
end if;
when st1_r1_a1_a2 =>
if count < sec2 then
state <= st1_r1_a1_a2;
count <= count + 1;
else
state <= st2_g1_r2;
count <= (others => '0');
end if;
when st2_g1_r2 =>
if count < sec10 then
state <= st2_g1_r2;
count <= count + 1;
else
state <= st3_a1_r2_a2;
count <= (others => '0');
end if;
when st3_a1_r2_a2 =>
if count < sec2 then
state <= st3_a1_r2_a2;
count <= count + 1;
else
state <=st0_r1_g2;
count <= (others => '0');
end if;
when others =>
state <= st0_r1_g2;
end case;
end if;
end process;
output_decode:
process (state)
begin
case state is
when st0_r1_g2 => trafficlights <= "100001"; -- traffic red 1, pedestrian green 1
when st1_r1_a1_a2 => trafficlights <= "110010";
when st2_g1_r2 => trafficlights <= "001100";
when st3_a1_r2_a2 => trafficlights <= "010110";
when others => trafficlights <= "100001";
end case;
end process;
end architecture behavioral;
The conditions found in state st0_r1_g2 have been collapsed to separately write a '0' to the pb_event flip flop. You might anticipate any time count = sec20 the flip flop should be cleared.

VHDL change CLK speed

From this code I create a block, then add CLK, KEY[0] and LEDR[0:15]
library ieee;
use ieee.std_logic_1164.all;
--library work;
--use work.car_pkg.all;
entity knight_rider2 is
port ( clk, resetn, clock_button : in std_logic;
led1, led2, led3, led4, led5, led6, led7, led8,
led9, led10, led11, led12, led13, led14, led15 : out std_logic);
end entity knight_rider2;
architecture fsm of knight_rider2 is
type state_types is (start, forward1, forward2, forward3,
forward4, forward5, forward6, forward7, forward8, forward9,
forward10,forward11,forward12, forward13, forward14);
signal state: state_types;
signal led_states : std_logic_vector(14 downto 0);
begin
count : process(clk, resetn, clock_button)
begin
if clock_button = '0' then
counter <= 0;
fsm_pulse <= '0';
else
if rising_edge(clk) then
counter <= counter + 1;
fsm_pulse <= '0';
if counter = divider then
fsm_pulse <= '1';
counter <= 0;
end if;
end if;
end if;
end process;
combined_next_current: process (clk, resetn, clock_button)
begin
if (resetn = '0') then
state <= start;
elsif rising_edge(clk) then
if fsm_pulse = '1' then
case state is
when start =>
state <= forward1;
when forward1 =>
state <= forward2;
when forward2 =>
state <= forward3;
when forward3 =>
state <= forward4;
when forward4 =>
state <= forward5;
when forward5 =>
state <= forward6;
when forward6 =>
state <= forward7;
when forward7 =>
state <= forward8;
when forward8 =>
state <= forward9;
when forward9 =>
state <= forward10;
when forward10 =>
state <= forward11;
when forward11 =>
state <= forward12;
when forward12 =>
state <= forward13;
when forward13 =>
state <= forward14;
when forward14 => state <=start;
when others =>
state <= forward1;
end case;
end if;
end process;
--combinational output logic
--internal signal to control state machine transistions
led_select : process(state)
begin
case state is
when forward1 =>
led_states <= "000000000000011";
when forward2 =>
led_states <= "000000000000110";
when forward3 =>
led_states <= "000000000001100";
when forward4 =>
led_states <= "000000000011000";
when forward5 =>
led_states <= "000000000110000";
when forward6 =>
led_states <= "000000001100000";
when forward7 =>
led_states <= "000000011000000";
when forward8 =>
led_states <= "000000110000000";
when forward9 =>
led_states <= "000001100000000";
when forward10 =>
led_states <= "000011000000000";
when forward11=>
led_states <= "000110000000000";
when forward12=>
led_states <= "001100000000000";
when forward13=>
led_states <= "011000000000000";
when forward14=>
led_states <= "110000000000000";
when others =>
led_states <= "100000000000001";
end case;
end process;
led1 <= led_states(0);
led2 <= led_states(1);
led3 <= led_states(2);
led4 <= led_states(3);
led5 <= led_states(4);
led6 <= led_states(5);
led7 <= led_states(6);
led8 <= led_states(7);
led9 <= led_states(8);
led10 <= led_states(9);
led11 <= led_states(10);
led12 <= led_states(11);
led13 <= led_states(12);
led14 <= led_states(13);
led15 <= led_states(14);
end;
But now I want add KEY[1] button to change speed, for example:
1st press : 2*f
2 press: 4*f
3 press: 8*f
4 press: f
5 press: 2*f etc
So, how can I change this code to do what I want?
You can change the rate that your state machine operates at by employing a counter, for example:
-- Generate a counter at your main clock frequency
-- counter is declared as an integer.
count : process(clock, resetn)
begin
if resetn = '0' then
counter <= 0;
fsm_pulse <= '0';
else
if rising_edge(clock) then
counter <= counter + 1;
fsm_pulse <= '0';
if counter = divider then
fsm_pulse <= '1';
counter <= 0;
end if;
end if;
end if;
end process;
The new signals are declared as follows:
signal fsm_pulse : std_logic;
signal counter : integer;
signal divider : integer;
Then, in your FSM process you can trigger state transitions using the fsm_pulse you generated:
combined_next_current: process (clk, resetn)
begin
if (resetn = '0') then
state <= start;
elsif rising_edge(clk) then
if fsm_pulse = '1' then
case state is
when start =>
state <= forward1;
when forward1 =>
state <= forward2;
...
etc (your remaining states)
end if;
The fsm_pulse will be set to '1' for a single clock cycle whenever the counter reaches the divider value you have chosen. The divider value represents the number of clock cycles you desire each FSM transition to occur after, for example a divider of zero will make the FSM transition at the main clock frequency and a divider of 1 will make the FSM transition at halve the main clock frequency.

Resources