I've recently been working on some code trying to make a vending machine in vhdl. Started getting some strange errors and managed to narrow it down to my display value being updated.
The code is basically suppose to be able to toggle between display formats for a 7-segment display. I'd say it works as it should mostly but seemed to freeze randomly
I altered to code,found below, a little for debugging and noticed that the values within the case statement get stuck at a certain value. The rest of the code continuous to run perfectly so I can reset and it will work again. Below is the code with the problem
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity display_switch is
Port ( clk : in STD_LOGIC;
reset: in STD_LOGIC;
number : in STD_LOGIC_VECTOR (13 downto 0);-- unsigned binary number
hexid : in std_logic_vector(15 downto 0); -- hex representation
sel : in std_logic;
an : out std_logic_vector(3 downto 0);
seg : out STD_LOGIC_VECTOR (6 downto 0); -- 7 segment display
dp,Led,Led1,Led2 : out std_logic);
end display_switch;
architecture bhv of display_switch is
type button_state is(dec,hex,deb); -- states for display formats
signal current_display,next_display : button_state;
process(clk, reset)
begin
if reset = '1' then -- asynchronous reset
current_display <= dec;
next_display <= hex;
decp <= '1'; -- decimal point
elsif rising_edge(clk) then
segm_display <= hexid;
case current_display is
when dec => Led2 <= '1';
Led1 <= '0';
Led <= '0';
decp <= '0';
next_display <= hex;
if sel = '1' then
current_display <= deb;
end if;
when hex => Led2 <= '0';
Led1 <= '1';
Led <= '0';
decp <= '1';
next_display <= dec;
if sel = '1' then
current_display <= deb;
end if;
when deb => Led2 <= '0';
Led1 <= '0';
Led <= '1';
if sel /= '1' then
current_display <= next_display;
end if;
when others => current_display <= dec;
end case;
end if;
end process;
end bhv;
Basically what happens is that the output values in the case statements either all get stuck at '1' or all get stuck at '0'.
Thanks
Your computation for the next states is dubious. If you are using a synchronous process (as you are indeed doing), you do not need a next_display signal. Just assign the next state value to current_display instead.
I found the problem. It was a timing issue with the "sel" input variabel.
added a signal to store the value on rising clock edge.
temp <= sel;
then used that temp variable instead.
Related
So i have this receiver code for the RS232 communication link, I'm supposed to send 8 bits with 1 start bit "0" and one stop bit "1", no parity check bit, I have tried with those code in most kinds of ways but the simulation never worked correctly, even though some people told me my problem is the testbench not the code but it never works on the FPGA implementation, the first signal i sent is always wrong where as any signal after that is correct.
here is the code below
entity Rs232Rxd is
port( Reset, Clock16x, Rxd: in std_logic;
DataOut1: out std_logic_vector (7 downto 0));
end Rs232Rxd;
architecture Rs232Rxd_Arch of Rs232Rxd is
attribute enum_encoding: string;
-- state definitions
type stateType is (stIdle, stData, stStop, stRxdCompleted);
attribute enum_encoding of statetype: type is "00 01 11 10";
signal iReset : std_logic;
signal iRxd1, iRxd2 : std_logic := '1';
signal presState: stateType;
signal nextState: stateType;
signal iClock1xEnable, iClock1x, iEnableDataOut: std_logic :='0' ;
signal iClockDiv: std_logic_vector (3 downto 0) := (others=>'0') ;
signal iDataOut1, iShiftRegister: std_logic_vector (7 downto 0):= (others=>'0');
signal iNoBitsReceived: std_logic_vector (3 downto 0):= (others=>'0') ;
begin
process (Clock16x) begin
if rising_edge(Clock16x) then
if Reset = '1' or iReset = '1' then
iRxd1 <= '1';
iRxd2 <= '1';
iClock1xEnable <= '0';
iClockDiv <= (others=>'0');
else
iRxd1 <= Rxd;
iRxd2 <= iRxd1;
end if;
if iRxd1 = '0' and iRxd2 = '1' then
iClock1xEnable <= '1';
end if;
if iClock1xEnable = '1' then
iClockDiv <= iClockDiv + '1';
end if;
end if;
end process;
iClock1x <= iClockDiv(3);
process (iClock1xEnable, iClock1x)
begin
if iClock1xEnable = '0' then
iNoBitsReceived <= (others=>'0');
presState <= stIdle;
elsif rising_edge(iClock1x) then
iNoBitsReceived <= iNoBitsReceived + '1';
presState <= nextState;
if iEnableDataOut = '1' then
iDataOut1 <= iShiftRegister;
--iShiftRegister <= (others=>'0');
else
iShiftRegister <= Rxd & iShiftRegister(7 downto 1);
end if;
end if;
end process;
DataOut1 <= iDataOut1;
process (presState, iClock1xEnable, iNoBitsReceived)
begin
-- signal defaults
iReset <= '0';
iEnableDataOut <= '0';
case presState is
when stIdle =>
if iClock1xEnable = '1' then
nextState <= stData;
else
nextState <= stIdle;
end if;
when stData =>
if iNoBitsReceived = "1000" then
iEnableDataOut <= '1';
nextState <= stStop;
else
iEnableDataOut <= '0';
nextState <= stData;
end if;
when stStop =>
nextState <= stRxdCompleted;
when stRxdCompleted =>
iReset <= '1';
nextState <= stIdle;
end case;
end process;
end Rs232Rxd_Arch;
Your question doesn't present a Minimal Complete and Verifiable Example. The problem cannot be duplicated without writing a testbench and your problem lacks specificity ('signal' and 'wrong' used here are imprecise).
There are some observations.
A stop bit followed by a start bit of a successive character leaves no room for state stRxdCompleted. Also iNoBitsReceived is not set to all '0's when iClock1xEnable goes invalid, meaning the sampling point is not determined by the falling edge of the start bit for successive characters:
This is a capital 'A' immediately followed by a lower case 'a', the stop bit immediately followed by the start bit of the second character (which is legal).
In the first character you see that the start bit is counted as one of the character bits.
You also see that the bit counter isn't reset when the enable goes invalid, which will cause sampling point drift (and may eventually cause sampling errors depending on clock differences or transmission distortion and lack of isosynchronous sampling point reset).
You also see presState is stStop during the last data bit of the first character and yet the second character is correct. Looking a bit closer we see the start bit of the first character occurs during stData and that doesn't occur for the second character.
There's a basic issue with number of states and state transitions when iClock1x is stopped.
You don't need the state machine, you have the counter named iNoBitsReceived that can store all the state should ishiftregister be long enough to accommodate start (and possibly stop) bits should you also detect framing errors.
Tying operations to specific counts without a separate state machine, along with clearing the bit counter when idle:
Gives us something that works with a bit less complexity:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Rs232Rxd is
port (
Reset,
Clock16x,
Rxd: in std_logic;
DataOut1: out std_logic_vector (7 downto 0)
);
end entity Rs232Rxd;
architecture foo of Rs232Rxd is
signal rxd1: std_logic;
signal rxd2: std_logic;
signal baudctr: unsigned (3 downto 0);
signal ctr16x: unsigned (3 downto 0);
signal enab1xstart: std_logic;
signal enable1x: std_logic;
signal ninthbit: std_logic;
signal sampleenab: std_logic;
signal shiftregister: std_logic_vector(7 downto 0);
begin
CLOCK_DOMAIN:
process (clock16x)
begin
if rising_edge(clock16x) then
rxd1 <= rxd;
rxd2 <= rxd1;
end if;
end process;
enab1xstart <= not rxd1 and rxd2 and not enable1x;
ENABLE_1X:
process (clock16x, reset)
begin
if reset = '1' then
enable1x <= '0';
elsif rising_edge(clock16x) then
if enab1xstart = '1' then
enable1x <= '1';
elsif ninthbit = '1' then
enable1x <= '0';
end if;
end if;
end process;
SAMPLE_COUNTER:
process (clock16x, reset, ninthbit)
begin
if reset = '1' or ninthbit = '1' then
ctr16x <= (others => '0'); -- for simulation
elsif rising_edge(clock16x) then
if enab1xstart = '1' or enable1x = '1' then
ctr16x <= ctr16x + 1;
end if;
end if;
end process;
sampleenab <= not ctr16x(3) and ctr16x(2) and ctr16x(1) and ctr16x(0);
BAUD_COUNTER:
process (clock16x, reset)
begin
if reset = '1' then
baudctr <= (others => '0');
elsif rising_edge(clock16x) and sampleenab = '1' then
if baudctr = 8 then
baudctr <= (others => '0');
else
baudctr <= baudctr + 1;
end if;
end if;
end process;
NINTH_BIT: -- one clock16x period long, after baudctr changes
process (clock16x, reset)
begin
if reset = '1' then
ninthbit <= '0';
elsif rising_edge(clock16x) then
ninthbit <= sampleenab and baudctr(3) and not baudctr(2) and
not baudctr(1) and not baudctr(0);
end if;
end process;
SHIFT_REG:
process (clock16x, reset)
begin
if reset = '1' then
shiftregister <= (others => '0'); -- for pretty waveforms
elsif rising_edge(clock16x) and sampleenab = '1' then
shiftregister <= rxd2 & shiftregister(7 downto 1);
end if;
end process;
OUTREG:
process (clock16x, reset)
begin
if reset = '1' then
dataout1 <= (others => '0');
elsif rising_edge(clock16x) and ninthbit = '1' then
dataout1 <= shiftregister;
end if;
end process;
end architecture;
VHDL basic identifiers are case insensitive, and the names weren't particularly enlightening. The format of the two above waveforms indicates name changes handily.
If you extend the shift register length by one or two you can detect framing errors during the stop bit. Changing the shift register length would require slicing the shift register output for writing to your data output.
Note this architecture is written to use package numeric_std and not Synopsys package std_logic_arith. You also didn't provide the context clause preceding the entity declaration.
This architecture also produces enables and uses the 16x clock instead of producing a 1x clock.
It was written after finding the amount of changes to correct issues in the original architecture seemed overwhelming. (When in doubt, start over.)
This testbench was used:
library ieee;
use ieee.std_logic_1164.all;
entity rs232rxd_tb is
end entity;
architecture foo of rs232rxd_tb is
signal reset: std_logic := '0';
signal clock16x: std_logic := '0';
signal rxd: std_logic := '1';
signal dataout1: std_logic_vector (7 downto 0);
begin
DUT:
entity work.rs232rxd
port map (
reset => reset,
clock16x => clock16x,
rxd => rxd,
dataout1 => dataout1
);
CLOCK:
process
begin
wait for 3.255 us; -- 16X clock divided by 2, 9600 baud 104.16 us
clock16x <= not clock16x;
if now > 2.30 ms then
wait;
end if;
end process;
STIMULI:
process
begin
wait for 6.51 us;
reset <= '1';
wait for 13.02 us;
reset <= '0';
wait for 13.02 us;
wait for 40 us;
rxd <= '0';
wait for 104.16 us; -- start bit
rxd <= '1';
wait for 104.16 us; -- first data bit, bit 0 = '1'
rxd <= '0';
wait for 104.16 us; -- second data bit, bit 1 = '0'
rxd <= '0';
wait for 104.16 us; -- third data bit, bit 2 = '0';
wait for 104.16 us; -- fourth data bit, bit 3 = '0';
wait for 104.16 us; -- fifth data bit, bit 4 = '0';
wait for 104.16 us; -- sixth data bit, bit 5 = '0';
rxd <= '1';
wait for 104.16 us; -- seventh data bit, bit 6 = '1';
rxd <= '0';
wait for 104.16 us; -- eigth data bit, bit 7 = '0';
rxd <= '1';
wait for 104.16 us; -- stop bit ( = '1')
--wait for 104.16 us; -- idle
rxd <= '0';
wait for 104.16 us; -- start bit
rxd <= '1';
wait for 104.16 us; -- first data bit, bit 0 = '1'
rxd <= '0';
wait for 104.16 us; -- second data bit, bit 1 = '0'
rxd <= '0';
wait for 104.16 us; -- third data bit, bit 2 = '0';
wait for 104.16 us; -- fourth data bit, bit 3 = '0';
wait for 104.16 us; -- fifth data bit, bit 4 = '0';
rxd <= '1';
wait for 104.16 us; -- sixth data bit, bit 5 = '1';
wait for 104.16 us; -- seventh data bit, bit 6 = '1';
rxd <= '0';
wait for 104.16 us; -- eigth data bit, bit 7 = '0';
rxd <= '1';
wait for 104.16 us; -- stop bit ( = '1')
wait;
end process;
end architecture;
You can see that new architecture has all the same essential elements, although clocked process elements are in separate process statements.
There is no state machine process.
The architecture is extensible to a full feature UART receiver by playing around with separating inputs to the shift register (for parity, two stop bits, 7 data bits, etc.). Parity can be performed serially.
So I have a modulo counter going from 1->15, then looping back around constantly in a seperate entity. I would like to, in a case statement depending on some outputs, sample this value on the rising_edge of a clock, but only do it once, otherwise the value will be constantly changing. Is there a way to do this? Assign the signal and have it stay static?
I've posted some code that I hope will demonstrate what I am trying to say a bit better.
process(all)
begin --sensitivity list?
if(reset) then
playerCards <= "0000000000000000";
dealerCards <= "0000000000000000";
elsif rising_edge(clock) then
case? deal & dealTo & dealToCardSlot is
when "1100" =>
playerCards(3 downto 0) <= singleCard;
playerCards(15 downto 4) <= (others => '0');
when "1101" =>
playerCards(7 downto 4) <= singleCard;
playerCards(15 downto 8) <= (others => '0');
when "1110" =>
playerCards(11 downto 8) <= singleCard;
playerCards(15 downto 12) <= (others => '0');
when "1111" =>
playerCards(15 downto 12) <= singleCard;
when "1000" =>
dealerCards(3 downto 0) <= singleCard; --dcard1
dealerCards( 15 downto 4) <= (others => '0');
when "1001" =>
dealerCards(7 downto 4) <= singleCard; --dcard2
dealerCards( 15 downto 8) <= (others => '0');
when "1010" =>
dealerCards(11 downto 8) <= singleCard; --dcard3
dealerCards( 15 downto 12) <= (others => '0');
when "1011" =>
dealerCards(15 downto 12) <= singleCard; --dcard4
when "0--0" => null; --do nothing when in win/end
when others => --this covers the start case --sets cards to 0
playerCards <= "0000000000000000";
dealerCards <= "0000000000000000";
end case?;
end if;
end process;
Here I have singleCard being linked to the output of my counter, which increments every clock edge. So basically I would like my case statement to only happen update the value of playerCards once, and then stop.
Thanks for any help.
Your requirement can be stated as : the process can be in two states - sampling, or not sampling, and to transition to not sampling when you sample.
So you can do this with a state variable, which in this case can be a boolean - this turns your process into a state machine. As the other answer says, you can use a signal here instead of a variable, but that breaks encapsulation, making the processes internal workings visible.
Some people would insist you separate out the state machine into another two (or even 3) processes, but I think the single process form is a lot smaller and easier to understand.
process(reset,clock) -- original sens list is incorrect for a clocked process
variable sampling : boolean;
begin
if(reset) then
sampling <= true;
-- other reset actions
elsif rising_edge(clock) then
if sampling then -- add conditions here, or it'll sample on the first clock.
sampling := false;
case ... -- sampling process and program logic
end case;
else
-- if you need to turn sampling back on, set "sampling" here
end if;
end if;
end process;
Yes, you need an additional internal signal that will control your operation mode: updating and non-updating.
It would be actually a kind of feedback signal. You generate it depending on the input conditions, and then you also use it on input to modify the behaviour.
I am new to VHDL and currently working on a clock generator that generates two different clock speeds.
Everything is working, except the switch between the slow and fast speed_status.
There seems to be a problem with the "speed button" because sometimes I have to press it more than once to change the current set speed. The "reset button" is always working as expected. Is there something wrong with my VHDL Code or do I need to add some sort of software debouncing? If so, why is the reset button working?
And could you give me some advice which parts of my clock generator I could improve (code/logic)?
entity clk_gen is
Port ( clk_in : in STD_LOGIC;
clk_btn_in : in STD_LOGIC_VECTOR (3 DOWNTO 0);
clk_out : out STD_LOGIC);
end clk_gen;
architecture Behavioral of clk_gen is
signal temp : STD_LOGIC := '0';
begin
clock: process(clk_in,clk_btn_in)
variable counter : integer range 0 to 49999999 := 0;
constant freq_cnt_slow : integer := 49999999;
constant freq_cnt_fast : integer := 4999999;
type speed is (slow, fast);
variable speed_status : speed := slow;
begin
if rising_edge(clk_in) then
-- RESET BUTTON PRESSED
if (clk_btn_in = "1000") then
temp <= '0';
counter := 0;
speed_status := slow;
-- SPEED BUTTON
elsif (clk_btn_in = "0100") then
if (speed_status = fast) then
speed_status:= slow;
elsif (speed_status = slow) then
speed_status := fast;
end if;
end if;
if ((counter = freq_cnt_fast) and (speed_status = fast)) then
temp <= NOT(temp);
counter := 0;
elsif ((counter = freq_cnt_slow) and (speed_status = slow)) then
temp <= NOT(temp);
counter := 0;
else
counter := counter + 1;
end if;
end if;
end process clock;
clk_out <= temp;
end Behavioral;
I use Xilinx ISE 13.4 and the XC5VLX110T based on Xilinx Virtex 5.
It looks like your speed mode will toggle any time the button is in the 'pressed' state. Unless you can guarantee that your button is only 'pressed' for one clock period, the state is likely to toggle many times, making the state after you pressed the button essentially random (depending on the exact timing of the button press).
Firstly, you need a debouncing circuit on the button. This can be implemented externally, or within the FPGA. I will not go into switch debouncing in detail here, but you can easily find information on this elsewhere. Secondly, you need to convert the button into a synchronous signal, that is, one that has a fixed relationship to your clock. An example synchroniser for your example would be:
signal button_reg1 : std_logic_vector(3 downto 0) := (others => '0');
signal button_reg2 : std_logic_vector(3 downto 0) := (others => '0');
...
process (clk_in)
begin
if (rising_edge(clk_in)) then
button_reg2 <= button_reg1;
button_reg1 <= clk_btn_in;
end if;
end process;
button_reg2 will then have a fixed relationship to the clock.
Without this, you could violate the setup/hold constraints on the speed_status register. Lastly, you need to convert the pressing of the button into a pulse that is one clock period in length. Example:
signal speed_button_reg : std_logic := '0';
signal speed_button_pressed : std_logic := '0';
...
process (clk_in)
begin
if (rising_edge(clk_in)) then
speed_button_reg <= button_reg2(2);
if (speed_button_reg = '0' and button_reg2(2) = '1') then
-- The button has just been pressed (gone from low to high)
-- Do things here, or set another signal e.g.
speed_button_pressed <= '1';
else
speed_button_pressed <= '0';
end if;
end if;
end process;
I have been trying to design an RS-232 receiver taking an FSM approach. I will admit that I do not have a very well-rounded understanding of VHDL, so I have been working on the code on the fly and learning as I go. However, I believe I've hit a brick wall at this point.
My issue is that I have two processes in my code, one to trigger the next state and the other to perform the combinational logic. My code is as follows:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity ASyncReceiverV4 is
Port ( DataIn : in STD_LOGIC;
Enable : in STD_LOGIC;
CLK : in STD_LOGIC;
BadData : out STD_LOGIC;
DataOut : out STD_LOGIC_VECTOR (7 downto 0));
end ASyncReceiverV4;
architecture Behavioral of ASyncReceiverV4 is
type states is (StartBitCheck, ReadData, StopBitCheck);
signal currentState, nextState : states;
begin
process(CLK)
begin
if rising_edge(CLK) then
currentState <= nextState;
end if;
end process;
process(CLK)
variable counter : integer := 0;
variable dataIndex : integer := 0;
begin
case currentState is
when StartBitCheck =>
if Enable = '1' then
if (DataIn = '0' and counter < 8) then
counter := counter + 1;
elsif (DataIn = '0' and counter = 8) then
BadData <= '0';
nextState <= ReadData;
counter := 0;
else
nextState <= StartBitCheck;
end if;
end if;
when ReadData =>
if Enable = '1' then
if counter < 16 then
counter := counter + 1;
elsif (counter = 16 and dataIndex < 8) then
DataOut(dataIndex) <= DataIn;
counter := 0;
dataIndex := dataIndex + 1;
elsif dataIndex = 8 then
dataIndex := 0;
nextState <= StopBitCheck;
else
nextState <= ReadData;
end if;
end if;
when StopBitCheck =>
if Enable = '1' then
if DataIn = '1' then
if counter < 16 then
counter := counter + 1;
nextState <= StopBitCheck;
elsif counter = 16 then
counter := 0;
nextState <= StartBitCheck;
end if;
else
DataOut <= "11111111";
BadData <= '1';
nextState <= StartBitCheck;
end if;
end if;
end case;
end process;
end Behavioral;
For whatever reason, based on my simulations, it seems that my processes are out of sync. Although things are only supposed to occur at the rising edge of the clock, I have transitions occurring at the falling edge. Furthermore, it seems like things are not changing according to the value of counter.
The Enable input is high in all of my simulations. However, this is just to keep it simple for now, it will eventually be fed the output of a 153,600 Baud generator (the Baud generator will be connected to the Enable input). Hence, I only want things to change when my Baud generator is high. Otherwise, do nothing. Am I taking the right approach for that with my code?
I can supply a screenshot of my simulation if that would be helpful. I am also not sure if I am including the correct variables in my process sensitivity list. Also, am I taking the right approach with my counter and dataIndex variables? What if I made them signals as part of my architecture before any of my processes?
Any help on this would be very much so appreciated!
The easiest way to fix this, while also producing the easiest to read code, would be to move to a 1-process state machine like so (warning: not complied may contain syntax errors):
entity ASyncReceiverV4 is
Port ( DataIn : in STD_LOGIC;
Enable : in STD_LOGIC;
CLK : in STD_LOGIC;
BadData : out STD_LOGIC;
DataOut : out STD_LOGIC_VECTOR (7 downto 0));
end ASyncReceiverV4;
architecture Behavioral of ASyncReceiverV4 is
type states is (StartBitCheck, ReadData, StopBitCheck);
signal state : states := StartBitCheck;
signal counter : integer := 0;
signal dataIndex : integer := 0;
begin
process(CLK)
begin
if rising_edge(CLK) then
case state is
when StartBitCheck =>
if Enable = '1' then
if (DataIn = '0' and counter < 8) then
counter <= counter + 1;
elsif (DataIn = '0' and counter = 8) then
BadData <= '0';
state <= ReadData;
counter <= 0;
end if;
end if;
when ReadData =>
if Enable = '1' then
if counter < 16 then
counter <= counter + 1;
elsif (counter = 16 and dataIndex < 8) then
DataOut(dataIndex) <= DataIn;
counter <= 0;
dataIndex <= dataIndex + 1;
elsif dataIndex = 8 then
dataIndex <= 0;
state <= StopBitCheck;
end if;
end if;
when StopBitCheck =>
if Enable = '1' then
if DataIn = '1' then
if counter < 16 then
counter <= counter + 1;
elsif counter = 16 then
counter <= 0;
state <= StartBitCheck;
end if;
else
DataOut <= "11111111";
BadData <= '1';
state <= StartBitCheck;
end if;
end if;
end case;
end if;
end process;
end Behavioral;
Note that while this no longer contains language issues, there are still odd things in the logic.
You cannot enter the state StopBitCheck until counter is 16 because the state transition is in an elsif of counter < 16. Therefore, the if counter < 16 in StopBitCheck is unreachable.
Also note that the state transition to StopBitCheck happens on the same cycle that you would normally sample data, so the sampling of DataIn within StopBitCheck will be a cycle late. Worse, were you ever to get bad data (DataIn/='1' in StopBitCheck), counter would still be at 16, StartBitCheck would always go to the else clause, and the state machine would lock up.
Some more explanation on what was wrong before:
Your simulation has things changing on the negative clock edge because your combinatorial process only has the clock on the sensitivity list. The correct sensitivity list for the combinatorial process would include only DataIn, Enable, currentState, and your two variables, counter and dataIndex. Variables can't be a part of your sensitivity list because they are out of scope for the sensitivity list (also you do not want to trigger your process off of itself, more on that in a moment).
The sensitivity list is, however, mostly just a crutch for simulators. When translated to real hardware, processes are implemented in LUTs and Flip Flops. Your current implementation will never synthesize because you incorporate feedback (signals or variables that get assigned a new value as a function of their old value) in unclocked logic, producing a combinatorial loop.
counter and dataIndex are part of your state data. The state machine is simpler to understand because they are split off from the explicit state, but they are still part of the state data. When you make a two process state machine (again, I recommend 1 process state machines, not 2) you must split all state data into Flip Flops used to store it (such as currentState) and the output of the LUT that generates the next value (such as nextState). This means that for your two process machine, the variables counter and dataIndex must instead become currentCounter, nextCounter, currentDataIndex, and nextDataIndex and treated like your state assignment. Note that if you choose to implement changes to keep a 2-process state machine, the logic errors mentioned above the line will still apply.
EDIT:
Yes, resetting the counter back to 0 before moving into StopBitCheck might be a good idea, but you also need to consider that you are waiting the full 16 counts after sampling the last data bit before you even transition into StopBitCheck. It is only because counter is not reset that the sample is only off by one clock instead of 16. You may want to modify your ReadData action to transition to StopBitCheck as you sample the last bit when dataIndex=7 (as well as reset counter to 0) like so:
elsif (counter = 16) then
DataOut(dataIndex) <= DataIn;
counter <= 0;
if (dataIndex < 7) then
dataIndex <= dataIndex + 1;
else
dataIndex <= 0;
state <= StopBitCheck;
end if;
end if;
A pure state machine only stores a state. It generates its output purely from the state, or from a combination of the state and the inputs. Because counter and dataIndex are stored, they are part of the state. If you wanted to enumerate every single state you would have something like:
type states is (StartBitCheck_Counter0, StartBitCheck_counter1...
and you would end up with 8*16*3 = 384 states (actually somewhat less because only ReadData uses dataIndex, so some of the 384 are wholly redundant states). As you can no doubt see, it is much simpler to just declare 3 separate signals since the different parts of the state data are used differently. In a two process state machine, people often forget that the signal actually named state isn't the only state data that needs to be stored in the clocked process.
In a 1-process machine, of course, this isn't an issue because everything that is assigned is by necessity stored in flip flops (the intermediary combinational logic isn't enumerated in signals). Also, do note that 1-process state machines and 2-process state machines will synthesize to the same thing (assuming they were both implemented correctly), although I'm of the opinion that is comparatively easier to read and more difficult to mess up a 1-process machine.
I also removed the else clauses that maintained the current state assignment in the 1-process example I provided; they are important when assigning a combinational nextState, but the clocked signal state will keep its old value whenever it isn't given a new assignment without inferring a latch.
First Process runs just on CLK rising edge, while the second one runs on both CLK edge (because runs on every CLK change).
You use 2 process, “memory-state” and “next-state builder”, the first must be synchronous (as you done) and the second, normally, is combinatorial to be able to produce next-state in time for next CLK active edge.
But in your case the second process needs also to run on every CLK pulse (because of variable counter and index), so the solution can be to run the first on rising-edge and the second on falling-edge (if your hardware support this).
Here is your code a little bit revisited, I hope can be useful.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity ASyncReceiverV4 is
Port ( DataIn : in STD_LOGIC;
Enable : in STD_LOGIC;
CLK : in STD_LOGIC;
BadData : out STD_LOGIC := '0';
DataOut : out STD_LOGIC_VECTOR (7 downto 0) := "00000000");
end ASyncReceiverV4;
architecture Behavioral of ASyncReceiverV4 is
type states is (StartBitCheck, ReadData, StopBitCheck);
signal currentState : states := StartBitCheck;
signal nextState : states := StartBitCheck;
begin
process(CLK)
begin
if rising_edge(CLK) then
currentState <= nextState;
end if;
end process;
process(CLK)
variable counter : integer := 0;
variable dataIndex : integer := 0;
begin
if falling_edge(CLK) then
case currentState is
when StartBitCheck =>
if Enable = '1' then
if (DataIn = '0' and counter < 8) then
counter := counter + 1;
elsif (DataIn = '0' and counter = 8) then
BadData <= '0';
nextState <= ReadData;
counter := 0;
else
nextState <= StartBitCheck;
end if;
end if;
when ReadData =>
if Enable = '1' then
if counter < 15 then
counter := counter + 1;
elsif (counter = 15 and dataIndex < 8) then
DataOut(dataIndex) <= DataIn;
counter := 0;
dataIndex := dataIndex + 1;
elsif dataIndex = 8 then
dataIndex := 0;
nextState <= StopBitCheck;
else
nextState <= ReadData;
end if;
end if;
when StopBitCheck =>
if Enable = '1' then
if DataIn = '1' then
if counter < 15 then
counter := counter + 1;
nextState <= StopBitCheck;
elsif counter = 15 then
counter := 0;
nextState <= StartBitCheck;
end if;
else
DataOut <= "11111111";
BadData <= '1';
nextState <= StartBitCheck;
end if;
end if;
end case;
end if;
end process;
end Behavioral;
This is a 0x55 with wrong stop bit receive data simulation
I'm a VHDL newbie and I'm struggling with the following idea. I think I still misunderstand the idea of counters and timers in VHDL. I will explain it with a simple blinking LED diode. (BTW I'm learning on Spartan-3E FPGA kit.) So here is my code (I'm not using reset yet)
entity top_level is
Port( clk : in STD_LOGIC;
led1 : out STD_LOGIC);
end top_level;
architecture Behavioral of top_level is
signal timer : STD_LOGIC_VECTOR(25 downto 0) := "00000000000000000000000000";
signal reset: boolean:= false;
begin
process (clk)
begin
led1 <= '1';
if clk='1' and clk'event then
if reset <= true then
timer <= (others => '0');
end if;
timer <= timer + 1;
end if;
if timer <= "11100100111000011100000000" then
led1 <= '0';
end if;
end process;
end Behavioral;
The oscillator frequency is 50 MHz so one period is 20 ns. If I want to blink with a LED for 1.2 second (which makes 60 000 000 cycles) I need to create a 26 bit vector. So I created a process which is triggered by clk change.
WHAT I THINK IT SHOULD DO:
the first line of code is a logic 1 assignment to led1. So the led1 should light until the counter won't count 60 000 000 cycles. When counter counts 60 000 000 cycles, the led logic state should switch to 0 which means no light. As the maximum value of 26 bit number is 67 108 863, the LED should light for 60 000 000 cycles and be turned off for the remaining 7 108 863 cycles. Isn't that right ?
WHAT IT DOES:My impression is, that it's kinda reversed. The LED is off for the most of the time (67 108 063 cycles) and lights for 7 108 863 cycles. Why is this happening ? I don't really get it.
Additional question: How can I achieve to run this process only once/twice/...? E.g. I want to blink with my LED 3 times and then turn it off. Because as far as I know after reaching maximum 26 bit number, the time vector will start counting from the beginning (from 0). And so on, endlessly.
First of all, you should divide your design in several parts, which can be entities or several processes. I'll use processes or some one-liner. You can also extract the presented functions into a separate package.
part 1: generate a 0.833 Hz signal from 50 MHz system clock
part 2: control whether the led is on or off
part 3: count the on cycles and disable the led after 3
Part 1
I would suggest to use the type UNSIGNED for a counter, so the '+' operator is defined for this type.
I named it timer_us so it's easy to see that this signal is an unsigned.
Additionally, you can use (others => '0') in declarations, too.
signal reset : STD_LOGIC := '0'; -- disabled reset; TODO move this signal to port
signal timer_us : UNSIGNED(25 downto 0) := (others => '0');
signal timer_tick : STD_LOGIC;
process(clk)
begin
if rising_edge(clk) then
if (reset = '1') then
timer_us <= (others => '0');
else
timer_us <= timer_us + 1;
end if;
end if;
end process;
timer_tick <= '1' when (timer_us = to_unsigned(60 * 1000 * 1000), timer_us'length) else '0';
The last line describes a ternary operator (like z = a ? x : y in C). So the tick signal is '1' if the timer reaches 60,000,000. But there is a fault: Your counter starts at 0 so 60,000,000 cycles are already reached at max - 1.
Some improvements for a more generic counter template:
in most cases it's necessary to reset the counter independently from the main reset -> timer_rst
define a constant for the maximal counter value -> TIMER_MAX
automatically calculate the counter value depending on the maximal counter value -> log2ceil
implement a function to convert boolean expressions to STD_LOGIC -> to_sl
because timer is of type unsigned, you can use a direct comparison with an integer value
Here the extended counter code:
signal reset : STD_LOGIC := '0'; -- disabled reset; TODO move this signal to port
function log2ceil(arg : positive) return natural is
variable tmp : positive := 1;
variable log : natural := 0;
begin
if arg = 1 then return 0; end if;
while arg > tmp loop
tmp := tmp * 2;
log := log + 1;
end loop;
return log;
end function;
function to_sl(condition : BOOLEAN) return STD_LOGIC is
begin
if condition then
return '1';
else
return '0';
end if;
end function;
constant TIMER_MAX : POSITIVE := 60 * 1000 * 1000 - 1;
constant TIMER_BITS : POSITIVE := log2ceil(TIMER_MAX);
signal timer_rst : STD_LOGIC;
signal timer_us : UNSIGNED(TIMER_BITS - 1 downto 0) := (others => '0');
signal timer_tick : STD_LOGIC;
timer_rst <= reset or timer_tick;
process(clk)
begin
if rising_edge(clk) then
if (timer_rst = '1') then
timer <= (others => '0');
else
timer <= timer + 1;
end if;
end if;
end process;
timer_tick <= to_sl(timer = TIMER_MAX - 1));
If you have fun in coding function, you can also invent a function which converts a time (the period for the 0.833 Hz signal) into a cycle count at a given frequency of 50 MHz ;)
Part 2
A blinking LED is a simple T-FF:
signal blink : STD_LOGIC := '0'; -- blink will be mapped to a FF, so initialize it
process(clk)
begin
if rising_edge(clk) then
if (timer_tick = '1') then
blink <= not blink;
end if;
end if;
end process;
LED <= blink;
Or as an one-liner (no need for a process block):
blink <= blink xor timer_tick when rising_edge(clk);
LED <= blink;
Part 3
So now you have all the tools to build counters. You can implement a second counter to count from 0 to 2. if 2 is reached you can set a control signal counter2_ctrl which is then feed back to the blink process to stop this process from toggling.
Here the extended one-liner:
blink_enable <= not counter2_ctrl;
blink <= blink xor (timer_tick and blink_enable) when rising_edge(clk);
To your question
The inverse LED output can be caused by low-active circuits on your test board.