My code is intended to be purely combinational. Only one element gives some synchronysm to simulation. it is a 4*4 led matrix where only 3*3 (starting on the top right) is valid. like:
-- LED matrix
-- rows\cols | A | B | C | D |
---------------------------------
-- 1 | 3 | 2 | 1 | 0 |
-- 2 | 7 | 6 | 5 | 4 |
-- 3 | 11 | 10| 9 | 8 |
-- 4 | 15 | 14| 13| 12| <- row not used
-- ^
-- |
-- column not used
---------------------------------
the following code compiles and simulates on an FPGA but not with the desired behaviour. The wanted behabiour is to iluminate a red led if one input is detected, 2 if 2, and if 3 are in a row in the matrix at the same time instead of 3 red led it should show 3 blue ones. no memory involved. The observed behaviour is explained as coments within the code.
entity mt is
PORT (
cD, cC, cB, cA : in std_logic; -- comparators for each column. cA is not necessary / not used.
row : inout std_logic_vector (3 downto 0) := (others => '0'); -- detection of each row.
led_R, led_G, led_B : out std_logic_vector (15 downto 0) := (others => '1') -- '1' indicates they are OFF. 12 to 15 will not be used (as well as 3, 7, 11 positions)
);
end mt;
I have 4 concurrent processes which depend on the signals explained:
architecture arc1 of mt is
signal led_R_in : std_logic_vector (15 downto 0) := (others => '1');
signal led_G_in : std_logic_vector (15 downto 0) := (others => '1'); -- don't think they are necessary
signal led_B_in : std_logic_vector (15 downto 0) := (others => '1'); -- don't think they are necessary
signal counter : std_logic_vector (1 downto 0) := "00";
begin
PROCESS (row, cD, cC, cB, cA) -- execute if any of these change
BEGIN
CASE row IS
WHEN "1000" => -- row 1 --
-- (LEDs are active at logic level 0)
CASE cD IS
WHEN '1' => led_R_in(0) <= '0'; led_G_in(0) <= '1'; led_B_in(0) <= '1';
WHEN OTHERS => led_R_in(0) <= '1'; led_G_in(0) <= '1'; led_B_in(0) <= '1';
END CASE;
CASE cC IS
WHEN '1' => led_R_in(1) <= '0'; led_G_in(1) <= '1'; led_B_in(1) <= '1';
WHEN OTHERS => led_R_in(1) <= '1'; led_G_in(1) <= '1'; led_B_in(1) <= '1';
END CASE;
CASE cB IS
WHEN '1' => led_R_in(2) <= '0'; led_G_in(2) <= '1'; led_B_in(2) <= '1';
WHEN OTHERS => led_R_in(2) <= '1'; led_G_in(2) <= '1'; led_B_in(2) <= '1';
END CASE;
CASE cA IS -- not necessary
WHEN '1' => led_R_in(3) <= '0'; led_G_in(3) <= '1'; led_B_in(3) <= '1';
WHEN OTHERS => led_R_in(3) <= '1'; led_G_in(3) <= '1'; led_B_in(3) <= '1';
END CASE;
WHEN "0100" => -- row 2 --
-- (LEDs are active at logic level 0)
CASE cD IS
WHEN '1' => led_R_in(4) <= '0'; led_G_in(4) <= '1'; led_B_in(4) <= '1';
WHEN OTHERS => led_R_in(4) <= '1'; led_G_in(4) <= '1'; led_B_in(4) <= '1';
END CASE;
CASE cC IS
WHEN '1' => led_R_in(5) <= '0'; led_G_in(5) <= '1'; led_B_in(5) <= '1';
WHEN OTHERS => led_R_in(5) <= '1'; led_G_in(5) <= '1'; led_B_in(5) <= '1';
END CASE;
CASE cB IS
WHEN '1' => led_R_in(6) <= '0'; led_G_in(6) <= '1'; led_B_in(6) <= '1';
WHEN OTHERS => led_R_in(6) <= '1'; led_G_in(6) <= '1'; led_B_in(6) <= '1';
END CASE;
CASE cA IS -- not necessary
WHEN '1' => led_R_in(7) <= '0'; led_G_in(7) <= '1'; led_B_in(7) <= '1';
WHEN OTHERS => led_R_in(7) <= '1'; led_G_in(7) <= '1'; led_B_in(7) <= '1';
END CASE;
WHEN "0010" => -- row 3 --
-- (LEDs are active at logic level 0)
CASE cD IS
WHEN '1' => led_R_in(8) <= '0'; led_G_in(8) <= '1'; led_B_in(8) <= '1';
WHEN OTHERS => led_R_in(8) <= '1'; led_G_in(8) <= '1'; led_B_in(8) <= '1';
END CASE;
CASE cC IS
WHEN '1' => led_R_in(9) <= '0'; led_G_in(9) <= '1'; led_B_in(9) <= '1';
WHEN OTHERS => led_R_in(9) <= '1'; led_G_in(9) <= '1'; led_B_in(9) <= '1';
END CASE;
CASE cB IS
WHEN '1' => led_R_in(10) <= '0'; led_G_in(10) <= '1'; led_B_in(10) <= '1';
WHEN OTHERS => led_R_in(10) <= '1'; led_G_in(10) <= '1'; led_B_in(10) <= '1';
END CASE;
CASE cA IS -- not necessary
WHEN '1' => led_R_in(11) <= '0'; led_G_in(11) <= '1'; led_B_in(11) <= '1';
WHEN OTHERS => led_R_in(11) <= '1'; led_G_in(11) <= '1'; led_B_in(11) <= '1';
END CASE;
WHEN OTHERS => Null; -- not necessary, although for avoiding latches creation I will have to assign them.
END CASE;
END PROCESS;
PROCESS (led_R_in) -- executes when led_R_in changes
BEGIN
-- leds are ON at '0' value
-- the problem is that, when initialising, the first row of leds will be blue, which means that
-- led_R_in 0, 1, 2 are 0, but they should be 1 as stated in their default values
-- the second and third row initialises correctly to green values, although the response to changes in the inputs are not only affecting them but also their neighbours, which I think it could be a problem of the FPGA pin assignment.
if (led_R_in(0)='0' AND ((led_R_in(1)='0' AND led_R_in(2)='0') OR (led_R_in(4)='0' AND led_R_in(8)='0') OR (led_R_in(5)='0' AND led_R_in(10)='0'))) then
led_B(0) <= '0';
led_R(0) <= '1';
led_G(0) <= '1';
else
led_R(0) <= led_R_in(0);
led_G(0) <= '0';
led_B(0) <= '1';
end if;
if (led_R_in(1)='0' AND ((led_R_in(0)='0' AND led_R_in(2)='0') OR (led_R_in(5)='0' AND led_R_in(9)='0'))) then
led_B(1) <= '0';
led_R(1) <= '1';
led_G(1) <= '1';
else
led_R(1) <= led_R_in(1);
led_G(1) <= '0';
led_B(1) <= '1';
end if;
if (led_R_in(2)='0' AND ((led_R_in(0)='0' AND led_R_in(1)='0') OR (led_R_in(10)='0' AND led_R_in(6)='0') OR (led_R_in(5)='0' AND led_R_in(8)='0'))) then
led_B(2) <= '0';
led_R(2) <= '1';
led_G(2) <= '1';
else
led_R(2) <= led_R_in(2);
led_G(2) <= '0';
led_B(2) <= '1';
end if;
if (led_R_in(4)='0' AND ((led_R_in(0)='0' AND led_R_in(8)='0') OR (led_R_in(5)='0' AND led_R_in(6)='0'))) then
led_B(4) <= '0';
led_R(4) <= '1';
led_G(4) <= '1';
else
led_R(4) <= led_R_in(4);
led_G(4) <= '0';
led_B(4) <= '1';
end if;
if (led_R_in(5)='0' AND ((led_R_in(2)='0' AND led_R_in(8)='0') OR (led_R_in(1)='0' AND led_R_in(9)='0') OR (led_R_in(0)='0' AND led_R_in(10)='0') OR (led_R_in(6)='0' AND led_R_in(4)='0'))) then
led_B(5) <= '0';
led_R(5) <= '1';
led_G(5) <= '1';
else
led_R(5) <= led_R_in(5);
led_G(5) <= '0';
led_B(5) <= '1';
end if;
if (led_R_in(6)='0' AND ((led_R_in(2)='0' AND led_R_in(10)='0') OR (led_R_in(5)='0' AND led_R_in(4)='0'))) then
led_B(6) <= '0';
led_R(6) <= '1';
led_G(6) <= '1';
else
led_R(6) <= led_R_in(6);
led_G(6) <= '0';
led_B(6) <= '1';
end if;
if (led_R_in(8)='0' AND ((led_R_in(2)='0' AND led_R_in(5)='0') OR (led_R_in(4)='0' AND led_R_in(0)='0') OR (led_R_in(9)='0' AND led_R_in(10)='0'))) then
led_B(8) <= '0';
led_R(8) <= '1';
led_G(8) <= '1';
else
led_R(8) <= led_R_in(8);
led_G(8) <= '0';
led_B(8) <= '1';
end if;
if (led_R_in(9)='0' AND ((led_R_in(1)='0' AND led_R_in(5)='0') OR (led_R_in(10)='0' AND led_R_in(8)='0'))) then
led_B(9) <= '0';
led_R(9) <= '1';
led_G(9) <= '1';
else
led_R(9) <= led_R_in(9);
led_G(9) <= '0';
led_B(9) <= '1';
end if;
if (led_R_in(10)='0' AND ((led_R_in(9)='0' AND led_R_in(8)='0') OR (led_R_in(5)='0' AND led_R_in(0)='0') OR (led_R_in(6)='0' AND led_R_in(2)='0'))) then
led_B(10) <= '0';
led_R(10) <= '1';
led_G(10) <= '1';
else
led_R(10) <= led_R_in(10);
led_G(10) <= '0';
led_B(10) <= '1';
end if;
END PROCESS;
PROCESS -- executes at the beginning (when is equal to "00") and changes its value every 10 ms
BEGIN
counter <= counter + "01"; -- there is an intended combinational loop here, so that it does this forever changing the row.
WAIT for 10 ms;
END PROCESS;
PROCESS (counter) -- executes at the beginning (when is equal to "00") and when counter changes (every 10 ms)
BEGIN
CASE counter IS
WHEN "00" => row <= "1000";
WHEN "01" => row <= "0100";
WHEN "10" => row <= "0010";
WHEN OTHERS => Null; -- for avoiding the automatic generation of latches due to non existing assignments. although it could also be row <= "0001"
END CASE;
END PROCESS;
END arc1;
why is it not working with the behaviour that I want?
Related
I'm looking to control an external display where the pins are connected to the ports JA and JB on the Nexys A7 100T, I've configured the state machine below according to the instructions in the datasheet but nothing is being displayed. Since this is the first time I'm controlling a display through VHDL, I suspect that either the display is not working or something is not being initialized in the correct manner.
--- Initialization and Data transfer of LCD display---
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;
entity LCD is
generic(
display_lines : std_logic := '0'; --Amount of displaylines: (0 = 1-line, 1 = 2-lines)
font_type : std_logic := '0'; -- Font type: (0 = 5x8 font, 1 = 5x11 font but only available for 1 line mode)
display_on : std_logic := '1'; -- Diplay ON/OFF: (0 = OFF, 1 = ON)
display_off : std_logic := '0';
cursor : std_logic := '0'; -- Cursor ON/OFF: (0 = OFF, 1 = ON)
blink : std_logic := '0'; -- Blink ON/OFF: (0 = OFF, 1 = ON)
I_D : std_logic := '1'; -- Increment/Decrement (0 = Decrement(move left), 1 = Increment(Move right))
shift : std_logic := '1'; -- Shift of display( 0 = Shift not perfomed, 1 = shift done according to I/D)
LCD_freq : integer := (100e6/270e3) - 1 -- Operating frequency of display
);
port(
CLK100MHZ, reset: in std_logic; -- 100MHZ clock and reset signal
LCD_RW: out std_logic; -- Read/write bit for LCD
LCD_RS: out std_logic; -- Register Select for LCD
LCD_E: out std_logic; -- Enable bit for the LCD
data: out std_logic_vector(7 downto 0) -- Data being sent to LCD including setup bits.
);
end entity;
architecture arch of LCD is
Type control is (RESET_1,RESET_2,RESET_3, FUNCTION_SET, DISPLAY_OFF1, DISPLAY_CLEAR, DISPLAY_ON1, ENTRY_MODE_SET, WRITE_T, RETURN_HOME,TOGGLE_E, HOLD);
signal freq_div :std_logic_vector(9 downto 0);
signal clk270 : std_logic; -- LCD clock
signal state, next_cmd: control;
begin
-- Clock for the LCD frequency
process(CLK100MHZ, reset)
begin
if reset = '1' then
freq_div <= (others => '0');
elsif rising_edge(CLK100MHZ) then
if freq_div = LCD_freq then
clk270 <= '1';
freq_div <= (others => '0');
else
clk270 <= '0';
freq_div <= freq_div + 1;
end if; -- freq_div
end if; -- reset
end process;
-- State diagram controlling display
process(CLK100MHZ, reset)
begin
if reset = '1' then
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00111000";
state <= TOGGLE_E;
next_cmd <= RESET_1;
elsif rising_edge(CLK100MHZ) then
if clk270 = '1' then
case state is
when RESET_1 =>
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00111000";
state <= TOGGLE_E;
next_cmd <= RESET_2;
when RESET_2 =>
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00111000";
state <= TOGGLE_E;
next_cmd <= RESET_3;
when RESET_3 =>
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00111000";
state <= TOGGLE_E;
next_cmd <= FUNCTION_SET;
--- Initilization steps done individually ---
when FUNCTION_SET => -- sets the function for the display
LCD_RS <= '0';
LCD_RW <= '0';
data <= "0011" & display_lines & font_type & "00";
LCD_E <= '1'; -- Enables function for display
state <= TOGGLE_E;
next_cmd <= DISPLAY_OFF1;
when DISPLAY_OFF1 => -- Turns the display off
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00001" & display_off & cursor & blink;
state <= TOGGLE_E;
next_cmd <= DISPLAY_CLEAR;
when DISPLAY_CLEAR => -- Clears the display
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00000001";
state <= TOGGLE_E;
next_cmd <= DISPLAY_ON1;
when DISPLAY_ON1 => -- Turns on the display
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00001" & display_on & cursor & blink;
state <= TOGGLE_E;
next_cmd <= ENTRY_MODE_SET;
when ENTRY_MODE_SET => -- Sets the increment and shift
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "000001" & I_D & shift;
state <= TOGGLE_E;
next_cmd <= WRITE_T;
when WRITE_T =>
LCD_RS <= '1';
LCD_RW <= '0';
LCD_E <= '1';
data <= "01000101"; --Letter T
state <= TOGGLE_E;
next_cmd <= RETURN_HOME;
when RETURN_HOME =>
LCD_E <= '1';
LCD_RS <= '0';
LCD_RW <= '0';
data <= "00000010";
state <= TOGGLE_E;
next_cmd <= WRITE_T;
-- Toggles a falling edge for Enable.
when TOGGLE_E =>
LCD_E <= '1';
state <= HOLD;
when HOLD =>
state <= next_cmd;
end case;
end if; -- clk270kHz
end if; -- reset
end process;
end arch;
The display is of the archetype ST7066U. Any feedback is appreciated.
I'm working on project which should convert data from analog to digital with approximation and I have error when i try compile code in Quartus II 9.1sp2 Web Edition which is shown in title with Case Statement in the code below:
architecture behavior of adc is
type state is (reset, state1, state2, state3, state4, state5, state6, state7, state8, state9, state10);
signal nx_state : state;
begin
process (in_clk, rst_n, start)
begin
if(rst_n'event and rst_n='0') then
B_hold <= "1111";
D_out <= "0000";
data_out <= "0000";
hold <= '1';
sample <= '0';
eoc <= '0';
if start = '1' then
nx_state <= state1;
else
nx_state <= reset;
end if;
elsif(in_clk'event and in_clk='1') then
case nx_state is
when state1 => nx_state <= state2;
B_hold <= "0000";
hold <= '0';
sample <= '1';
when state2 => nx_state <= state3;
B_hold <= "1111";
D_out <= "0000";
when state3 => nx_state <= state4;
B_hold(3) <= '0';
D_out(3) <= '1';
data_out(3) <= '1';
when state4 => nx_state <= state5;
if comp_in = '1' then
B_hold(3) <= '0';
D_out(3) <= '1';
data_out(3) <= '1';
else
B_hold(3) <= '1';
D_out(3) <= '0';
data_out(3) <= '0';
end if;
when state5 => nx_state <= state6;
B_hold(2) <= '0';
D_out(2) <= '1';
data_out(2) <= '1';
when state6 => nx_state <= state7;
if comp_in = '1' then
B_hold(2) <= '0';
D_out(2) <= '1';
data_out(2) <= '1';
else
B_hold(2) <= '1';
D_out(2) <= '0';
data_out(2) <= '0';
end if;
when state7 => nx_state <= state8;
B_hold(1) <= '0';
D_out(1) <= '1';
data_out(1) <= '1';
when state8 => nx_state <= state9;
if comp_in = '1' then
B_hold(1) <= '0';
D_out(1) <= '1';
data_out(1) <= '1';
else
B_hold(1) <= '1';
D_out(1) <= '0';
data_out(1) <= '0';
end if;
when state9 => nx_state <= state10;
B_hold(0) <= '0';
D_out(0) <= '1';
data_out(0) <= '1';
when state10 => nx_state <= reset;
if comp_in = '1' then
B_hold(0) <= '0';
D_out(0) <= '1';
data_out(0) <= '1';
else
B_hold(0) <= '1';
D_out(0) <= '0';
data_out(0) <= '0';
end if;
eoc <= '1';
end case;
end if;
end process;
end behavior;
I'm new newbie at vhdl and I don't know what exactly is wrong with the conditions shown above.
Your type includes a state named reset. You need a when for that state.
case nx_state is
when reset =>
Reset is level sensitive. So change
if(rst_n'event and rst_n='0') then
to
if(rst_n='0') then
It is also unusual to have a condition within the reset condition
if start = '1' then
nx_state <= state1;
else
nx_state <= reset;
end if;
Hence, you probably just want:
nx_state <= reset;
I'm trying to use a LCD project in my own project but I don't really
understand this project fully especially with the counters e.g count1 and count2
I can provide the datasheet if needed!
I hope I can get a clarification to this, I understand what is going on when counter has reached a certain number but what I do not understand is what is that number is representing!
I think something is worth mentioning is the clock used in the FPGA is 50MHz
the code is as fellow
library ieee;
use ieee.std_logic_1164.all;
entity display is
port( clk : in std_logic;
rst : in std_logic;
byte_ready : in std_logic;
RS : out std_logic;
RW : out std_logic;
E : out std_logic;
DB : out std_logic_vector(7 downto 0);
rxdata : in std_logic_vector(7 downto 0) );
end entity display;
architecture rtl of display is
signal cnt : integer range 0 to 1000000; -- init counter
signal cnt2 : integer range 0 to 50000000; -- counter that resets every time byte i recieved
begin
clk_gen : process(clk, cnt, rst)
begin
if (rst = '0') then
cnt <= 0;
cnt2 <= 0;
else
if rising_edge(clk) and cnt < 1000000 then
cnt <= cnt + 1;
elsif rising_edge(clk) and cnt = 1000000 then
if (byte_Ready = '1') then
cnt2 <= 0;
end if;
if (cnt2 < 5000000) then
cnt2 <= cnt2 + 1;
end if;
end if;
end if;
end process clk_gen;
p_main : process(clk, rst)
begin
if (rst = '1') then
if rising_edge(clk) then
case cnt is -- INIT
when 100000 =>
RS <= '0';
RW <= '0';
E <= '1';
DB <= "00111000"; -- function set --kan ändras till 00111011 western eurpean #2
when 140000 =>
E <= '0';
when 150000 =>
E <= '1';
DB <= "00001011"; -- display off
when 190000 =>
E <= '0';
when 200000 =>
E <= '1';
DB <= "00000001"; -- display clear
when 300000 =>
E <= '0';
when 350000 =>
E <= '1';
DB <= "00000110"; -- entry mode
when 390000 =>
E <= '0';
when 400000 =>
E <= '1';
DB <= "00000010"; -- home command
when 440000 =>
E <= '0';
when 450000 =>
E <= '1';
DB <= "00001111"; -- display on
when 490000 =>
E <= '0';
when 500000 =>
RS <= '0';
E <= '1';
DB <= "00010000"; -- cursor shift left
when 550000 =>
E <= '0';
when 600000 =>
RS <= '1';
E <= '1';
DB <= "10100000"; -- output space
when 650000 =>
E <= '0';
when 700000 =>
RS <= '0';
E <= '1';
DB <= "00010000"; -- cursor shift left
when 750000 =>
E <= '0';
when others => null;
end case;
if (rxdata = "01111111") then -- if input is backspace
case cnt2 is
when 300000 =>
RS <= '0';
E <= '1';
DB <= "00010000"; -- cursor shift left
when 350000 =>
E <= '0';
when 400000 =>
RS <= '1';
E <= '1';
DB <= "10100000"; -- output space
when 450000 =>
E <= '0';
when 500000 =>
RS <= '0';
E <= '1';
DB <= "00010000"; -- cursor shift left
when 550000 =>
E <= '0';
when others => null;
end case;
elsif (rxdata = "00001101") then -- if input is enter
case cnt2 is
when 300000 =>
RS <= '0';
E <= '1';
DB <= "11000000"; -- go to second row
when 350000 =>
E <= '0';
when others => null;
end case;
else
case cnt2 is
when 300000 =>
RS <= '1';
E <= '1';
DB <= rxdata; -- output character
when 350000 =>
E <= '0';
when others => null;
end case;
end if;
end if;
end if;
end process p_main;
end architecture rtl;
This one has been boggling my mind for the last two days so i've came to the internets for help.
Bit of background info first...
I'm working on a traffic lights project for uni using an Altera DE0 board. I'm a complete n00b with regards to VHDL and this first assignment was more or less a case of "here's an example of a finite state machine and an example of an LPM counter, go make some traffic lights". I think the idea's just to get a feel for using VHDL and mess about with the code to get something working.
We were given an example from a textbook (Free Range VHDL p93 iirc) on an FSM then shown how to make an LPM counter using the Megawizard Plugin Manager in Quartus and basically just had to merge/expand them. Its the first thing i've done using VHDL.
The traffic lights are supposed to be for an intersection of a major road and minor road. The default state will be major road green and minor road red. It should stay in this state until it detects a pushbutton (i.e. a car at the minor road) then go amber then red, then the minor road will go from red to green and stay in green for 10 seconds. It will stay in each other state for 1 second.
I've used 9 states (A-I) and one LPM counter and i'm just looking for a 1 in bit 26 and 29 of the "q" output(?) of the counter for the 1 and 10 second delay.
My problem is that i'm not sure where to set and reset the timer. Technically it should be reset after moving into each state then set (i.e. allowed to count) when moving to the next state.
I'll paste my code below, currently the timer_rst bits are commented out. I've tried placing them in all different lines in the code but the closest i've came to having it work is setting and resetting the timer where those commented out set and reset parts are. When i un-comment them out one at a time and run it each time it'll go from state A to B then C but after that it'll just skip to E then it moves through states so quick all the LEDs light and it seems to jump randomly through different states. Obviously this isn't how it should be done!
Can anyone help me out then?
I hope i've given a decent enough explanation here. I'll paste a link to a video of the board running my code and you can check the code out below too.
Thanks for any help provided!
--Finite state machine using DE0 board implementing a set
--of traffic tights at a major road/minor road junction.
--Major road is green until car present at minor road
--then goes to red while minor road goes to green.
--8 states, A-H. A is 'default' state
--1 sec delay: state B,C,D,F,G,H, 10 sec delay: state E,I.
--Maj Rd lights: LEDG(5 downto 3) Red/Amber/Green.
--Min Rd lights: LEDG(2 downto 0) Red/Amber/Green.
--State vector printed on LEDG(9 downto 6) in binary
--library declarations
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY lpm; --allows use of Altera LPM functions
USE lpm.all;
--entity
entity TRAFFICLIGHTS is
port(
KEY : in std_logic_vector(1 downto 0); --minor rd car present KEY(1) & reset KEY(0)-ACTIVE LOW!
CLOCK_50 : in std_logic;
LEDG : out std_logic_vector(9 downto 0); --6 lights 2 * (red/amber/green) & state vector
HEX0 : out std_LOGIC_VECTOR(7 downto 0) --display current state
);
end TRAFFICLIGHTS;
-- architecture
architecture TRAFFICLIGHTS_arch of TRAFFICLIGHTS is
type state_type is (A,B,C,D,E,F,G,H,I);
signal PS, NS : state_type;
signal timer_rst : std_logic; --wiring to delay components , one_sec, ten_sec
signal timer_q : std_logic_vector(29 downto 0); --output from timer
--LPM counter
component timer
PORT
(
aclr : IN STD_LOGIC ;
clock : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (29 DOWNTO 0) --uses bit 29 for 10 secs, bit 26 for 1 sec
);
end component;
begin
--wiring up LPM counter to signals
U1 : timer
PORT MAP (
aclr => timer_rst,
clock => clock_50,
q => timer_q
);
--detects change in clock, next state or reset key press
sync_proc: process (clock_50, NS, KEY(0))
begin
if (KEY(0)='0') then --if reset pressed, return to state A
PS <= A;
elsif (rising_edge(clock_50)) then --else put present state in next state
PS <= NS;
end if;
end process sync_proc;
--detect change in present state or KEY(1) i.e. minor road car present
comb_proc: process (PS, KEY(1))
begin
case PS is
when A => --when in A: MajRd green, MinRd red, no delay
--show state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0001";
HEX0(7 downto 0) <= "10001000"; --display state on 7 seg
LEDG(5) <= '0'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '1'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (KEY(1) = '0') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= B; --if car present #MinRd, next state is B
else NS <= A;
end if;
when B => --when in B: MajRd amber, MinRd red, 1 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0010";
HEX0(7 downto 0) <= "10000011"; --display state on 7 seg
LEDG(5) <= '0'; --MajRed
LEDG(4) <= '1'; --MajAmber
LEDG(3) <= '0'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(26) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= C;
else NS <= B;
end if;
when C => --when in C: MajRd red, MinRd red, 1 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0011";
HEX0(7 downto 0) <= "11000110"; --display state on 7 seg
LEDG(5) <= '1'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '0'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(26) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= D;
else NS <= C;
end if;
when D => --when in D: MajRd red, MinRd red/amber, 1 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0100";
HEX0(7 downto 0) <= "10100001"; --display state on 7 seg
LEDG(5) <= '1'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '0'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '1'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(26) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= E;
else NS <= D;
end if;
when E => --when in E: MajRd red, MinRd green, 10 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0101";
HEX0(7 downto 0) <= "10000110"; --display state on 7 seg
LEDG(5) <= '1'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '0'; --MajGreen
LEDG(2) <= '0'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '1'; --MinGreen
if (timer_q(29) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= F;
else NS <= E;
end if;
when F => --when in F: MajRd red, MinRd amber, 1 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0110";
HEX0(7 downto 0) <= "10001110"; --display state on 7 seg
LEDG(5) <= '1'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '0'; --MajGreen
LEDG(2) <= '0'; --MinRed
LEDG(1) <= '1'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(26) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= G;
else NS <= F;
end if;
when G => --when in G: MajRd red, MinRd red, 1 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0111";
HEX0(7 downto 0) <= "10010000"; --display state on 7 seg
LEDG(5) <= '1'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '0'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(26) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= H;
else NS <= G;
end if;
when H => --when in H: MajRd red/amber, MinRd red, 1 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "1000";
HEX0(7 downto 0) <= "10001001"; --display state on 7 seg
LEDG(5) <= '0'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '1'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(26) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= I;
else NS <= H;
end if;
--new state allows MajRd to stay green (10 sec) if car at MinRd or not
when I => --when in I: MajRd green, MinRd red, 10 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "1001";
HEX0(7 downto 0) <= "11111001"; --display state on 7 seg
LEDG(5) <= '0'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '1'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(29) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= C;
else NS <= A;
end if;
when others => -- the catch-all condition
PS <= A; -- if anything else, return to state A
end case;
end process comb_proc;
end TRAFFICLIGHTS_arch;
Video:
https://www.dropbox.com/s/70tkr67zdjj8pyk/File%2018-03-2015%2017%2057%2054.mov?dl=0
Tried adding intermediate states, here's the code from the case statement for the first few below. Its just starting and jumping straight to state B now and not going anywhere.
case PS is
when A => --when in A: MajRd green, MinRd red, no delay
--show state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0001";
HEX0(7 downto 0) <= "10001000"; --display state on 7 seg
LEDG(5) <= '0'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '1'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (KEY(1) = '0') then
timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= B; --if car present #MinRd, next state is B
else NS <= A_1;
end if;
when A_1 =>
--LEDs and 7 seg same as A
LEDG(9 downto 0) <= "0001001100";
HEX0(7 downto 0) <= "10001000"; --display state on 7 seg
timer_rst <= '0'; -- allow timer to count
NS <= B;
when B => --when in B: MajRd amber, MinRd red, 1 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0010";
HEX0(7 downto 0) <= "10000011"; --display state on 7 seg
LEDG(5) <= '0'; --MajRed
LEDG(4) <= '1'; --MajAmber
LEDG(3) <= '0'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(26) = '1') then
timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= B_1;
else NS <= B;
end if;
when B_1 =>
--LEDs and 7 seg same as B
LEDG(9 downto 0) <= "0010010100";
HEX0(7 downto 0) <= "10000011"; --display state on 7 seg
timer_rst <= '0'; -- allow timer to count
NS <= C;
Chris, check "FINITE STATE MACHINES IN HARDWARE...", V. A. Pedroni, MIT Press, page 166.
I am new in VHDL. I try to create train ticket machine using vhdl. It have 3 destination and all destination have fee. When user insert money with same of fee, ticket will out and no change but if user enter extra money than fee, ticket will out also with change.When i run the simulation all output does not appear correctly but only come out with uuu. Anybody can help me with my code below, please.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity trainticket_machine is
PORT( Clock,Reset,Cancel : IN STD_LOGIC;
RM1,RM2,RM5 : IN STD_LOGIC;
KL_station,Mid_station,Klang_station : IN STD_LOGIC;
Ticket : OUT STD_LOGIC;
Change,Retrn : OUT STD_LOGIC_VECTOR (3 DOWNTO 0);
Money_sum : INOUT STD_LOGIC_VECTOR (3 DOWNTO 0)
);
end trainticket_machine;
architecture Behavioral of trainticket_machine is
TYPE state IS (S0,S1,S2,S3,S4,S5,S6,S7,S8,S9,Cancl,waiting1,waiting2,waiting3,KL_Ticket,Mid_Ticket,Shah_Ticket);
SIGNAL p_state,Train_state: STATE;
BEGIN
PROCESS(Reset,Clock)
BEGIN
IF (Reset = '1') THEN
p_state <= S0;
Ticket <= '0';
Retrn <= "0000";
Money_sum <= "ZZZZ";
ELSIF (Clock'EVENT AND Clock = '1') THEN
p_state <= Train_state;
END IF;
END PROCESS;
PROCESS (p_state,Cancel,RM1,RM2,RM5,KL_station,Mid_station,Klang_station)
BEGIN
CASE p_state IS
WHEN S0 =>
Money_sum <= "0000";
Change <= "0000";
IF (KL_station = '1') THEN Train_state <= waiting1;
ELSIF(Mid_station = '1') THEN Train_state <= waiting2;
ELSIF(Klang_station = '1') THEN Train_state <= waiting3;
ELSE Train_state <= S0;
END IF;
WHEN waiting1 =>
Ticket <= '0';
Change <= "0000";
IF (RM1 = '1') THEN Train_state <= S1;
ELSIF (RM2 = '1') THEN Train_state <= S2;
ELSIF (RM5 = '1') THEN Train_state <= S3;
ELSIF (Money_sum >= 2) THEN train_state <= KL_Ticket;
ELSIF (Cancel = '1') THEN Train_state <= Cancl;
ELSE Train_state <= waiting1;
END IF;
WHEN waiting2 =>
Ticket <= '0';
Change <= "0000";
IF (RM1 = '1') THEN Train_state <= S4;
ELSIF (RM2 = '1') THEN Train_state <= S5;
ELSIF (RM5 = '1') THEN Train_state <= S6;
ELSIF (Money_sum >= 4) THEN train_state <= Mid_Ticket;
ELSIF (Cancel = '1') THEN Train_state <= Cancl;
ELSE Train_state <= waiting2;
END IF;
WHEN waiting3 =>
Ticket <= '0';
Change <= "0000";
IF (RM1 = '1') THEN Train_state <= S7;
ELSIF (RM2 = '1') THEN Train_state <= S8;
ELSIF (RM5 = '1') THEN Train_state <= S9;
ELSIF (Money_sum >= 6) THEN train_state <= Shah_Ticket;
ELSIF (Cancel = '1') THEN Train_state <= Cancl;
END IF;
WHEN S1 =>
IF (RM1 <= '1' AND RM2 <= '0' AND RM5 <= '0') THEN
Ticket <= '0';
Change <= "0000";
Money_sum <= Money_sum + 1;
ELSE Train_state <= waiting1;
END IF;
WHEN S2 =>
IF (RM1 <= '1' AND RM2 <= '1' AND RM5 <= '0') THEN
Ticket <= '1';
Change <= "0000";
Money_sum <= Money_sum + 2;
ELSE Train_state <= waiting1;
END IF;
WHEN S3 =>
IF (RM1 <= '0' AND RM2 <= '0' AND RM5 <= '1') THEN
Ticket <= '1';
Change <= "0001";
Money_sum <= Money_sum + 5;
ELSE Train_state <= waiting1;
END IF;
WHEN S4 =>
IF (RM1 <= '1' AND RM2 <= '0' AND RM5 <= '0') THEN
Ticket <= '0';
Change <= "0000";
Money_sum <= Money_sum + 1;
ELSE Train_state <= waiting2;
END IF;
WHEN S5 =>
IF (RM1 <= '0' AND RM2 <= '1' AND RM5 <= '0') THEN
Ticket <= '0';
Change <= "0000";
Money_sum <= Money_sum + 2;
ELSE Train_state <= waiting2;
END IF;
WHEN S6 =>
IF (RM1 <= '0' AND RM2 <= '0' AND RM5 <= '1') THEN
Ticket <= '0';
Change <= "0001";
Money_sum <= Money_sum + 5;
ELSE Train_state <= waiting2;
END IF;
WHEN S7 =>
IF (RM1 <= '1' AND RM2 <= '0' AND RM5 <= '0') THEN
Ticket <= '0';
Change <= "0000";
Money_sum <= Money_sum + 1;
ELSE Train_state <= waiting3;
END IF;
WHEN S8 =>
IF (RM1 <= '0' AND RM2 <= '1' AND RM5 <= '0') THEN
Ticket <= '0';
Change <= "0000";
Money_sum <= Money_sum + 2;
ELSE Train_state <= waiting3;
END IF;
WHEN S9 =>
IF (RM1 <= '0' AND RM2 <= '0' AND RM5 <= '1') THEN
Ticket <= '0';
Change <= "0000";
Money_sum <= Money_sum + 5;
ELSE Train_state <= waiting3;
END IF;
WHEN KL_Ticket =>
Ticket <= '1';
Change <= Money_sum - 2;
Train_state <= waiting1;
WHEN Mid_Ticket =>
Ticket <= '1';
Change <= Money_sum - 4;
Train_state <= waiting2;
WHEN Shah_Ticket =>
Ticket <= '1';
Change <= Money_sum - 6;
Train_state <= waiting3;
WHEN Cancl =>
IF (Cancel <= '1') THEN
Retrn <= Money_sum;
ELSE Train_state <= S0;
END IF;
END CASE;
END PROCESS;
end Behavioral;
------------------------------simulation----------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use ieee.std_logic_arith.all;
ENTITY trainticket_machine_tb IS
END trainticket_machine_tb;
ARCHITECTURE behavior OF trainticket_machine_tb IS
Signal Clock,Reset,Cancel,RM1,RM2,RM5,KL_station,Mid_station,Klang_station : std_logic := '0';
Signal Ticket : std_logic ;
signal Change,Retrn,Money_sum : std_logic_vector(3 downto 0);
constant Clock_period : time := 10 ns;
BEGIN
uut: entity work.trainticket_machine PORT MAP (
Clock => Clock,
Reset => Reset,
Cancel => Cancel,
RM1 => RM1,
RM2 => RM2,
RM5 => RM5,
KL_station => KL_station,
Mid_station => Mid_station,
Klang_station => Klang_station,
Ticket => Ticket,
Change => Change,
Retrn => Retrn,
Money_sum => Money_sum
);
Clock_process :process
begin
Clock <= '0';
wait for Clock_period/2;
Clock <= '1';
wait for Clock_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
wait for Clock_period*2;
Reset <= '1';
wait for Clock_period;
Reset <= '0';
wait for Clock_period;
Cancel <= '1';
wait for Clock_period;
Cancel <= '0';
wait for Clock_period;
KL_station <= '1';
wait for Clock_period;
KL_station <= '0';
wait for Clock_period;
Mid_station <= '1';
wait for Clock_period;
Mid_station <= '0';
wait for Clock_period;
Klang_station <= '1';
wait for Clock_period;
Klang_station <= '0';
wait for Clock_period;
RM1 <= '1';
wait for Clock_period;
RM1 <= '0';
wait for Clock_period;
RM2 <= '1';
wait for Clock_period;
RM2 <= '0';
wait for Clock_period;
RM5 <= '1';
wait for Clock_period;
RM5 <= '0';
wait for Clock_period;
wait;
end process;
END;
Starting with the first problem you describe: since you are seeing only 'U's, maybe your outputs were never assigned any value. Did you remember to force Reset to '1' in the beginning of the simulation?
Now let's take a look at the state machine logic itself, which has many problems. First thing: you should differentiate between combinational logic and registered state. By state I mean values that must be kept in registers of flip-flops, between the clock transitions.
This is important because for each process you will have to decide whether it is combinational or registered. If the process is registered, it must be sensitive to your clock. If the process is combinational, it cannot have any statements that woud imply keeping state information.
So the first suggestion is to go through your code, and decide the nature of each process you have. You may have to create a few more processes, it's ok. From your code, it looks like the signal money_sum is state information, and therefore it should be updated on the rising edge of clock.
The second suggestion is: if you have an output that depends only on the current state (maybe your signal ticket), you need to assign a value to this signal on every condition of your case statement. Try removing the line Ticket <= '0'; from your first process and see what happens.
Third, please use more descriptive names for your states and signals, it is really hard to understand what is going on from names like S0, S1, S2, RM1, RM2, and RM5.
Finally, it would be really helpful to have some assertions in your testbench code. For instance, after every wait for Clock_period;, you could check your outputs to make sure they match what you expected:
Reset <= '1';
wait for Clock_period;
assert ticket = '0' report "Wrong value for 'ticket' after reset";
assert change = "0000" report "Wrong value for 'change' after reset";
assert retrn = "0000" report "Wrong value for 'retrn' after reset";
assert money_sum = "0000" report "Wrong value for 'money_sum' after reset";