vhdl code for keypad interfacing - vhdl

entity hex_kp is
Port ( row : out STD_LOGIC_VECTOR (3 downto 0);
coloumn : in STD_LOGIC_VECTOR (3 downto 0);
sevenseg : out STD_LOGIC_VECTOR (7 downto 0);
ca : out STD_LOGIC_VECTOR (3 downto 0));
end hex_kp;
architecture Behavioral of hex_kp is
begin
ca <="0111";
if(row = "0111") then
if(coloumn = "0111") then sevenseg <= "00000110" ;
elsif (coloumn = "1011") then sevenseg <= "01011011" ;
elsif (coloumn = "1101") then sevenseg <= "01001111" ;
elsif (coloumn = "1110") then sevenseg <= "01110001" ;
end if;
end if;
This my part of my vhdl code for 4x4 keypad scanner for Basys2. It gives an error to "if(row = "0111") then" statement. I couldn't find why help please.

You can use a conditional signal assignment statement:
architecture behave of hex_kp is
begin
ca <="0111";
-- if(row = "0111") then
--
-- if(coloumn = "0111") then sevenseg <= "00000110" ;
-- elsif (coloumn = "1011") then sevenseg <= "01011011" ;
-- elsif (coloumn = "1101") then sevenseg <= "01001111" ;
-- elsif (coloumn = "1110") then sevenseg <= "01110001" ;
-- end if;
-- end if;
sevenseg <= "00000110" when coloumn = "0111" and row = "0111" else
"01011011" when coloumn = "1011" and row = "0111" else
"01001111" when coloumn = "1101" and row = "0111" else
"01110001" when coloumn = "1110" and row = "0111" else
"00000000" when row = "0111";
end architecture behave;
Note that like your Stack Exchange question (vhdl code interfacing keypad with fpga) There are inferred latches on sevenseg caused by using row = "0111" as a condition for assignment.
The above architecture gives the same result as my answer on your Stack Exchange question (vhdl code interfacing keypad with fpga).
Your modified code analyzes, elaborates and the added testbench there simulates the above architecture:
Getting rid of the latches would be as simple as removing the row = "0111" from the final choice in the conditional signal assignment above, or in the the Stack Exchange example using a case statement, providing an else for the enclosing if statement.
The entire code including the testbench and both architectures, predicated on using row as an input:
library ieee;
use ieee.std_logic_1164.all;
entity hex_kp is
port (
row: in std_logic_vector (3 downto 0);
coloumn: in std_logic_vector (3 downto 0); -- 'column 'is mispelled
sevenseg: out std_logic_vector (7 downto 0); -- why is 7 segs 8 long?
ca : out std_logic_vector (3 downto 0)
);
end entity hex_kp;
architecture behavioral of hex_kp is
-- signal row: std_logic_vector(3 downto 0); -- who drive row?
begin -- this was missing
UNLABELLED:
process(row, coloumn) -- was 'column' (didn't match declaration)
begin
ca <="0111";
if row = "0111" then
case coloumn is
when "0111" =>
sevenseg <= "00000110";
when "1011" =>
sevenseg <= "01011011";
when "1101" =>
sevenseg <= "01001111";
when "1110" =>
sevenseg <= "01110001";
when others =>
sevenseg <= (others => '0');
end case;
end if;
end process;
end architecture behavioral;
architecture behave of hex_kp is
begin
ca <="0111";
-- if(row = "0111") then
--
-- if(coloumn = "0111") then sevenseg <= "00000110" ;
-- elsif (coloumn = "1011") then sevenseg <= "01011011" ;
-- elsif (coloumn = "1101") then sevenseg <= "01001111" ;
-- elsif (coloumn = "1110") then sevenseg <= "01110001" ;
-- end if;
-- end if;
sevenseg <= "00000110" when coloumn = "0111" and row = "0111" else
"01011011" when coloumn = "1011" and row = "0111" else
"01001111" when coloumn = "1101" and row = "0111" else
"01110001" when coloumn = "1110" and row = "0111" else
"00000000" when row = "0111";
end architecture behave;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity hex_kp_tb is
end entity;
architecture foo of hex_kp_tb is
signal row: std_logic_vector (3 downto 0);
signal coloumn: std_logic_vector (3 downto 0);
signal sevenseg: std_logic_vector (7 downto 0);
signal ca: std_logic_vector (3 downto 0);
signal count: unsigned (7 downto 0) := (others => '0');
begin
DUT:
entity work.hex_kp
port map (
row => row,
coloumn => coloumn,
sevenseg => sevenseg,
ca => ca
);
STIMULUS:
process
begin
row <= std_logic_vector (count(3 downto 0));
coloumn <= std_logic_vector (count(7 downto 4));
wait for 100 ns;
count <= count + 1;
if count = "11111111" then
wait;
end if;
end process;
end architecture;

You are trying to use an if statement in a concurrent context. However, if statements need to be within a sequential context - for instance a process statement:
process(row, column)
begin
if(row = "0111") then
if(coloumn = "0111") then
sevenseg <= "00000110";
elsif(coloumn = "1011") then
sevenseg <= "01011011";
elsif(coloumn = "1101") then
sevenseg <= "01001111";
elsif(coloumn = "1110") then
sevenseg <= "01110001";
end if;
end if;
end process;
However - note that if you synthesize the above, it will most probably end up giving you a nice set of latches (which you usually don't want), since you are not assigning sevenseg in all possible cases (if row is different from 0111, or if coloumn doesn't match any of the if statements).
To fix it, either 1) use a clocked process, or 2) assign sevenseg to a default value if row and coloumn do not match one of the specified cases. For instance:
process(row, column)
begin
sevenseg <= (others => '0');
if(row = "0111") then
if(coloumn = "0111") then
sevenseg <= "00000110";
elsif(coloumn = "1011") then
sevenseg <= "01011011";
elsif(coloumn = "1101") then
sevenseg <= "01001111";
elsif(coloumn = "1110") then
sevenseg <= "01110001";
end if;
end if;
end process;
I've added the sevenseg <= (others => '0'); which will make sevenseg default to all 0's, if none of the specified cases are hit - if they are, they will override the added line, and set sevenseg to the appropriate value.
An even nicer way to do it is to use a case statement, since that probably better describes what you actually want:
process(row, column)
begin
if(row = "0111") then
case coloumn is
when "0111" =>
sevenseg <= "00000110";
when "1011" =>
sevenseg <= "01011011";
when "1101" =>
sevenseg <= "01001111";
when "1110" =>
sevenseg <= "01110001";
when others =>
sevenseg <= (others => '0');
end case;
else
sevenseg <= (others => '0');
end if;
end process;

Related

When will this variable be assigned?

Here is the code:
process(SRSTN, CSN, WRN,AB) is
begin
if SRSTN = '0' then
WR0 <= (OTHERS => '0');
elsif CSN = '0' then
if WRN = '0' then
case AB(15 downto 0) is
when "0101000100010000" =>
WR0(15 downto 0) <= DB(15 downto 0);
when OTHERS => NULL;
WR0(15 downto 8) <= "00000000" ;
end case;
end if;
end if;
end process;
I'm wondering when will
WR0(15 downto 8) <= "00000000"be executed. Is it assigned everytime except AB equals 0101000100010000?
You have to use signal or variable (inside the process). A possible solution could be:
architecture Beh of Test is
signal temp : std_logic_vector((WR0'LENGTH - 1) downto 0) := (others => '0');
begin
WR0 <= std_logic_vector(temp);
process(SRSTN, CSN, WRN,AB) is
begin
if SRSTN = '0' then
temp <= (OTHERS => '0');
elsif CSN = '0' then
if WRN = '0' then
case AB(15 downto 0) is
when "0101000100010000" =>
temp(15 downto 0) <= DB(15 downto 0);
when OTHERS =>
temp(15 downto 8) <= "00000000" ;
end case;
end if;
end if;
end process;
end Beh;
The WR0 output will be imediatly assigned if one of the inputs SRSTN, CSN, WRN, AB is changing.

VHDL signal does not change value

I am currently trying to implement a state machine with 5 different states. Basically, I want to stay in one state, wait for some time, move on to the next state, wait for a different amount of time, get into the next state etc....
For now I implemented a counter which generates a 1s signal from a 1ms signal that I create in the testbench. I created one process that determines the next state and one that upgrades the current state from the next state. The signal which does not behave as I expected is: next_stateHS which should upgrade stateHS. The code in question is in the process called "hsNextState". What I also can't explain is that the signal "startCounter" behaves as expected. This signal receives a new value in the same else - case as the signal "next_StateHS"
I will now add the code for the state machine and the test bench and a picture of the simulated waveform.
State machine:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity ampel is
port
(
clk : in std_ulogic;
reset : in std_ulogic;
enable : in std_ulogic;
haupt : out std_ulogic_vector(2 downto 0);
neben : out std_ulogic_vector(2 downto 0)
);
end ampel;
architecture ampel_behave of ampel is
--Codierung
-- idle = 000
-- gruen = 001
-- gelb = 010
-- rot = 011
-- rot_gelb = 100
signal stateHS, stateNS : std_ulogic_vector(2 downto 0) := (others => '0');
signal next_stateHS, next_stateNS : std_ulogic_vector(2 downto 0) := (others => '0');
signal startCounter : std_ulogic := '0';
signal counter : unsigned(9 downto 0) := (others => '0'); --für clk = 1ms im Testbench
signal count_seconds : unsigned(3 downto 0) := (others => '0');
begin
counterProcess : process(clk, reset, enable, startCounter)
begin
if enable = '0' or reset = '1' or startCounter = '0' then
counter <= (others => '0');
count_seconds <= (others => '0');
elsif rising_edge(clk) then
if counter < "1111101000" then
counter <= counter + 1;
else
counter <= (others => '0');
count_seconds <= count_seconds + 1;
end if;
end if;
end process counterProcess;
outputProcessHS : process(stateHS, reset, enable)
begin
if enable = '0' or reset = '1' then
haupt <= "000";
else
case (stateHS) is
when "000" =>
haupt <= "000";
when "001" =>
haupt <= "001";
when "010" =>
haupt <= "010";
when "011" =>
haupt <= "011";
when "100" =>
haupt <= "100";
when others =>
haupt <= "000";
end case;
end if;
end process outputProcessHS;
outputProcessNS : process(stateNS, reset, enable)
begin
if enable = '0' or reset = '1' then
neben <= "000";
else
case (stateNS) is
when "000" =>
neben <= "000";
when "001" =>
neben <= "001";
when "010" =>
neben <= "010";
when "011" =>
neben <= "011";
when "100" =>
neben <= "100";
when others =>
neben <= "000";
end case;
end if;
end process outputProcessNS;
hsNextState : process(reset, enable, stateHS, count_seconds)
begin
if enable = '0' or reset = '1' then
next_stateHS <= "000";
else
case (stateHS) is
when "000" =>
next_stateHS <= "001";
startCounter <= '1';
when "001" =>
if count_seconds < "1110" then
next_stateHS <= "001";
else
next_stateHS <= "010";
startCounter <= '0';
end if;
when "010" =>
next_stateHS <= "011";
when "011" =>
next_stateHS <= "100";
when "100" =>
next_stateHS <= "001";
when others =>
next_stateHS <= "000";
end case;
end if;
end process hsNextState;
hsState : process(reset, enable, next_stateHS, count_seconds)
begin
if enable = '0' or reset = '1' then
stateHS <= "000";
else
stateHS <= next_stateHS;
end if;
end process hsState;
-- nsStateProcess : process(reset, enable, stateNS, count_seconds)
-- begin
-- if enable = '0' or reset = '1' then
-- next_stateNS <= idle;
-- else
-- case (stateNS) is
-- when idle =>
-- next_stateNS <= gruen;
-- when gruen =>
-- next_stateNS <= gelb;
-- when gelb =>
-- next_stateNS <= rot;
-- when rot =>
-- next_stateNS <= rot_gelb;
-- when rot_gelb =>
-- next_stateNS <= gruen;
-- when others =>
-- next_stateNS <= idle;
-- end case;
-- end if;
-- stateNS <= next_stateNS;
-- end process nsStateProcess;
end ampel_behave;
Test Bench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity ampel_tb is
end ampel_tb;
architecture test of ampel_tb is
component ampel
port
(
clk : in std_ulogic;
reset : in std_ulogic;
enable : in std_ulogic;
haupt : out std_ulogic_vector(2 downto 0);
neben : out std_ulogic_vector(2 downto 0)
);
end component;
signal clk : std_ulogic := '0';
signal reset : std_ulogic := '0';
signal enable : std_ulogic := '1';
signal haupt, neben : std_ulogic_vector(2 downto 0);
signal count_cycles : unsigned (19 downto 0) := (others => '0');
begin
ampel_1 : ampel port map
(
clk => clk,
reset => reset,
enable => enable,
haupt => haupt,
neben => neben
);
clock_signal : process
begin
if count_cycles < "0011100000000000000" then
clk <= '0';
wait for 500 us;
clk <= '1';
wait for 500 us;
count_cycles <= count_cycles + 1;
else
wait;
end if;
end process clock_signal;
end test;

finite state machine & avoiding metastability

I'm trying to do an electronic dice using fsm as well as avoiding metastability in the process. so I've written this code
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity Dice is
port( clk : in std_logic; -- clock
reset : in std_logic;
key_in : in std_logic; -- key to be preesed to change state
seven_seg : out std_logic_vector (6 downto 0)
);
end Dice;
architecture rulling of Dice is
constant s_one : std_logic_vector (6 downto 0) := "1111001";
constant s_two : std_logic_vector (6 downto 0) := "0100100";
constant s_three : std_logic_vector (6 downto 0) := "0110000";
constant s_four : std_logic_vector (6 downto 0) := "0011001";
constant s_five : std_logic_vector (6 downto 0) := "0010010";
constant s_six : std_logic_vector (6 downto 0) := "0000010";
signal state : std_logic_vector (6 downto 0) := "1111001";
signal Metastable : std_logic;
signal stablee : std_logic;
begin
fsm : process(clk,reset)
begin
if reset = '1' then
--Metastable <= '0';
--stablee <= '0';
--state <= s_one;
seven_seg <= s_one;
else
if rising_edge(clk) then
Metastable <= key_in;
stablee <= Metastable;
case state is
when s_one =>
seven_seg <= s_one; -- writing my OFL (output function logic) what to do inside the state!
if (stablee = '0') then
state <= s_two; -- define my NSL (nest state logic) what conditons there is to change state!
else
state <= s_one;
end if; -- ofl
when s_two =>
seven_seg <= s_two;
if (stablee = '0') then
state <= s_three;
else
state <= s_two;
end if;
when s_three =>
seven_seg <= s_three;
if (stablee = '0') then
state <= s_four;
else
state <= s_three;
end if;
when s_four =>
seven_seg <= s_four;
if (stablee = '0') then
state <= s_five;
else
state <= s_four;
end if;
when s_five =>
seven_seg <= s_five;
if (stablee = '0') then
state <= s_six;
else
state <= s_five;
end if;
when s_six =>
seven_seg <= s_six;
if (stablee = '0') then
state <= s_one;
else
state <= s_six;
end if;
when others =>
state <= s_one;
seven_seg <= s_one;
end case;
end if;
end if;
end process fsm;
end rulling;
for metastability I'm implementing this enter image description here
My question is when i press the debounced button witch is low active for the key_in nothing happens! but when I press the reset button and press key_in its move throw the states. Im really new to VHDL so any help appreciated.

VHDL uart which send 16 chars string

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

Bitsequence detector counter doesn't work (VHDL)

I build a 4 bit sequence detector with a 16-bit input.
I wanna now how often the sequence appears in the 16 bits.
For that I use this code:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY seqdec IS
PORT ( X: IN std_logic_vector(15 DOWNTO 0);
CLK: IN std_logic;
RESET:IN std_logic;
LOAD: IN std_logic;
Y: OUT std_logic);
END seqdec;
ARCHITECTURE SEQ OF seqdec IS
TYPE statetype IS (s0, s1, s2, s3, s4);
SIGNAL state, next_state: statetype;
SIGNAL counter: std_logic_vector(3 DOWNTO 0) :="0000" ;
SIGNAL temp: std_logic_vector(15 DOWNTO 0);
SIGNAL so: std_logic;
BEGIN
STATE_AKT: PROCESS (CLK, RESET)
BEGIN
IF RESET = '1' THEN
state <= s0 ;
counter <= (OTHERS => '0') ;
ELSIF CLK = '1' AND CLK'event THEN
state <= next_state ;
END IF;
END PROCESS STATE_AKT;
PISO: PROCESS (CLK, LOAD, X)
BEGIN
IF (LOAD = '1') THEN
temp(15 DOWNTO 0) <= X(15 DOWNTO 0);
ELSIF (CLK'event and CLK='1') THEN
so <= temp(15) ;
temp(15 DOWNTO 1) <= temp(14 DOWNTO 0);
temp(0) <= '0';
END IF;
END PROCESS PISO;
STATE_CAL: PROCESS (so,state)
BEGIN
CASE state IS
WHEN s0 => IF so = '0' THEN next_state <= s0 ;
ELSE next_state <= s1 ;
END IF;
WHEN s1 => IF so = '0' THEN next_state <= s1;
ELSE next_state <= s2 ;
END IF;
WHEN s2 => IF so = '0' THEN next_state <= s3 ;
ELSE next_state <= s2 ;
END IF;
WHEN s3 => IF so = '0' THEN next_state <= s0 ;
ELSE next_state <= s4 ;
END IF;
WHEN s4 => IF so = '0' THEN next_state <= s0;
ELSE next_state <= s2 ;
END IF;
WHEN OTHERS => NULL;
END CASE;
END PROCESS STATE_CAL;
STATE_Y: PROCESS (state)
BEGIN
CASE state IS
WHEN s4 =>
Y <= '1';
counter <= counter + '1';
WHEN OTHERS => Y <= '0' ;
END CASE;
END PROCESS STATE_Y;
END SEQ;
But neither my counter reset nor my incrementation of counter is working.
The rest is working perfect and fine.
Has somebody a hint or an idea for me?
The programm is now working fine in ModelSim, but I struggle with getting it on the board.
I simulated it several times in ModelSim, with different parameters and it works fine, so the functional part is fine.
My code looks now this way:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY seqdec IS
PORT ( X: IN std_logic_vector(15 DOWNTO 0);
CLK: IN std_logic;
RESET: IN std_logic;
LOAD: IN std_logic;
DIGIT: OUT std_logic_vector(6 DOWNTO 0) := "1111110";
COUT: OUT std_logic_vector(2 DOWNTO 0);
Y: OUT std_logic);
END seqdec;
ARCHITECTURE SEQ OF seqdec IS
TYPE statetype IS (s0, s1, s2, s3, s4);
SIGNAL state: statetype;
SIGNAL next_state: statetype:=s0;
SIGNAL counter: std_logic_vector(2 DOWNTO 0) :="000" ;
SIGNAL temp: std_logic_vector(15 DOWNTO 0);
SIGNAL so: std_logic := 'U';
-------------------Aktualisierung des Zustandes--------------------------------
BEGIN
STATE_AKT: PROCESS (CLK, RESET)
BEGIN
IF RESET = '1' THEN
state <= s0;
ELSIF CLK = '1' AND CLK'event THEN
state <= next_state ;
END IF;
END PROCESS STATE_AKT;
---------------------Counter---------------------------------------------------
COUNT: PROCESS (state, RESET)
BEGIN
IF (RESET = '1') THEN
counter <= (OTHERS => '0');
ELSIF (state = s4) THEN
counter <= counter + '1';
COUT <= counter;
END IF;
END PROCESS COUNT;
-------------------PiSo für die Eingabe des zu Prüfenden Vektors---------------
PISO: PROCESS (CLK, LOAD, X)
BEGIN
IF (LOAD = '1') THEN
temp(15 DOWNTO 0) <= X(15 DOWNTO 0);
ELSIF (CLK'event and CLK='1') THEN
so <= temp(15);
temp(15 DOWNTO 1) <= temp(14 DOWNTO 0);
temp(0) <= '0';
END IF;
END PROCESS PISO;
-------------------Zustandsabfrage und Berechnung------------------------------
STATE_CAL: PROCESS (so,state)
BEGIN
CASE state IS
WHEN s0 => IF so = '0' THEN next_state <= s0 ;
ELSIF (so = '1') THEN next_state <= s1 ;
END IF;
WHEN s1 => IF so = '0' THEN next_state <= s1;
ELSIF (so = '1') THEN next_state <= s2 ;
END IF;
WHEN s2 => IF so = '0' THEN next_state <= s3 ;
ELSIF (so = '1') THEN next_state <= s2 ;
END IF;
WHEN s3 => IF so = '0' THEN next_state <= s0 ;
ELSIF (so = '1') THEN next_state <= s4 ;
END IF;
WHEN s4 => IF so = '0' THEN next_state <= s0;
ELSIF (so = '1') THEN next_state <= s2 ;
END IF;
WHEN OTHERS => NULL;
END CASE;
END PROCESS STATE_CAL;
-------------------Ausgang-----------------------------------------------------
STATE_Y: PROCESS (state)
BEGIN
CASE state IS
WHEN s4 =>
Y <= '1';
WHEN OTHERS => Y <= '0' ;
END CASE;
END PROCESS STATE_Y;
-------------------7 Segment---------------------------------------------------
SEVEN_SEG: PROCESS (counter, CLK)
BEGIN
IF (RESET = '1') THEN
DIGIT <= "1111110";
END IF;
CASE counter IS
WHEN "000" => DIGIT <= "1111110";
WHEN "001" => DIGIT <= "0110000";
WHEN "010" => DIGIT <= "1101101";
WHEN "011" => DIGIT <= "1111001";
WHEN "100" => DIGIT <= "0110011";
WHEN "101" => DIGIT <= "1011011";
WHEN OTHERS => NULL;
END CASE;
END PROCESS SEVEN_SEG;
END SEQ;
When i put it on the board the 7-segment will show a "3".
I would assume, as the functional part seems to be good,that it has to do somethink with the timings, but i can't find any solution to it. If some experience VHDL-programmer could give me a new hint that would be great.
Best regards
Adrian

Resources