Receiving data from RS232, vhdl - serial-port

I am using RS232 interface reference component from https://reference.digilentinc.com/reference/programmable-logic/nexys-2/start and an example code which is:
-------------------------------------------------------------------------
-- main.vhd
-------------------------------------------------------------------------
-- Author: Dan Pederson
-- Copyright 2004 Digilent, Inc.
-------------------------------------------------------------------------
-- Description: This file tests the included UART component by
-- sending data in serial form through the UART to
-- change it to parallel form, and then sending the
-- resultant data back through the UART to determine if
-- the signal is corrupted or not. When the serial
-- information is converted into parallel information,
-- the data byte is displayed on the 8 LEDs on the
-- system board.
--
-- NOTE: Not all mapped signals are used in this test.
-- The signals were mapped to ease the modification of
-- test program.
-------------------------------------------------------------------------
-- Revision History:
-- 07/30/04 (DanP) Created
-- 05/26/05 (DanP) Modified for Pegasus board/Updated commenting style
-- 06/07/05 (DanP) LED scancode display added
-------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-------------------------------------------------------------------------
--
--Title: Main entity
--
--Inputs: 3 : RXD
-- CLK
-- RST
--
--Outputs: 1 : TXD
-- LEDS
--
--Description: This describes the main entity that tests the included
-- UART component. The LEDS signals are used to
-- display the data byte on the LEDs, so it is set equal to
-- the dbOutSig. Technically, the dbOutSig is the scan code
-- backwards, which explains why the LEDs are mapped
-- backwards to the dbOutSig.
--
-------------------------------------------------------------------------
entity DataCntrl is
Port ( TXD : out std_logic := '1';
RXD : in std_logic := '1';
CLK : in std_logic;
LEDS : out std_logic_vector(7 downto 0) := "11111111";
RST : in std_logic := '0');
end DataCntrl;
architecture Behavioral of DataCntrl is
-------------------------------------------------------------------------
-- Local Component, Type, and Signal declarations.
-------------------------------------------------------------------------
-------------------------------------------------------------------------
--
--Title: Component Declarations
--
--Description: This component is the UART that is to be tested.
-- The UART code can be found in the included
-- RS232RefComp.vhd file.
--
-------------------------------------------------------------------------
component RS232RefComp
Port ( TXD : out std_logic := '1';
RXD : in std_logic;
CLK : in std_logic;
DBIN : in std_logic_vector (7 downto 0);
DBOUT : out std_logic_vector (7 downto 0);
RDA : inout std_logic;
TBE : inout std_logic := '1';
RD : in std_logic;
WR : in std_logic;
PE : out std_logic;
FE : out std_logic;
OE : out std_logic;
RST : in std_logic := '0');
end component;
-------------------------------------------------------------------------
--
--Title: Type Declarations
--
--Description: There is one state machine used in this program, called
-- the mainState state machine. This state machine controls
-- the flow of data around the UART; allowing for data to be
-- changed from serial to parallel, and then back to serial.
--
-------------------------------------------------------------------------
type mainState is (
stReceive,
stSend);
-------------------------------------------------------------------------
--
--Title: Local Signal Declarations
--
--Description: The signals used by this entity are described below:
--
-- -dbInSig : This signal is the parallel data input
-- for the UART
-- -dbOutSig : This signal is the parallel data output
-- for the UART
-- -rdaSig : This signal will get the RDA signal from
-- the UART
-- -tbeSig : This signal will get the TBE signal from
-- the UART
-- -rdSig : This signal is the RD signal for the UART
-- -wrSig : This signal is the WR signal for the UART
-- -peSig : This signal will get the PE signal from
-- the UART
-- -feSig : This signal will get the FE signal from
-- the UART
-- -oeSig : This signal will get the OE signal from
-- the UART
--
-- The following signals are used by the main state machine
-- for state control:
--
-- -stCur, stNext
--
-------------------------------------------------------------------------
signal dbInSig : std_logic_vector(7 downto 0);
signal dbOutSig : std_logic_vector(7 downto 0);
signal rdaSig : std_logic;
signal tbeSig : std_logic;
signal rdSig : std_logic;
signal wrSig : std_logic;
signal peSig : std_logic;
signal feSig : std_logic;
signal oeSig : std_logic;
signal stCur : mainState := stReceive;
signal stNext : mainState;
------------------------------------------------------------------------
-- Module Implementation
------------------------------------------------------------------------
begin
------------------------------------------------------------------------
--
--Title: LED definitions
--
--Description: This series of definitions allows the scan code to be
-- displayed on the LEDs on the FPGA system board. Because the
-- dbOutSig is the scan code backwards, the LEDs must be
-- defined backwards from the dbOutSig.
--
------------------------------------------------------------------------
LEDS(7) <= dbOutSig(0);
LEDS(6) <= dbOutSig(1);
LEDS(5) <= dbOutSig(2);
LEDS(4) <= dbOutSig(3);
LEDS(3) <= dbOutSig(4);
LEDS(2) <= dbOutSig(5);
LEDS(1) <= dbOutSig(6);
LEDS(0) <= dbOutSig(7);
-------------------------------------------------------------------------
--
--Title: RS232RefComp map
--
--Description: This maps the signals and ports in main to the
-- RS232RefComp. The TXD, RXD, CLK, and RST of main are
-- directly tied to the TXD, RXD, CLK, and RST of the
-- RS232RefComp. The remaining RS232RefComp ports are
-- mapped to internal signals in main.
--
-------------------------------------------------------------------------
UART: RS232RefComp port map ( TXD => TXD,
RXD => RXD,
CLK => CLK,
DBIN => dbInSig,
DBOUT => dbOutSig,
RDA => rdaSig,
TBE => tbeSig,
RD => rdSig,
WR => wrSig,
PE => peSig,
FE => feSig,
OE => oeSig,
RST => RST);
-------------------------------------------------------------------------
--
--Title: Main State Machine controller
--
--Description: This process takes care of the Main state machine
-- movement. It causes the next state to be evaluated on
-- each rising edge of CLK. If the RST signal is strobed,
-- the state is changed to the default starting state, which
-- is stReceive.
--
-------------------------------------------------------------------------
process (CLK, RST)
begin
if (CLK = '1' and CLK'Event) then
if RST = '1' then
stCur <= stReceive;
else
stCur <= stNext;
end if;
end if;
end process;
-------------------------------------------------------------------------
--
--Title: Main State Machine
--
--Description: This process defines the next state logic for the Main
-- state machine. The main state machine controls the data
-- flow for this testing program in order to send and
-- receive data.
--
-------------------------------------------------------------------------
process (stCur, rdaSig, dboutsig)
begin
case stCur is
-------------------------------------------------------------------------
--
--Title: stReceive state
--
--Description: This state waits for the UART to receive data. While in
-- this state, the rdSig and wrSig are held low to keep the
-- UART from transmitting any data. Once the rdaSig is set
-- high, data has been received, and is safe to transmit. At
-- this time, the stSend state is loaded, and the dbOutSig
-- is copied to the dbInSig in order to transmit the newly
-- acquired parallel information.
--
-------------------------------------------------------------------------
when stReceive =>
rdSig <= '0';
wrSig <= '0';
if rdaSig = '1' then
dbInSig <= dbOutSig;
stNext <= stSend;
else
stNext <= stReceive;
end if;
-------------------------------------------------------------------------
--
--Title: stSend state
--
--Description: This state tells the UART to send the parallel
-- information found in dbInSig. It does this by strobing
-- both the rdSig and wrSig signals high. Once these
-- signals have been strobed high, the stReceive state is
-- loaded.
--
-------------------------------------------------------------------------
when stSend =>
rdSig <= '1';
wrSig <= '1';
stNext <= stReceive;
end case;
end process;
end Behavioral;
On the basis of above code,I am trying to make my own state machine that allows me to receive few bytes from a terminal in a row to a buffer, change the state and send this bytes from a buffer to a terminal on my PC.
I've started from making counter that counts the amounts of the received bytes. I ended up not knowing what is going on, because the counter changes its value not by one but randomly. I am new to VHDL and any suggestions will be appreciated.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
entity DataCntrl is
Port ( TXD : out std_logic := '1';
RXD : in std_logic := '1';
CLK : in std_logic;
LED : out std_logic_vector(7 downto 0) := "00000000";
RST : in std_logic := '0');
end DataCntrl;
architecture Behavioral of DataCntrl is
component RS232RefComp
Port ( TXD : out std_logic := '1';
RXD : in std_logic;
CLK : in std_logic;
DBIN : in std_logic_vector (7 downto 0);
DBOUT : out std_logic_vector (7 downto 0);
RDA : inout std_logic;
TBE : inout std_logic := '1';
RD : in std_logic;
WR : in std_logic;
PE : out std_logic;
FE : out std_logic;
OE : out std_logic;
RST : in std_logic := '0');
end component;
type mainState is (
stReceive, stA,
stRereceive);
signal dbInSig : std_logic_vector(7 downto 0);
signal dbOutSig : std_logic_vector(7 downto 0);
signal rdaSig : std_logic;
signal tbeSig : std_logic;
signal rdSig : std_logic;
signal wrSig : std_logic;
signal peSig : std_logic;
signal feSig : std_logic;
signal oeSig : std_logic;
signal stCur : mainState := stReceive;
signal stNext : mainState;
begin
UART: RS232RefComp port map ( TXD => TXD,
RXD => RXD,
CLK => CLK,
DBIN => dbInSig,
DBOUT => dbOutSig,
RDA => rdaSig,
TBE => tbeSig,
RD => rdSig,
WR => wrSig,
PE => peSig,
FE => feSig,
OE => oeSig,
RST => RST);
process (CLK, RST)
begin
if (CLK = '1' and CLK'Event) then
if RST = '1' then
stCur <= stReceive;
else
stCur <= stNext;
end if;
end if;
end process;
process (stCur, rdaSig, dboutsig)
variable Send: std_logic :='0';
variable Count: integer :=0;
variable Jol: integer :=0;
begin
Jol:=Count;
Led<=std_logic_vector(to_unsigned(Jol,8));
case stCur is
when stReceive =>
rdSig <= '0';
wrSig <= '0';
if rdaSig = '1' then
Send:='0';
dbInSig <= dbOutSig;
if(Count=4) then
dbInSig <= "11101111";
stNext <= stA;
else
stNext <= stRereceive;
end if;
else
stNext <= stReceive;
end if;
when stRereceive =>
rdSig <= '1';
if(Send='0') then
Count:=Count+1;
Send:='1';
end if;
stNext <= stReceive;
when stA=>
wrSig <= '1';
rdSig <= '1';
end case;
end process;
end Behavioral;

So, take a look at your counter increment code:
process (stCur, rdaSig, dboutsig)
[...]
variable Count: integer := 0;
begin
[...]
case stCur is
[...]
when stRereceive =>
[...]
if(Send='0') then
Count:=Count+1;
Let's analyse what we see here.
count is a variable.
count is increased in a combinatorial process.
[let's leave out that your sensitivity list is incomplete]
When you say "the counter changes its value not by one", I assume you want it to increase by one every clock cycle (or comparable). But to be able to increase over a previous value, the counter must hold that previous value. That means registers are required. However, registers required a clock input. So in a clock-less combinatorial process no registers are inferred.
Then: don't use variables for registered values. There are only very little situations in which you should use variables, and this is not one of them.
Here's an example of a clocked counter process
architecture rtl of ent is
signal count : unsigned(3 downto 0) := (others => '0');
begin
clk_proc : process (clk)
begin
if rising_edge(clk) then
if [condition] then
count <= count + 1;
end if;
if reset = '1' then
count <= (others => '0');
end if;
end if;
end process;

Related

How can I test all cases of vector multiplexer in VHDL?

This is my first VHDL code, I have this multiplexer (two inputs, one selection bit) which has 8bit-vector inputs. How can I write a testing function that generates all possible vectors?
library IEEE;
use IEEE.std_logic_1164.all;
entity mux is
port(
in0, in1: in std_logic_vector(7 downto 0);
sel: in std_logic;
out0: out std_logic_vector(7 downto 0);
end mux;
architecture dataflow of mux is
begin
out0<=in1 when sel='1'
else in0;
end dataflow;
This is the testbench at the moment:
library IEEE;
use IEEE.std_logic_1164.all;
entity testbench is --empty
end testbench;
architecture tb of testbench is
-- DuT component
component mux is
port(
in0, in1: in std_logic_vector(7 downto 0);
sel: in std_logic;
out0: out std_logic);
end component;
signal tb_sel: std_logic;
signal tb_in0, tb_in1, tb_out0: std_logic_vector(7 downto 0);
begin
-- Connect DuT
DuT: mux port map(tb_in0, tb_in1, tb_sel, tb_out0);
process
begin
tb_sel <= 0;
tb_in0 <= "00000000";
tb_in1 <= "00000000";
-- TODO: test all possibilities
end process;
end tb;
Something like this can be used:
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
entity testbench is --empty
end testbench;
architecture tb of testbench is
signal tb_sel: std_logic;
signal tb_in0, tb_in1, tb_out0: std_logic_vector(7 downto 0);
begin
-- Connect DuT
DuT: entity work.mux port map(tb_in0, tb_in1, tb_sel, tb_out0);
process
begin
-- Done: Test all possibilities
for sel in 0 to 1 loop
for in0 in 0 to 2 ** tb_in0'length - 1 loop
for in1 in 0 to 2 ** tb_in1'length - 1 loop
-- Make stimuli
if sel = 0 then
tb_sel <= '0';
else
tb_sel <= '1';
end if;
tb_in0 <= std_logic_vector(to_unsigned(in0, tb_in0'length));
tb_in1 <= std_logic_vector(to_unsigned(in1, tb_in1'length));
-- Wait for output, also to ease viewing in waveforms
wait for 10 ns;
-- Test output
if sel = 0 then
assert tb_out0 = tb_in0 report "Wrong out0 output value for selected in0 input" severity error;
else
assert tb_out0 = tb_in1 report "Wrong out0 output value for selected in1 input" severity error;
end if;
end loop;
end loop;
end loop;
report "OK (not actual failure)" severity FAILURE;
wait;
end process;
end tb;
Note that I have used instantiation by entity for mux, to avoid the component declaration, where there actually was an error in the port list; clearly showing why it is a bad idea to write the same twice ;-)
Also not that I have included the IEEE numeric_std package.
It can surely be improved with respect to testing of X values also, but for a simple module like a mux the testing above will give the required coverage.
For more advanced testing, take a look at OSVVM.

Write VHDL code to count frequency of counter clock for MACHX03LF-6900C-CABGA256

I am abit new to VHDL and trying to write a code that count frequency of counter clock.I had counter clock was driven by 12MHz. But I used clock register to slow it down to 45.7Hz by choosing clock register (17).
So what I did was created a reference clock at the same time at higher frequency to accuracy reasons. I used clock register (14) in this case which is 366Hz. I used a reference clock counter as well to say when it is 366HZ which is 1 second. and when it is 137 then reset everything.
I'm not too sure what was wrong with the code in this situation. Any advice would be greatly appreciated.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
--library MACHXO3;
--use MACHXO3.all;
entity testCC2510 is
port(clkin: in std_logic;
reset: in std_logic;
SW4: in std_logic;
LED: out std_logic_vector(7 downto 0);
com: out std_logic;
D2_out: out std_logic_vector(6 downto 0);
D1_out: out std_logic_vector(6 downto 0);
D0_out: out std_logic_vector(6 downto 0);
DP1_out: out std_logic;
DP2_out: out std_logic;
LED_out: out std_logic_vector(7 downto 0));
-- define the pin connections
attribute loc:string;
attribute loc of clkin: signal is "C8";
attribute loc of D0_out: signal is "R13,T14,T12,R11,T11,M11,N10";
attribute loc of D1_out: signal is "R10,P10,T10,R9,T9,N9,M8";
attribute loc of D2_out: signal is "M6,L8,T8,P8,R7,R8,T7";
attribute loc of com: signal is "P7";
attribute loc of reset: signal is "D2";--was K1
attribute loc of SW4: signal is "N1";
attribute loc of DP1_out: signal is "P9";
attribute loc of DP2_out: signal is "P11";
attribute loc of LED_out: signal is "F3,D3,G3,C2,F5,E3,B1,C1";
end;
architecture arch_testCC2510 of testCC2510 is
component SevenSeg
port(LEDin: in integer;
SevSegout: out std_logic_vector);
end component;
signal ref_clk : std_logic; --reference clk
signal ref_counter: integer range 0 to 183; -- reference counter
signal display_0: integer range 0 to 9;
signal display_1: integer range 0 to 9;
signal clkreg : std_logic_vector(31 downto 0);
signal c_clk: std_logic;
signal dig2: std_logic_vector(6 downto 0):="1111111";
signal dig1: std_logic_vector(6 downto 0);
signal dig0: std_logic_vector(6 downto 0);
signal DP1: std_logic:='1';
signal DP2: std_logic:='1';
signal count0: integer range 0 to 9;
signal count1: integer range 0 to 9;
signal oscpin: std_logic;
begin
clk1:process(clkin)
begin
if (clkin'event and clkin = '1') then
clkreg <= clkreg+X"00000001";
end if;
ref_clk <= clkreg (14);
c_clk <= clkreg(17);
oscpin <= clkreg(15);
end process clk1;
--LCD modulation to avoid damage to LCD screen
lcdmod:process(oscpin)
begin
if (oscpin='1') then
D2_out<=dig2;
D1_out<=dig1;
D0_out<=dig0;
DP1_out<=DP1;
DP2_out<=DP2;
else
D2_out<= not dig2;
D1_out<= not dig1;
D0_out<= not dig0;
DP1_out<= not DP1;
DP2_out<= not DP2;
end if;
com<=oscpin;
end process;
DD0:SevenSeg port map(display_0,dig0);
DD1:SevenSeg port map(display_1,dig1);
p_counter: process
begin
wait until rising_edge(c_clk);
if (SW4='1') then
if (((count1=9) and (count0=9)) or reset='0') then
count1<=0;
count0<=0;
elsif(count0=9) then
count1<=count1+1;
count0<=0;
else
count0<=count0+1;
end if;
end if;
--
end process p_counter;
Ref_cnt: process (ref_clk)
begin
wait until rising_edge (ref_clk);
if (ref_clk = 366) then
display_0 <= count0;
display_1 <= count1;
elseif (ref_clk = 367) then --reset count0 and count1
count0 <= 0;
count1 <= 0;
ref_count <= 0;
else
ref_clk = ref_clk + 1;
end if;
end process Ref_cnt;
LED_out <= "00000000";
end arch_testCC2510;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity SevenSeg is
port(LEDin: integer range 0 to 9;
SevSegout: out std_logic_vector(6 downto 0));
end;
architecture SevenSeg_arch of SevenSeg is
begin
process(LEDin)
begin
Lab0:case LEDin is
when 0=>SevSegout<="0000001";
when 1=>SevSegout<="1001111";
when 2=>SevSegout<="0010010";
when 3=>SevSegout<="0000110";
when 4=>SevSegout<="1001100";
when 5=>SevSegout<="0100100";
when 6=>SevSegout<="0100000";
when 7=>SevSegout<="0001111";
when 8=>SevSegout<="0000000";
when 9=>SevSegout<="0000100";
end case Lab0;
end process;
end SevenSeg_arch;

VHDL RS232 Receiver not working correctly with Xilinx ISE

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.

How to initialize std_logic_vector?

I have this code
--RAM module
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.numeric_std.all;
entity RAM is
generic(
address_length, data_length : integer);
port(
addr : in std_logic_vector(address_length-1 downto 0);
dat : inout std_logic_vector(data_length-1 downto 0);
rd, wr, en : in bit);
end entity RAM;
architecture RAM_impl of RAM is
type mem is array(2**address_length-1 downto 0) of std_logic_vector(data_length-1 downto 0);
begin
process(rd, wr, en)is
variable cont : mem;
begin
if(en = '1')then
if(wr = '1' and rd = '0')then
cont(to_integer(unsigned(addr))) := dat;
end if;
if(rd = '1' and wr = '0')then
dat <= cont(to_integer(unsigned(addr)));
end if;
end if;
end process;
end architecture RAM_impl;
--Test module
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.numeric_std.all;
entity Example4RAM is
end entity Example4RAM;
architecture Tester of Example4RAM is
signal rd, wr, en : bit;
signal str : std_logic_vector(15 downto 0);
signal ext : std_logic_vector(7 downto 0);
begin
module : entity work.RAM(RAM_impl)
generic map(
address_length => 16,
data_length => 8)
port map(str, ext, rd, wr, en);
tt : process is
begin
str <= X"0001";
ext <= "00000000";
rd <= '0'; wr <= '1';
wait for 5 ns;
en <= '1';
wait for 5 ns;
rd <= '0'; wr <= '0';
wait for 10 ns;
rd <= '1'; wr <= '0';
end process;
end architecture Tester;
When i run simulation on this RAM module str vector initializes fine but ext vector stays uninitialized. In RAM module str is in vector and ext is inout vector. Is this somehow making problem and does anyone know the solution? (I did change source since yesterday but it doesn't work still)
I added a RAM module and tinkered with the test stimulus slightly (ext is driven to all 'Z's when wr goes invalid (the behavioral model requires no hold over).
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity RAM is
generic (
constant address_length: natural := 16;
constant data_length: natural := 8
);
port (
signal str: in std_logic_vector (address_length-1 downto 0);
signal ext: inout std_logic_vector (data_length-1 downto 0);
signal rd: in BIT;
signal wr: in BIT
);
end entity;
architecture RAM_impl of RAM is
type ram_array is array (natural range address_length-1 downto 0)
of std_logic_vector (data_length-1 downto 0);
signal mem_array: ram_array;
begin
MEMORY:
process (str, ext, rd, wr)
variable addr: natural range 0 to 2**address_length -1 ;
begin
addr := TO_INTEGER(UNSIGNED(str)); -- heed the warnings
if wr = '1' then
mem_array(addr) <= ext;
end if;
if rd = '0' then
ext <= (others => 'Z');
else
ext <= mem_array(addr);
end if;
end process;
end architecture;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- use IEEE.numeric_std.ALL;
entity Example4RAM is
end entity Example4RAM;
architecture Tester of Example4RAM is
signal rd,wr,clk: bit;
signal str: std_logic_vector(15 downto 0);
signal ext: std_logic_vector(7 downto 0);
begin
module:
entity work.RAM(RAM_impl)
generic map (
address_length=>16,
data_length=>8
)
port map (
str,
ext,
rd,
wr
)
;
tt:
process
begin
str<=X"0001";
ext<="00000000";
wait for 5 ns;
rd<='0';wr<='1';
wait for 5 ns;
rd<='0';wr<='0';
ext <= (others => 'Z'); -- ADDED
wait for 10 ns;
rd<='1';wr<='0';
wait for 20 ns; -- ADDED
str <=X"0002"; -- ADDED
wait for 20 ns; -- ADDED
wait;
end process;
end architecture Tester;
The change to the stimulus includes a change to the RAM address showing that reading an uninitialized location returns 'U's (uu on the waveform):
ghdl -a exampleram.vhdl
ghdl -r Example4RAM --wave=Example4RAM.ghw
../../../../libraries/ieee/numeric_std-body.v93:2098:7:#0ms:(assertion warning):
NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0
open *.ghw
Essentially, the process and the RAM drive ext with all 'Z's whenever either one shouldn't be driving a value out. Writing before reading hides the 'U' values from str address X"0001". As you see, if the address is changed to a location that is not initialized, the 'U's show up. Resolution delivers the RAM read data or provides write data to the RAM array on the bidirectional data bus (ext).
(This was done on a Mac with a ghdl mcode version (direct compile, like for Windows, requiring no explicit elaboration), and displayed using GTKWave).
The assertion warning (metavalue detected) comes from the default value assigned to str (all 'U's) at time zero (#0ms).

VHDL Value in case statement randomly gets stuck at a certain value

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.

Resources