VHDL Traffic Light Controller - vhdl

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.

Related

Different Clock Domain VHDL

I'm making a custom hardware ARINC 429 Core.
For now I have described the module in transmission (TX-FSM), according to the ARINC 429 standard and a FIFO in transmission from which it takes the data and sends them to the outside.
The FIFO works at a frequency of 2MHz (clk2M), while TX-FSM can generate a frequency of 100kb / s or 12.5kb / s (clk429) from 2MHz as per standard.
Since the FIFO works at a higher frequency (2 MHz), and the TX-FSM works at a lower frequency (100 kb/s), when the TX-FSM requests a data from the FIFO by raising the "TX_FIFO_rd" signal ("rd_en" on FIFO ), the FIFO supplies all the data contained within it, since in the FIFO clock domain the "rd_en" signal remains high for several cycles.
The FIFO should only provide one data at a time. Once the data has been transmitted, the TX-FSM will request the next data.
How can I make the FIFO and TX-FSM work in sync using a single clock?
FIFO VHDL code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity FIFO is
generic (
FIFO_WIDTH : natural := 32;
FIFO_DEPTH : integer := 10;
ALMOST_FULL_LEVEL : integer := 8;
ALMOST_EMPTY_LEVEL : integer := 2
);
port (
reset : in std_logic;
clk : in std_logic;
-- FIFO Write Interface
wr_en : in std_logic;
wr_data : in std_logic_vector(FIFO_WIDTH-1 downto 0);
ALMOST_FULL : out std_logic;
FULL : out std_logic;
-- FIFO Read Interface
rd_en : in std_logic;
rd_data : out std_logic_vector(FIFO_WIDTH-1 downto 0);
ALMOST_EMPTY : out std_logic;
EMPTY : out std_logic
);
end FIFO;
architecture rtl of FIFO is
type t_FIFO_DATA is array (0 to FIFO_DEPTH) of std_logic_vector(FIFO_WIDTH-1 downto 0);
signal r_FIFO_DATA : t_FIFO_DATA := (others => (others => '0'));
signal r_WR_INDEX : integer range 0 to FIFO_DEPTH -1 := 0;
signal r_RD_INDEX : integer range 0 to FIFO_DEPTH -1 := 0;
-- # Words in FIFO, has extra range to allow for assert conditions
signal r_FIFO_COUNT : integer range -1 to FIFO_DEPTH+1 := 0;
signal w_FULL : std_logic;
signal w_EMPTY : std_logic;
begin
-- FIFO process
-------------------------------------------------------------------
-------------------------------------------------------------------
WRITE_INDEX : process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
r_WR_INDEX <= 1;
else
if (wr_en = '1' and w_FULL = '0') then
if r_WR_INDEX = FIFO_DEPTH-1 then
r_WR_INDEX <= 1;
else
r_WR_INDEX <= r_WR_INDEX + 1;
end if;
end if;
end if;
end if;
end process;
READ_INDEX : process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
r_RD_INDEX <= 0;
else
if (rd_en = '1' and w_EMPTY = '0') then
if r_RD_INDEX = FIFO_DEPTH-1 then
r_RD_INDEX <= 0;
else
r_RD_INDEX <= r_RD_INDEX + 1;
end if;
end if;
end if;
end if;
end process;
COUNT_INDEX : process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
r_FIFO_COUNT <= 0;
else
if (wr_en = '1' and rd_en = '0') then
r_FIFO_COUNT <= r_FIFO_COUNT + 1;
elsif (wr_en = '0' and rd_en = '1') then
if r_FIFO_COUNT > 0 then
r_FIFO_COUNT <= r_FIFO_COUNT - 1;
end if;
end if;
end if;
end if;
end process;
Write_Data : process (clk) is
begin
if rising_edge(clk) then
if wr_en = '1' then
r_FIFO_DATA(r_WR_INDEX) <= wr_data;
end if;
end if;
end process;
rd_data <= r_FIFO_DATA(r_RD_INDEX);
w_FULL <= '1' when r_FIFO_COUNT = FIFO_DEPTH else '0';
w_EMPTY <= '1' when r_FIFO_COUNT = 0 else '0';
ALMOST_FULL <= '1' when r_FIFO_COUNT > ALMOST_FULL_LEVEL else '0';
ALMOST_EMPTY <= '1' when r_FIFO_COUNT < ALMOST_EMPTY_LEVEL else '0';
FULL <= w_FULL;
EMPTY <= w_EMPTY;
end rtl;
TX-FSM code
-- Arinc 429 trasmitter interface
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Tx is
port
(
--INPUT
clk2M : in std_logic; -- clock signal
reset : in std_logic; -- reset signal
enable : in std_logic; -- enable signal
en_parity : in std_logic; -- enable parity bit
parity : in std_logic; -- odd/even parity
speed : in std_logic; -- speed 100kbps or 12.5kbps
gap : in std_logic; -- gap between two messages: 4 or 64 bit of gap
TX_FIFO_ep : in std_logic; -- TX FIFO EMPTY
a429TX_in : in std_logic_vector (31 downto 0); -- data in
--OUTPUT
a429TX_outA : out std_logic; -- positive out
a429TX_outB : out std_logic; -- negative out
TX_FIFO_rd : out std_logic -- TX FIFO READ
);
end entity;
architecture RTL_A429TX of Tx is
-- FSM state name
type state_type is (IDLE,START, PAR,TRANSMITTING,WAITING);
signal state : state_type;
-- FSM register
signal shift_reg : std_logic_vector (31 downto 0);
signal shift_counter : std_logic_vector (4 downto 0);
signal gap_counter : std_logic_vector (6 downto 0);
-- speed clock register
signal clk429 : std_logic;
signal clk429_counter : integer;
signal clk429_max_count : integer;
signal clk429_half_count : integer;
begin
-- speed clock process
-------------------------------------------------------------------
-------------------------------------------------------------------
-- select speed process
process (speed)
begin
if (speed = '1') then
clk429_max_count <= 19; -- 100kbs/s
clk429_half_count <= 10;
else
clk429_max_count <= 159; -- 12.5kbs/s
clk429_half_count <= 80;
end if;
end process;
-- clock429 generate speed process
process (clk2M, reset)
begin
if (reset = '1') then
clk429 <= '0';
elsif rising_edge(clk2M) then
if (clk429_counter <= clk429_half_count ) then
clk429 <= '1';
else
clk429 <= '0';
end if;
end if;
end process;
-- counter activity process
process (clk2M, reset)
begin
if (reset = '1') then
clk429_counter <= 0;
elsif rising_edge(clk2M) then
if (clk429_counter >= clk429_max_count) then
clk429_counter <= 0;
else
clk429_counter <= clk429_counter + 1;
end if;
end if;
end process;
-------------------------------------------------------------------
-------------------------------------------------------------------
-- a429TX interface process
process (clk429, reset)
variable p : std_logic;
begin
if reset = '1' then
state <= IDLE;
shift_reg <= (others => '0');
shift_counter <= (others => '0');
gap_counter <= (others => '0');
a429TX_outA <= '0';
a429TX_outB <= '0';
TX_FIFO_rd <= '0';
elsif rising_edge(clk429) then
case state is
when IDLE => -- idle state
if (enable = '1') then
if (gap = '1') then
gap_counter <= "0000100"; -- 4
else
gap_counter <= "1000000"; -- 64
end if;
if TX_FIFO_ep = '0' then
TX_FIFO_rd <= '1';
state <= START;
else
state <= IDLE;
end if;
else
state <= IDLE;
end if;
when START =>
-- data formatting
TX_FIFO_rd <= '0';
shift_reg <= a429TX_in(31 downto 8)& a429TX_in(0) & a429TX_in(1) & a429TX_in(2) & a429TX_in(3) & a429TX_in(4) & a429TX_in(5) & a429TX_in(6) & a429TX_in(7);
shift_counter <= "11111";
if ( en_parity = '1') then
state <= PAR;
else
state <= TRANSMITTING;
end if;
when PAR => -- parity state
--TX_FIFO_rd <= '0';
p := '0';
for I in 31 downto 0 loop
p := p xor shift_reg(I);
end loop;
if (parity = '1') then
shift_reg(31) <= p; -- odd
else
shift_reg(31) <= not p; -- even
end if;
state <= TRANSMITTING;
when TRANSMITTING => -- transmission state
--TX_FIFO_rd <= '0';
a429TX_outA <= shift_reg(0);
a429TX_outB <= not shift_reg(0);
shift_reg <= shift_reg(0) & shift_reg(31 downto 1);
if (shift_counter = "00000") then
state <= WAITING;
else
shift_counter <= shift_counter -1;
state <= TRANSMITTING;
end if;
when WAITING => -- wait state. generate gap
a429TX_outA <= '0';
a429TX_outB <= '0';
if (gap_counter > 0) then
gap_counter <= gap_counter - 1;
state <= WAITING;
else
state <= IDLE;
end if;
when others => -- default
state <= IDLE;
end case;
elsif falling_edge (clk429) then
a429TX_outA <= '0';
a429TX_outB <= '0';
end if;
end process;
clk429 <= clk429;
end architecture;
Thanks for your help.
Run both FIFOs at the 2 MHz clk2M, and then generate a single cycle enable indication on TX_FIFO_rd when FIFO read data transfer is required.
Thereby you can get the benefit from synchronous design, without the hazzle of handling multiple clock domains.
Also, it is not good (but actually very bad :-) synchronous design practice to generate internal clock like the clk429, since it results in error prune design and more complex timing closure with Static Timing Analysis (STA). Instead make an enable signal that is asserted a single cycle, run the design on the clk2M, and the only update the relevant state when the enable signal is high.

Implementing a short pulse signal triggered by a push button on a Spartan 3E

I'm trying to implement an "emergency" function on a traffic light controller.
This emergency signal is an std_logic input, and it's triggered by a push button (using a ucf file).
What this signal does is basically whenever the push button is pressed, the controller will detect which of the two roads (north to south or west to east) is on red and it'll immediately switch it to orange (the other one , of course, will turn red) to let the emergency vehicle pass (an ambulance, for example).
I've tried to denounce the switch and then feed the denounced signal into a rising-edge detector. It didn't work: pressing the emergency button makes the red and yellow lights of both roads (NS and WE) light at the same time, just a disaster, the counter which I used to configure how long each light is on also gets disturbed for quite a while before going back to normal.
Here's my code so far:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity TLC is
Port (
Clck : in STD_LOGIC;
Reset: in STD_LOGIC;
emergency:in std_logic;
Trafficlights: out STD_LOGIC_Vector (5 downto 0) --trafficlights (5 downto 3) for the NS road and (2 downto 0) for the WE road.
);
end TLC;
architecture Behavioral of TLC is
-------------for debouncing
constant COUNT_MAX : integer := 20;
constant BTN_ACTIVE : std_logic := '1';
signal count1 : integer := 0;
type state_type1 is (idle,wait_time);
signal state1 : state_type1 := idle;
signal emergency_debounced:std_logic;
-----------------------------------------
type state_type is (NRWG, NRWY, NGWR, NYWR); --NRWG: North-South on red and West-East on green and so on.
signal one_second_counter: STD_LOGIC_vector(25 downto 0):="00000000000000000000000000";
signal one_second_enable: std_logic;
signal state: state_type:=NRWG;
signal count : std_logic_vector (3 downto 0);
constant sec8 : std_logic_vector ( 3 downto 0) := "1000";
constant sec3 : std_logic_vector (3 downto 0 ) := "0011";
constant sec11: std_logic_vector (3 downto 0 ) := "1011";
--edge detector signals
signal emergencya, emergencyb, emergencyc: std_logic;
----------
begin
controller: process (Clck,reset,emergencyc)
begin
if emergencyc='1' then
if state=NRWG or state=NRWY then ----if NS is on red then switch it to yellow.
state<=NYWR;
count<=x"0";
else
if state=NGWR or state=NYWR then ----if WE is on red then switch it to yellow.
state<=NRWY;
count<=x"0";
end if;
end if;
elsif reset ='1' then
state<=NRWG;
count<=X"0";
else
if rising_edge(clck) then
if one_second_enable='1' then
case state is
when NRWG =>
if count < sec8 then
state <= NRWG;
count <= count + 1;
else
state <= NRWY;
count <= X"0";
end if;
when NRWY =>
if count < sec3 then
state <= NRWY;
count <= count + 1;
else
state <= NGWR;
count <= X"0";
end if;
when NGWR =>
if count < sec11 then
state <= NGWR;
count <= count + 1;
else
state <= NYWR;
count <= X"0";
end if;
when NYWR =>
if count < sec3 then
state <= NYWR;
count <= count + 1;
else
state <=NRWG;
count <= X"0";
end if;
when others =>
state <= NRWG;
end case;
end if;
end if;
end if;
end process;
-----------decode state
OUTPUT_DECODE: process (state)
begin
case state is
when NRWG => Trafficlights <= "100001";
when NRWY => Trafficlights <= "100010";
when NGWR => Trafficlights <= "001100";
when NYWR => Trafficlights <= "010100";
when others => Trafficlights <= "100001";
end case;
end process;
--------------------------------
--------------Slow_Clock-------------
slow_clock:process(clck) begin
if(rising_edge(clck)) then
if(one_second_counter="10111110101111000010000000") then
one_second_counter <="00000000000000000000000000";
else
one_second_counter <= one_second_counter +1;
end if;
end if;
end process;
one_second_enable <= '1' when one_second_counter="10111110101111000010000000" else '0';
---------------------------------------------------
-----------------for debouncing---------------
debounce_emergency:process(clck)
begin
if(rising_edge(Clck)) then
case (state1) is
when idle =>
if(emergency = BTN_ACTIVE) then
state1 <= wait_time;
else
state1 <= idle;
end if;
emergency_debounced <= '0';
when wait_time =>
if(count1 = COUNT_MAX) then
count1 <= 0;
if(emergency = BTN_ACTIVE) then
emergency_debounced <= '1';
end if;
state1 <= idle;
else
count1 <= count1 + 1;
end if;
end case;
end if;
end process;
------------------------------------------------------------
---------edge_detector--------
edge_detection:process (clck)
begin
if(rising_edge(clck)) then
emergencya <= emergency_debounced;
emergencyb <= emergencya;
end if;
end process ;
emergencyc <= not emergencyb and emergencya;
---------------------------------
end Behavioral;
Any ideas as to why the emergency function doesn't work the way it supposed to?
Your debounce_emergency:process is wrong in many ways. I suggest you simulate your design to see it. What happens if the emergency button is pressed for 40 clock cycles?
Moreover in the controller: process the if emergencyc='1' ... part must be inside the if rising_edge(clck) otherwise will trigger multiple changes in the state signal.

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 uart which send 16 chars string

I have to do UART with vhdl on the Xilinx which will send 16 chars string. I wrote such code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.ALL;
entity uartByJackob is
Port ( CLK, A, B, C : in STD_LOGIC;
RESET : in STD_LOGIC;
TxD, TxDOSC : out STD_LOGIC);
end uartByJackob;
architecture Behavioral of uartByJackob is
signal K: std_logic_vector(14 downto 0);
signal Q: std_logic_vector(3 downto 0);
signal CLK_Txd: std_logic;
signal ENABLE: std_logic;
signal QTxD: std_logic_vector(9 downto 0);
signal DATA : STD_LOGIC_VECTOR(7 downto 0);
-- freq of clock
begin
process(CLK, RESET)
begin
if rising_edge(CLK) then
if(A = '1' and K < 10416) then
K <= K + 1;
CLK_Txd <= K(13);
elsif(B = '1' and K < 5208) then
K <= K + 1;
CLK_Txd <= K(12);
elsif(C = '1' and K < 20832) then
K <= K + 1;
CLK_Txd <= K(14);
else
K <= (others => '0');
end if;
end if;
end process;
--counter
process(CLK_Txd, RESET, ENABLE)
begin
if(RESET = '1' and ENABLE = '0') then
Q <= "0000";
elsif (rising_edge(CLK_Txd)) then
Q <= Q + 1;
end if;
end process;
--comparator
ENABLE <= '1' when (Q > 4) else '0';
--transcoder
process(Q, CLK_Txd)
begin
if (rising_edge(CLK_Txd)) then
case Q is
when "0001" => DATA <= x"40";
when "0010" => DATA <= x"41";
when "0011" => DATA <= x"42";
when "0100" => DATA <= x"43";
when "0101" => DATA <= x"44";
when "0110" => DATA <= x"45";
when "0111" => DATA <= x"46";
when "1000" => DATA <= x"47";
when "1001" => DATA <= x"48";
when "1010" => DATA <= x"49";
when "1011" => DATA <= x"50";
when "1100" => DATA <= x"51";
when "1101" => DATA <= x"52";
when "1110" => DATA <= x"53";
when "1111" => DATA <= x"54";
when others => DATA <= x"55";
end case;
end if;
end process;
--uart
process(CLK_Txd, ENABLE, DATA)
begin
if(ENABLE = '0') then
QTxD <= DATA & "01";
elsif rising_edge(CLK_Txd) then
QTxD <= '1'&QTxD(9 downto 1);
end if;
end process;
TxD <= QTxD(0);
TxDOSC <= QTxD(0);
end Behavioral;
It's send data completely not connected with that what i have in transcoder and realy dont know why. Do you have any ideas what is wrong with my code, or do you have any diffrent examples of it how to send your own 16 chars with uart? I suppose that something is wrong with my counter or comparator.
--EDIT
Thans for your effort, i can't try your code at the Xilinx right now couse I am workin on it at my university. I see that you made a lot of changes in my code. Of course first i try to do it like you show and i hope this will be acceptable, but I propably have to do it with transcoder according to this picture.
From last time i made such changes i my code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.ALL;
entity uartByJackob is
Port ( CLK, A, B, C : in STD_LOGIC;
RESET : in STD_LOGIC;
TxD, TxDOSC : out STD_LOGIC);
end uartByJackob;
architecture Behavioral of uartByJackob is
signal K: std_logic_vector(14 downto 0);
signal Q: std_logic_vector(7 downto 0);
signal CLK_Txd: std_logic;
signal ENABLE: std_logic;
signal QTxD: std_logic_vector(7 downto 0);
signal DATA : STD_LOGIC_VECTOR(7 downto 0);
signal QPrim: std_logic_vector(3 downto 0);
begin
process(CLK, RESET)
begin
CLK_Txd <= CLK;
end process;
process(CLK_Txd, RESET, ENABLE)
begin
if(ENABLE = '0') then
Q <= "00000000";
elsif (rising_edge(CLK_Txd)) then
Q <= Q + 1;
end if;
end process;
ENABLE <= '1' when (Q <= 255) else '0';
process(Q(7 downto 4))
begin
case Q(7 downto 4) is
when "0000" => DATA <= x"40";
when "0001" => DATA <= x"41";
when "0010" => DATA <= x"42";
when "0011" => DATA <= x"43";
when "0100" => DATA <= x"44";
when "0101" => DATA <= x"45";
when "0110" => DATA <= x"46";
when "0111" => DATA <= x"47";
when "1000" => DATA <= x"48";
when "1001" => DATA <= x"49";
when "1010" => DATA <= x"50";
when "1011" => DATA <= x"51";
when "1100" => DATA <= x"52";
when "1101" => DATA <= x"53";
when "1110" => DATA <= x"54";
when "1111" => DATA <= x"55";
when others => DATA <= x"56";
end case;
end process;
process(CLK_Txd, ENABLE, DATA)
begin
if(ENABLE = '1') then
QTxD <= DATA;
elsif rising_edge(CLK_Txd) then
QTxD <= '1'&QTxD(7 downto 1);
end if;
end process;
TxD <= QTxD(0);
TxDOSC <= QTxD(0);
end Behavioral;
According to that i send MSB to transcoder and LSB to comparator but my program all the time still send x"40" to DATA and it is propably connected with this counter which you were talking about.
There is my simulation efect. I becoming upset with that couse i don't have enough skills in vhdl to do it by my self. I hope that you will help me to do rebuild my project. On simulation it looks good i dont know how it looks on Xilinx.
Can you show me a piece of code? - Stefan
The entire purpose to providing the link to Adrian Adamcyzk's code (Altera FPGA hardware (has an issue) vs ModelSim simulation (ok) - self implemented UART) was to provide an example with a bit (baud) counter and flip flop used to control sending the message once.
Here's Jackob's modified:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity uartbyjackob is
port (
clk, a, b, c: in std_logic;
reset: in std_logic;
txd, txdosc: out std_logic
);
end entity uartbyjackob;
architecture foo of uartbyjackob is
-- signal k: unsigned(14 downto 0); -- FOR simulation
-- note if k were used in simulation it would require initialization
signal q: unsigned (3 downto 0); -- WAS std_logic_vector
signal clk_txd: std_logic;
signal enable: std_logic;
signal qtxd: std_logic_vector(9 downto 0);
-- signal data: std_logic_vector(7 downto 0);
-- added:
signal bdcnt: unsigned (3 downto 0);
signal ldqtxd: std_logic;
signal davl: std_logic;
type data_lut is array (0 to 15) of std_logic_vector (7 downto 0);
constant data: data_lut := (
x"40", x"41", x"42", x"43", x"44", x"45", x"46", x"47",
x"48", x"49", x"50", X"51", x"52", X"53", x"54", x"55"
);
signal datalut: std_logic_vector (7 downto 0); -- FOR SIMULATION visibility
begin
-- -- freq of clock -- NOTE k never in known binary state for simulation
-- process (clk, reset)
-- begin
-- if rising_edge(clk) then
-- if a = '1' and k < 10416 then
-- k <= k + 1;
-- clk_txd <= k(13);
-- elsif b = '1' and k < 5208 then
-- k <= k + 1;
-- clk_txd <= k(12);
-- elsif c = '1' and k < 20832 then
-- k <= k + 1;
-- clk_txd <= k(14);
-- else
-- k <= (others => '0');
-- end if;
-- end if;
-- end process;
clk_txd <= clk; -- SHORTENS SIMULATION
DAVL_FF: -- DATA_AVAILABLE to send
process (clk_txd, reset)
begin
if reset = '1' then
davl <= '0';
elsif rising_edge (clk_txd) then
if q = 15 and bdcnt = 9 then -- a JK FF equivalent
davl <= '0';
elsif q = 0 then
davl <= '1'; -- one clock holderover from reset
-- else
-- davl <= davl;
end if;
end if;
end process;
-- process(clk_txd, reset, enable)
-- begin
-- if reset = '1' and enable = '0' then
-- q <= "0000";
-- elsif rising_edge(clk_txd) then
-- q <= q + 1;
-- end if;
-- end process;
QCNT:
process (clk_txd, reset)
begin
if reset = '1' then
q <= (others => '0');
elsif rising_edge (clk_txd) then
if enable = '1' then
q <= q + 1;
end if;
end if;
end process;
BAUD_COUNTER:
process (clk_txd, reset)
begin
if reset = '1' then
bdcnt <= (others => '0');
elsif rising_edge (clk_txd) then
if davl = '0' or bdcnt = 9 then
bdcnt <= (others => '0');
else
bdcnt <= bdcnt + 1;
end if;
end if;
end process;
-- comparator
-- enable <= '1' when (q > 4) else '0';
enable <= '1' when bdcnt = 9 and davl = '1' and q /= 15 else
'0';
-- q latches at 15;
ldqtxd <= '1' when bdcnt = 9 and davl = '1' else
'0';
datalut <= data(to_integer(q)); -- FOR SIMULATION VISIBILITIY
--transcoder
-- process(q, clk_txd)
-- begin
-- if rising_edge(clk_txd) then
-- case q is
-- when "0001" => data <= x"40";
-- when "0010" => data <= x"41";
-- when "0011" => data <= x"42";
-- when "0100" => data <= x"43";
-- when "0101" => data <= x"44";
-- when "0110" => data <= x"45";
-- when "0111" => data <= x"46";
-- when "1000" => data <= x"47";
-- when "1001" => data <= x"48";
-- when "1010" => data <= x"49";
-- when "1011" => data <= x"50";
-- when "1100" => data <= x"51";
-- when "1101" => data <= x"52";
-- when "1110" => data <= x"53";
-- when "1111" => data <= x"54";
-- when others => data <= x"55";
-- end case;
-- end if;
-- end process;
-- uart
-- process (clk_txd, enable, data)
-- begin
-- if enable = '0' then
-- qtxd <= data & "01";
-- elsif rising_edge(clk_txd) then
-- qtxd <= '1' & qtxd(9 downto 1);
-- end if;
-- end process;
TX_SHIFT_REG:
process (clk_txd, reset) -- shift regiseter Tx UART
begin
if reset = '1' then
qtxd <= (others => '1'); -- output mark by default
elsif rising_edge (clk_txd) then
if ldqtxd = '1' then
qtxd <= '1' & data(to_integer(q)) & '0';
-- STOP & Data(q) 7 downto 0 & START , a MUX and expansion
else
qtxd <= '1' & qtxd(9 downto 1); -- shift out;
end if;
end if;
end process;
txd <= qtxd(0);
txdosc <= qtxd(0);
end architecture foo;
library ieee;
use ieee.std_logic_1164.all;
entity uartbyjackob_tb is
end entity;
architecture foo of uartbyjackob_tb is
signal clk: std_logic := '0';
signal reset: std_logic := '0';
signal txd: std_logic;
begin
DUT:
entity work.uartbyjackob
port map (
clk => clk, -- clk_txd driven by clk
a => 'X',
b => 'X',
c => 'X', -- a, b, c aren't used
reset => reset,
txd => txd,
txdosc => open
);
CLOCK:
process
begin
wait for 52.35 us;
clk <= not clk;
if now > 20000 us then
wait;
end if;
end process;
STIMULUS:
process
begin
wait for 104.7 us;
reset <= '1';
wait for 104.7 us;
reset <= '0';
wait;
end process;
end architecture;
The model has been modified for faster simulation, ignoring the baud rate clock generator.
There's an added flip flop (davl) for enabling the UART to run. There's an added baud (bit) counter bdcnt.
I changed the order of the start, stop and data values loaded into QTxD so the start bit came out first, followed by 8 data bits and the stop bit.
You can read off TxD from left to right start bit, data(q)(0) ... data(q(7), stop bit. The enable or ldqtxd will occur at the same time as a stop bit.
There's only one observable draw back to this implementation, if you reset while a value in the shift register hasn't finished loading you'll cause a framing error for the receiver. Don't reset it for 10 baud times after davl goes false.
The simulation is shown with a 9600 baud clk_txd, the characters go out back to back.
It has fewer flip flops than the original (disregarding k). There is no data register separate from QTxD ( - 8 FFs) plus bdcnt (+ 4) plus davl (+ 1). There are two comparisons (optimized to two) bdcnt = 9, q =, /= 9. Those could be expressed separately so it doesn't require optimization during synthesis.
I changed the look up table style, a matter of personal preference also the excuse for changing counters to type unsigned and using only package numeric_std for arithmetic.
The little testbench likewise doesn't expect the k counter to generate the baud clock.
Running the testbench gives:
Where there's an added signal datalut to show the value being shifted out after ldqtxd.
After your change making the q counter (7 downto 0)
We still see from your waveform that it doesn't work.
This is due to the enable and the shift register.
If you use a single counter with the upper four bits indexing the output character your character is transmitted in 10 out of the 16 clk_txd times indexed by the lower four bits of the counter. The remaining clock times TxD should be '1' (idle line marks in RS-232 parlance).
The order for data to be transmitted will be a space (the start bit), data(0) through data(7) and a mark (the stop bit). (Shown left to right on TxD).
For simulation the k counter is not used. I included it commented out below.
I made several changes for proper simulation. These include synchronously loading the shift register containing QTxD, synchronously clearing the rightmost bit of QTxD to provide a full width and moving enable to occur once every sixteen clocks (clk_txd). The enable is preceded by a new clear for the start bit and both been offset to prevent it from occurring during reset which has the effect of causing a framing error on the first character for any receiver.
Simulation is done with the same testbench I provide above.
The changes to your new code are shown by comments:
architecture behavioral of uartbyjackob is
-- signal k: std_logic_vector(14 downto 0);
signal q: unsigned (7 downto 0); -- std_logic_vector(7 downto 0);
signal clk_txd: std_logic;
signal enable: std_logic;
signal qtxd: std_logic_vector(7 downto 0);
-- using an 8 bit shift register requires a method of outputting a
-- synchronous start bit (the width is important for receive framing)
-- and synchronous stop bit
signal data: std_logic_vector(7 downto 0);
signal qprim: std_logic_vector(3 downto 0);
signal clear: std_logic; -- synchronous clear for start bit
begin
-- let's keep this here for when you put it the FPGA
-- -- freq of clock -- NOTE k never in known binary state for simulation
-- process (clk, reset)
-- begin
-- if rising_edge(clk then
-- if a = '1' and k < 10416 then
-- k <= k + 1;
-- clk_txd <= k(13);
-- elsif b = '1' and k < 5208 then
-- k <= k + 1;
-- clk_txd <= k(12);
-- elsif c = '1' and k < 20832 then
-- k <= k + 1;
-- clk_txd <= k(14);
-- else
-- k <= (others => '0');
-- end if;
-- end if;
-- end process;
process (clk) -- , reset)
begin
clk_txd <= clk; -- if simply a concurrent assignment statement this
end process; -- would look similar to the elaborated equivalent
-- process. The difference, no sensitivity list and
-- an explict wait on clk statement at the end.
-- This process wants to be removed and replaced by
-- the above commented out process for synthesis
process (clk_txd, reset) -- , reset, enable) -- enable a reset?
begin
-- if enable = '0' then
if reset = '1' then -- puts q counter in known state for simulation
q <= "00000000";
elsif rising_edge(clk_txd) then
if q /= 255 then -- stop after sending once
q <= q + 1;
end if;
end if;
end process;
-- enable <= '1' when q <= 255 else '0'; -- this appears incorrect
enable <= '1' when q(3 downto 0) = "0010" else
'0';
clear <= '1' when q(3 downto 0) = "0001" else
'0';
-- USING ONE COUNTER requires some clocks output MARKS
-- (idle bits) each 16 clocks. It requires the load (enable)
-- occur once every 16 clocks.
-- q(3 downto 0) is selected for enable to prevent outputting spaces
-- TxD during reset (q is reset to all '0's). This would cause a receive
-- framing error.
process (q(7 downto 4))
begin
case q(7 downto 4) is
when "0000" => data <= x"40";
when "0001" => data <= x"41";
when "0010" => data <= x"42";
when "0011" => data <= x"43";
when "0100" => data <= x"44";
when "0101" => data <= x"45";
when "0110" => data <= x"46";
when "0111" => data <= x"47";
when "1000" => data <= x"48";
when "1001" => data <= x"49";
when "1010" => data <= x"50";
when "1011" => data <= x"51";
when "1100" => data <= x"52";
when "1101" => data <= x"53";
when "1110" => data <= x"54";
when "1111" => data <= x"55";
when others => data <= x"56";
end case;
end process;
process (clk_txd) -- , enable, data) -- synchronous enable and clear
begin
-- if enable = '1' then -- this appears incorrect
-- qtxd <= data;
if reset = '1' then
qtxd <= (others => '1'); -- outputs mark after reset
elsif rising_edge(clk_txd) then
if clear = '1' then -- synchronous clear for start bit
qtxd(0) <= '0';
elsif enable = '1' then -- synchronous load
qtxd <= data;
else
qtxd <= '1' & qtxd(7 downto 1); -- shift right
end if;
end if;
end process;
-- the synchronous load prevents the first start bit from being stretched
-- q(3 downto 0) the following in hex notation
-- q(3 downto 0) = 2 is the start bit
-- = 3 is data(0)
-- ...
-- = A is data(7)
-- = B is the stop bit
-- = C - 1 are mark (idle) bits (q(3 downto 0) rolls over)
-- = 1 enable occurs loading qtxd
--
-- The offset is caused by synchronous load (1 clk_txd) and the load point
-- (q(3 downto 0) = 1 in enable term).
--
-- The load point wants to occur in the first 6 counts of q(3 downto 0) to
-- insure a trailing mark when q is stopped.
--
-- q(3 downto 0) = 1 is selected for enable to prevent spurious spaces
-- during reset from causing a receive framing error.
txd <= qtxd(0);
txdosc <= qtxd(0);
end architecture behavioral;
The comment table:
-- the synchronous load prevents the first start bit from being stretched
-- q(3 downto 0) the following in hex notation
-- q(3 downto 0) = 2 is the start bit
-- = 3 is data(0)
-- ...
-- = A is data(7)
-- = B is the stop bit
-- = C - 1 are mark (idle) bits (q(3 downto 0) rolls over)
-- = 1 enable occurs loading qtxd
--
-- The offset is caused by synchronous load (1 clk_txd) and the load point
-- (q(3 downto 0) = 1 in enable term).
--
-- The load point wants to occur in the first 6 counts of q(3 downto 0) to
-- insure a trailing mark when q is stopped.
--
-- q(3 downto 0) = 1 is selected for enable to prevent spurious spaces
-- during reset from causing a receive framing error.
tells you where to find bits of the data(q(7 downto 0)) selected character. In the following waveform q is shown as hex to match:
You'll find with the fixes the first character transmitted is 0x40, the second 0x41,...

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