VHDL change CLK speed - vhdl

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.

Related

Unable to assign counter signal to output (FSM)

I'm working on an FSM for a quadrature encoder counter, to be used on the Arty A7 35 --- this is my first VHDL project, so I apologize if I am missing something very basic. I have an internal count signal that I decrement or increment in the FSM, but when I try to assign that signal via COUNT_OUT <= count, COUNT_OUT stays at zero, even though I have been able to observe the state changing. I do this assignment at the very end of the FSM process.
simulation outputs
Further, I am not able to observe "state", "next state", or "count" in simulation --- I would appreciate help on this as well as would be very useful. These signals do not show up in the "objects" window beside the scope either
My entity declaration is as follows:
entity GPIO_demo is
Port ( BTN : in STD_LOGIC;
z : in STD_LOGIC;
A : in STD_LOGIC;
B : in STD_LOGIC;
LED : out STD_LOGIC;
CLK : in STD_LOGIC;
UART_TXD : out STD_LOGIC;
COUNT_OUT : out unsigned(11 downto 0)
);
end GPIO_demo;
I define these relevant signals in architecture:
type state_type is (S00, S01, S10, S11);
signal state, next_state: state_type;
signal count: unsigned(11 downto 0) := (others=>'0');
My FSM is as follows:
SYNC_PROC: process(CLK)
begin
if rising_edge(CLK) then
if ( z='1' ) then
state <= S00;
count <= "000000000000";
else
state <= next_state;
end if;
end if;
end process;
NEXT_STATE_DECODE: process(state, A, B)
begin
case state is
when S00 =>
if(A = '0' and B = '1') then
count <= "000000000000";
next_state <= S01;
elsif(A = '1' and B = '0') then
count <= "000000000000";
next_state <= S10;
end if;
when S01 =>
if(A = '1' and B = '1') then
count <= "100000000000";
next_state <= S11;
elsif(A = '0' and B = '0') then
count <= "100000000000";
next_state <= S00;
end if;
when S11 =>
if(A = '1' and B = '0') then
count <= count - 1;
next_state <= S10;
elsif(A = '0' and B = '1') then
count <= count + 1;
next_state <= S01;
end if;
when S10 =>
if(A = '0' and B = '0') then
count <= count - 1;
next_state <= S00;
elsif(A = '1' and B = '1') then
count <= count + 1;
next_state <= S11;
end if;
end case;
COUNT_OUT <= count;
end process;
Any idea on why this output does not update?

How to setup adv7513?

I'm setting up adv7513 on altera GX starter kit. Data that I've read from registers after setup is different from what I've sent.
I've tried to divide writes in to the single registers instead of one long transaction, and change the order of writes and reads, but I always read 0x03 from 0x98 and 0x00 from the rest of the registers.
I've used this i2c controller: https://www.digikey.com/eewiki/pages/viewpage.action?pageId=10125324
and I've made state machine in vhdl to control it, and write data stored in rom
if rising_edge(clk) then
case state is
when idle =>
if (beg='1') then
state <= start;
else
state <= idle;
end if;
when start =>
rom_addr <= count;
state <= lut_addr_i2c;
when lut_addr_i2c =>
ena <= '1';
rw <= '0';
addr <= "0111001";
data_wr <= lut_data(15 downto 8);
state <= lut_data_i2c;
when lut_data_i2c =>
if (busy='1' and busy_prev='0') then
data_wr <= lut_data(7 downto 0);
state <= cleanup;
count <= count+1;
end if;
when cleanup =>
if (busy='1' and busy_prev='0') then
state <= next_lut;
end if;
when next_lut =>
if (count = 31) then
state <= rd;
ena <= '0';
else
state <= start;
end if;
when rd =>
ready <= '1';
count <= 0;
if (rd_delay = 10000) then
state <= start_rd;
else
rd_delay <= rd_delay+1;
state <= rd;
end if;
when start_rd =>
rom_addr <= count;
if (next_rd = 20000) then
state <= rd_lut_addr;
next_rd <= 0;
else
next_rd <= next_rd+1;
state <= start_rd;
end if;
when rd_lut_addr =>
ena <= '1';
rw <= '0';
addr <= "0111001";
data_wr <= lut_data(15 downto 8);
state <= rd_lut;
when rd_lut =>
if (busy='1' and busy_prev='0') then
rw <= '1';
count <= count+1;
state <= rd_cleanup;
end if;
when rd_cleanup =>
if (busy='1' and busy_prev='0') then
state <= rd_next_lut;
end if;
when rd_next_lut =>
if (count = 31) then
state <= fin;
ena <= '0';
else
state <= start_rd;
ena <= '0';
end if;
when fin =>
state <= fin;
end case;
end if;
signal tap, what I write
signal tap, what I read
I think your problem is that you simply overrun the i2c slave. You should wait for not busy in your cleanup state latest after you've provided your second data byte.
Your code does not appear to wait for not busy at all?

Can't assign value to integer signal in 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:

How to set a value at moduleEN - VHDL

I've this code:
library IEEE;
use IEEE.std_logic_1164.all;
entity Controller is
port (
CLK : in std_logic;
OutENABLE : out std_logic_vector (2 downto 0);
ModuleRESET : in std_logic;
ModuleENABLE : in std_logic
);
end Controller;
architecture Controller_archi of Controller is
signal Counter : integer range 0 to 4200 := 0;
begin
process (CLK, ModuleRESET)
begin
if ModuleRESET = '0' then
OutENABLE <= (others => '0');
Counter <= 0;
elsif rising_edge(CLK) then
if ModuleENABLE = '1' then
Counter <= Counter + 1;
case Counter is
when 0 =>
OutENABLE <= "001";
when 450 =>
OutENABLE <= "010";
when 900 =>
OutENABLE <= "100";
when 1350 =>
OutENABLE <= "001";
Counter <= 0;
when others =>
end case;
else
OutENABLE <= "000";
end if;
end if;
end process;
end Controller_archi;
But it's not working like I need.
What I need:
When ModuleENABLE goes '1' instantly OutENABLE goes "001" and not at first rising_edge(CLK) (Now, in this code, if ModuleENABLE goes '1' OutENABLE doesn't change from "000" to "001", it change to "001" after first rising_edge(CLK))
Counter go up when rising_edge(CLK) and OutENABLE it's updated every CLK event. (Now, in this code, counter go up when rising_edge(CLK) but OutENABLE it's updated when rising_edge(CLK) and not when CLK goes up and goes down)
So I've modified code to do that:
library IEEE;
use IEEE.std_logic_1164.all;
entity Controller is
port (
CLK : in std_logic;
OutENABLE : out std_logic_vector (2 downto 0);
ModuleRESET : in std_logic;
ModuleENABLE : in std_logic
);
end Controller;
architecture Controller_archi of Controller is
signal Counter : integer range 0 to 4200 := 0;
begin
process (CLK, ModuleENABLE, ModuleRESET)
begin
if ModuleRESET = '0' then
OutENABLE <= (others => '0');
Counter <= 0;
elsif ModuleENABLE = '1' then
if rising_edge(CLK) then
Counter <= Counter + 1;
end if;
case Counter is
when 0 =>
OutENABLE <= "001";
when 450 =>
OutENABLE <= "010";
when 900 =>
OutENABLE <= "100";
when 1350 =>
OutENABLE <= "001";
Counter <= 0;
when others =>
end case;
else
Counter <= 0;
OutENABLE <= "000";
end if;
end process;
end Controller_archi;
Now code work like I need in ModelSim, but when I synthesize it or compile it and simulate again it doesn't work.
My question is:
What it's wrong with second code and how I can fix it?
If I can't fix second code how I can modify first code to work like I need?
What it's wrong with second code and how I can fix it?
Your synthesis tool is fussy about how the clock and reset lines are connected. You have to use a structure like:
if ModuleRESET = '0' then
...
elsif rising_edge(CLK) then
or the synthesis tool cannot recognise the clock and reset lines.
If I can't fix second code how I can modify first code to work like I need?
You need to move "OutENABLE" outside of the first process, and into a process of its own. From what you've said, OutENABLE should not be a register - it should be a combinatorial function of Counter, ModuleRESET and ModuleENABLE. Try this.
process (CLK, ModuleRESET)
begin
if ModuleRESET = '0' then
Counter <= 0;
elsif rising_edge(CLK) then
if ModuleENABLE = '1' then
Counter <= Counter + 1;
case Counter is
when 1350 =>
Counter <= 0;
when others =>
null;
end case;
end if;
end if;
end process;
process (Counter, ModuleRESET, ModuleEnable)
begin
OutENABLE <= "000";
if ModuleRESET = '1' and ModuleENABLE = '1' then
case Counter is
when 0 .. 449 =>
OutENABLE <= "001";
when 450 .. 899 =>
OutENABLE <= "010";
when 900 .. 1349 =>
OutENABLE <= "100";
when others =>
OutENABLE <= "001";
end case;
end if;
end process;

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.

Resources