UART communication between computer and BASYS 3 FPGA - vhdl

I have a project in which I need to send data from a Windows 10 computer to a BASYS 3 board(ARTIX7 FPGA). I use UART to do so. The data to send is entered in a PuTTY serial console.
For testing purposes, I decided to display the received data using 8 LEDs on the board.
I am using Vivado 2016.4.
The problem I have is that the data I get on the LEDs is totally different from what it should be. I suppose it's a problem of synchronization between PuTTY's baud rate and my VHDL module.
Please find hereafter the .vhd file and the .xdc file of this project :
The .vhd is based on a finite state machine (FSM), and there are two signals allowing the synchronization :
tick_UART : it ticks every 10417 clock period. Since the clock period is 10 ns, tick_UART rises 9600 times per second (I intend a use at 9600 bauds).
double_tick_UART : twice the frequency of tick_UART, used to sample the bits in the middle.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity UART_RX is
Port ( RxD : in STD_LOGIC;
clk : in STD_LOGIC;
RAZ : in STD_LOGIC;
data_out : out STD_LOGIC_VECTOR (7 downto 0));
end UART_RX;
architecture Behavioral of UART_RX is
signal tick_UART : STD_LOGIC; -- Signal "top" passage d'un état à l'autre selon vitesse connexion série
signal double_tick_UART : STD_LOGIC; -- Signal précédent, fréquence * 2
signal compteur_tick_UART : integer range 0 to 10420; -- Compteur pour tick_UART
signal double_compteur_tick_UART : integer range 0 to 5210; -- Compteur pour demi-périodes
type state_type is (idle, start, demiStart, b0, b1, b2, b3, b4, b5, b6, b7, stop); -- Etats de la FSM
signal state :state_type := idle; -- Etat par défaut
signal RAZ_tick_UART : STD_LOGIC; -- RAZ du signal tick_UART;
begin
process(clk, RAZ, state, RAZ_tick_UART) -- Compteur classique (tick_UART)
begin
if (raz='1') or (state = idle) or (RAZ_tick_UART = '1') then
compteur_tick_UART <= 0;
tick_UART <= '0';
elsif clk = '1' and clk'event then
if compteur_tick_UART = 10417 then
tick_UART <= '1';
compteur_tick_UART <= 0;
else
compteur_tick_UART <= compteur_tick_UART + 1;
tick_UART <= '0';
end if;
end if;
end process;
process(clk, RAZ, state) -- Compteur demi-périodes (double_tick_UART car fréquence double)
begin
if (raz='1') or (state = idle) then
double_compteur_tick_UART <= 0;
double_tick_UART <= '0';
elsif clk = '1' and clk'event then
if double_compteur_tick_UART = 5209 then
double_tick_UART <= '1';
double_compteur_tick_UART <= 0;
else
double_compteur_tick_UART <= double_compteur_tick_UART + 1;
double_tick_UART <= '0';
end if;
end if;
end process;
fsm:process(clk, RAZ) -- Machine à état
begin
if (RAZ = '1') then
state <= idle;
data_out <= "00000000";
RAZ_tick_UART <= '1';
elsif clk = '1' and clk'event then
case state is
when idle => if RxD = '0' then -- Si front descendant de RxD et en idle
state <= start;
RAZ_tick_UART <= '1';
end if;
when start => if double_tick_UART = '1' then
state <= demiStart;
RAZ_tick_UART <= '0';
end if;
data_out <= "00000000";
when demiStart => if tick_UART = '1' then
state <= b0;
RAZ_tick_UART <= '0';
end if;
data_out(0) <= RxD; -- Acquisition bit 0
when b0 => if tick_UART = '1' then
state <= b1;
end if;
data_out(1) <= RxD; -- Acquisition bit 1
when b1 => if tick_UART = '1' then
state <= b2;
end if;
data_out(2) <= RxD; -- Acquisition bit 2
when b2 => if tick_UART = '1' then
state <= b3;
end if;
data_out(3) <= RxD; -- Acquisition bit 3
when b3 => if tick_UART = '1' then
state <= b4;
end if;
data_out(4) <= RxD; -- Acquisition bit 4
when b4 => if tick_UART = '1' then
state <= b5;
end if;
data_out(5) <= RxD; -- Acquisition bit 5
when b5 => if tick_UART = '1' then
state <= b6;
end if;
data_out(6) <= RxD; -- Acquisition bit 6
when b6 => if tick_UART = '1' then
state <= b7;
end if;
data_out(7) <= RxD; -- Acquisition bit 7
when b7 => if tick_UART = '1' then
state <= stop;
end if;
when stop => if tick_UART = '1' then
state <= idle; -- Renvoi en idle
end if;
end case;
end if;
end process;
end Behavioral;
XDC file :
## Clock signal
set_property PACKAGE_PIN W5 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]
## LEDs
set_property PACKAGE_PIN U16 [get_ports data_out[0]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[0]]
set_property PACKAGE_PIN E19 [get_ports data_out[1]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[1]]
set_property PACKAGE_PIN U19 [get_ports data_out[2]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[2]]
set_property PACKAGE_PIN V19 [get_ports data_out[3]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[3]]
set_property PACKAGE_PIN W18 [get_ports data_out[4]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[4]]
set_property PACKAGE_PIN U15 [get_ports data_out[5]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[5]]
set_property PACKAGE_PIN U14 [get_ports data_out[6]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[6]]
set_property PACKAGE_PIN V14 [get_ports data_out[7]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[7]]
##Buttons
set_property PACKAGE_PIN T18 [get_ports RAZ]
set_property IOSTANDARD LVCMOS33 [get_ports RAZ]
##USB-RS232 Interface
set_property PACKAGE_PIN B18 [get_ports RxD]
set_property IOSTANDARD LVCMOS33 [get_ports RxD]
Do you spot any mistake ?
I also tried to use another .vhd (not written by myself and supposed to work).
This didn't work either: https://www.nandland.com/vhdl/modules/module-uart-serial-port-rs232.html
(I well modified the generic g_CLKS_PER_BIT in accordance with my clock & baud rate)
The issue could come from PuTTY but I've set a baud rate of 9600 baud, 8 data bits, 1 stop bit, no parity, so I don't see what could be wrong !
If you have further ideas / comments, because I can't find what's wrong !
Thank you very much !
EDIT March 16, 2017 :
Following #J.H.Bonarius & #user1155120 recommandations, I added a 2 stage flip flop synchronizer to synchronize the RxD incoming signal with my 100 MHz clock domain.
I also modified modified some asynchronous resets.
Nevertheless, I still have the same issue (LEDs not corresponding to what's sent via PuTTY).
Find hearafter the new .vhd code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity UART_RX is
Port ( RxD_in : in STD_LOGIC;
clk : in STD_LOGIC;
RAZ : in STD_LOGIC;
data_out : out STD_LOGIC_VECTOR (7 downto 0));
end UART_RX;
architecture Behavioral of UART_RX is
signal tick_UART : STD_LOGIC; -- Signal "top" passage d'un état à l'autre selon vitesse connexion série
signal double_tick_UART : STD_LOGIC; -- Signal précédent, fréquence * 2
signal compteur_tick_UART : integer range 0 to 10420; -- Compteur pour tick_UART
signal double_compteur_tick_UART : integer range 0 to 5210; -- Compteur pour demi-périodes
type state_type is (idle, start, demiStart, b0, b1, b2, b3, b4, b5, b6, b7); -- Etats de la FSM
signal state :state_type := idle; -- Etat par défaut
signal RAZ_tick_UART : STD_LOGIC; -- RAZ du signal tick_UART;
signal RxD_temp : STD_LOGIC; -- RxD provisoire entre deux FF
signal RxD_sync : STD_LOGIC; -- RxD synchronisé sur l'horloge
begin
D_flip_flop_1:process(clk) -- Clock crossing
begin
if clk = '1' and clk'event then
RxD_temp <= RxD_in;
end if;
end process;
D_flip_flop_2:process(clk) -- Clock crossing
begin
if clk = '1' and clk'event then
RxD_sync <= RxD_temp;
end if;
end process;
tickUART:process(clk, RAZ, state, RAZ_tick_UART) -- Compteur classique (tick_UART)
begin
if clk = '1' and clk'event then
if (RAZ='1') or (state = idle) or (RAZ_tick_UART = '1') then
compteur_tick_UART <= 0;
tick_UART <= '0';
elsif compteur_tick_UART = 10417 then
tick_UART <= '1';
compteur_tick_UART <= 0;
else
compteur_tick_UART <= compteur_tick_UART + 1;
tick_UART <= '0';
end if;
end if;
end process;
doubleTickUART:process(clk, RAZ, state) -- Compteur demi-périodes (double_tick_UART car fréquence double)
begin
if clk = '1' and clk'event then
if (RAZ='1') or (state = idle) then
double_compteur_tick_UART <= 0;
double_tick_UART <= '0';
elsif double_compteur_tick_UART = 5209 then
double_tick_UART <= '1';
double_compteur_tick_UART <= 0;
else
double_compteur_tick_UART <= double_compteur_tick_UART + 1;
double_tick_UART <= '0';
end if;
end if;
end process;
fsm:process(clk, RAZ) -- Machine à état
begin
if (RAZ = '1') then
state <= idle;
data_out <= "00000000";
RAZ_tick_UART <= '1';
elsif clk = '1' and clk'event then
case state is
when idle => if RxD_sync = '0' then -- Si front descendant de RxD (= bit de start) et en idle
state <= start;
RAZ_tick_UART <= '1';
end if;
when start =>if double_tick_UART = '1' then -- Demi période écoulée (pour échantillonage)
state <= demiStart;
RAZ_tick_UART <= '0'; -- Le compteur tick_UART commence à compter
end if;
data_out <= "00000000"; -- Reset des anciennes données
when demiStart => if tick_UART = '1' then
state <= b0;
RAZ_tick_UART <= '0';
end if;
data_out(0) <= RxD_sync; -- Acquisition bit 0
when b0 => if tick_UART = '1' then
state <= b1;
end if;
data_out(1) <= RxD_sync; -- Acquisition bit 1
when b1 => if tick_UART = '1' then
state <= b2;
end if;
data_out(2) <= RxD_sync; -- Acquisition bit 2
when b2 => if tick_UART = '1' then
state <= b3;
end if;
data_out(3) <= RxD_sync; -- Acquisition bit 3
when b3 => if tick_UART = '1' then
state <= b4;
end if;
data_out(4) <= RxD_sync; -- Acquisition bit 4
when b4 => if tick_UART = '1' then
state <= b5;
end if;
data_out(5) <= RxD_sync; -- Acquisition bit 5
when b5 => if tick_UART = '1' then
state <= b6;
end if;
data_out(6) <= RxD_sync; -- Acquisition bit 6
when b6 => if tick_UART = '1' then
state <= b7;
end if;
data_out(7) <= RxD_sync; -- Acquisition bit 7
when b7 => if tick_UART = '1' then
state <= idle; -- state <= stop;
end if;
end case;
end if;
end process;
end Behavioral;
Do you have any idea about the origin of my problem ?
Thank you very much !

First if (raz='1') or (state = idle) or (RAZ_tick_UART = '1') then don't put so many things in an asynchronous reset input. Actually: don't use asynchronous resets at all. They will introduce logic into the clock path.
Second thing: it's probably a good idea to put some clock domain synchronizations on your UART RxD. Just a two stage synchronizer. Else when idle => if RxD = '0' then will be affected by glitches.

Related

Is it bad design to have additional logic on your reset?

I have always been told it is bad design to have anything but a reset in your reset clause. For instance, see the two circuits below:
process (CLK)
begin
if rising_edge(CLK) then
if (RST = '1') then
Q0 <= '0';
else
if (CLR = '1') then
Q0 <= '0';
else
Q0 <= D;
end if;
end if;
end if;
end process;
process (CLK)
begin
if rising_edge(CLK) then
if (RST = '1' or CLR = '1') then
Q1 <= '0';
else
Q1 <= D;
end if;
end if;
end process;
I've been told the first is more correct, but...
Ive tested them and they appear to be equivalent logically:
They appear equivalent in synthesis and implementation (in fact Vivado synthesizes them as the second case more accurately):
So where is the disconnect? Did older tools not synthesize this properly? Is it actually bad design to do the second case?
The accepted answer below made me wonder how it would look if the resets were asynchronous:
process (CLK, RST)
begin
if (RST = '1') then
Q0 <= '0';
else
if rising_edge(CLK) then
if (CLR = '1') then
Q0 <= '0';
else
Q0 <= D;
end if;
end if;
end if;
end process;
process (CLK, RST, CLR)
begin
if (RST = '1' or CLR = '1') then
Q1 <= '0';
else
if rising_edge(CLK) then
Q1 <= D;
end if;
end if;
end process;
Synthesis results are very different for the asynchronous case. This makes more sense now from a timing perspective as now you'd have an asynchronous signal running around, thank you.
Minimum reproducible example (synchronous case):
top.vhd
library IEEE;
use IEEE.std_logic_1164.all;
entity top is
port (
CLK : in std_logic;
RST : in std_logic;
CLR : in std_logic;
D : in std_logic;
Q0 : out std_logic;
Q1 : out std_logic
);
end top;
architecture rtl of top is
begin
process (CLK)
begin
if rising_edge(CLK) then
if (RST = '1') then
Q0 <= '0';
else
if (CLR = '1') then
Q0 <= '0';
else
Q0 <= D;
end if;
end if;
end if;
end process;
process (CLK)
begin
if rising_edge(CLK) then
if (RST = '1' or CLR = '1') then
Q1 <= '0';
else
Q1 <= D;
end if;
end if;
end process;
end architecture rtl;
tb.vhd
library IEEE;
use IEEE.std_logic_1164.all;
library std;
use std.env.all;
entity tb is
end entity tb;
architecture behav of tb is
constant CLK_FREQ : real := 100.0e6;
constant CLK_HALF_P : time := (((1.0/CLK_FREQ)*10.0e8)/2.0) * 1 ns;
signal clk : std_logic;
signal rst : std_logic;
signal clr : std_logic;
signal d : std_logic;
signal q0 : std_logic;
signal q1 : std_logic;
begin
dut : entity work.top(rtl)
port map (
CLK => clk,
RST => rst,
CLR => clr,
D => d,
Q0 => q0,
Q1 => q1
);
sysClkProc : process ---------------------------------------------------------
begin
clk <= '1';
wait for CLK_HALF_P;
clk <= '0';
wait for CLK_HALF_P;
end process sysClkProc; ------------------------------------------------------
stimulusProc : process -------------------------------------------------------
begin
report ("Starting Simulation");
rst <= '1';
d <= '0';
clr <= '0';
wait for 100 ns;
rst <= '0';
for i in 1 to 10 loop
wait until rising_edge(clk);
end loop;
d <= '1';
for i in 1 to 10 loop
wait until rising_edge(clk);
end loop;
d <= '0';
for i in 1 to 10 loop
wait until rising_edge(clk);
end loop;
d <= '1';
for i in 1 to 5 loop
wait until rising_edge(clk);
end loop;
clr <= '1';
for i in 1 to 5 loop
wait until rising_edge(clk);
end loop;
clr <= '0';
for i in 1 to 5 loop
wait until rising_edge(clk);
end loop;
d <= '0';
wait for 100 ns;
finish(0);
end process stimulusProc; ----------------------------------------------------
end architecture behav;
constr.xdc - Target Nexys A7-100T (xc7a100tcsg324-1)
create_clock -period 10.000 -name sys_clock [get_ports CLK]
set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS18} [get_ports CLK]
set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS18} [get_ports RST]
set_property -dict {PACKAGE_PIN L16 IOSTANDARD LVCMOS18} [get_ports CLR]
set_property -dict {PACKAGE_PIN M13 IOSTANDARD LVCMOS18} [get_ports D ]
set_property -dict {PACKAGE_PIN H17 IOSTANDARD LVCMOS18} [get_ports Q0 ]
set_property -dict {PACKAGE_PIN K15 IOSTANDARD LVCMOS18} [get_ports Q1 ]
There are 2 different concepts: Asynchronous reset and synchronous reset. You are working with synchronous reset (getting active only at clock edges), which does not have any restrictions. So both versions of your design are ok, I would chose the first solution with "or", because it is easier to read. At asynchronous reset you do not have so much freedom, at many places in the design flow (static timing analysis, synthesis, layout) the tools do not like logic in the reset path, because it makes the situation more complicated. But of course, if logic in the asynchronous is really needed, you can implement it but you must live with more work effort.
It appears that you are using Xilinx tools and writing VHDL that describes what Xilinx calls an FDRE (D Flip-Flop with Clock Enable and Synchronous Reset).
You have two signals (RST and CLR) that can cause the FDRE to reset. Since the FDRE has only one reset (R) input then RST and CLR must be combined using combinatorial logic before being sent to the FDRE. Xilinx devices use a component called a LUT to perform combinatorial logic.
So, if you are trying to write VHDL that more directly
describes the hardware, then you should write:
R <= RST or CLR; --maps to a LUT
process(C) --maps to a FDRE
begin
if rising_edge(C) then
if (R = '1') then
Q <= '0';
else
Q <= D;
end if;
end if;
end process;

vhdl invalid memory access (dangling accesses or stack size too small)

I'm trying to recreate a traffic light. And as it seems I have some kind of loop in my program since this message comes up whenever I run my testbench. I know for a fact that the loop in the testbench was okay, at least not the main problem, since once I commented it out, the error message came up again. Once I commented out the ampel (traffic light), the error wasn't there anymore. So my guess is that something is wrong with my ampel entity, but I can't find what it is.
Here the code:
library ieee;
use ieee.std_logic_1164.all;
entity ampel is
port (
clk, reset : in std_logic;
rot, gelb, gruen : out std_logic_vector(3 downto 0)
);
end ampel;
architecture rtl of ampel is
type t_zustand is (a,b,c,d,e,f,g,h);
signal zustand : t_zustand;
signal timer : integer;
begin
rot <= "1111";
process is
begin
wait on clk until clk = '1';
timer <= timer + 1;
if reset = '0' then
zustand <= a;
rot <= "1111";
gelb <= "0000";
gruen <= "0000";
timer <= 2;
else
case zustand is
when a =>
rot <= "1111";
gelb <= "0000";
gruen <= "0000";
if timer = 5 then
zustand <= b;
end if;
when b =>
rot <= "0101";
gelb <= "1010";
gruen <= "0000";
if timer = 10 then
zustand <= c;
end if;
when c =>
rot <= "0101";
gelb <= "0000";
gruen <= "1010";
if timer = 40 then
zustand <= d;
end if;
when d =>
rot <= "0101";
gelb <= "1010";
gruen <= "0000";
if timer = 45 then
zustand <= e;
end if;
when e =>
rot <= "1111";
gelb <= "0000";
gruen <= "0000";
if timer = 50 then
zustand <= b;
end if;
when f =>
rot <= "1010";
gelb <= "0101";
gruen <= "0000";
if timer = 55 then
zustand <= b;
end if;
when g =>
rot <= "1010";
gelb <= "0000";
gruen <= "0101";
if timer = 85 then
zustand <= b;
end if;
when h =>
rot <= "1010";
gelb <= "0101";
gruen <= "0000";
if timer = 90 then
zustand <= b;
end if;
end case;
end if;
end process;
end rtl ;
The testbench:
library ieee;
use ieee.std_logic_1164.all;
entity ampel_tb is
end ampel_tb;
architecture testbench of ampel_tb is
component ampel is
port(
clk, reset : in std_logic;
rot, gelb, gruen : out std_logic_vector(3 downto 0)
);
end component;
signal clk, reset : std_logic;
signal rot, gelb, gruen : std_logic_vector(3 downto 0);
begin
ampel0: ampel port map(clk => clk, reset => reset, rot => rot, gelb => gelb, gruen => gruen);
process begin
reset <= '0';
clk <= '0';
wait for 500 ms;
clk <= '1';
wait for 500 ms;
reset <= '1';
clk <= '0';
wait for 500 ms;
for I in 0 to 180 loop
clk <= '1';
wait for 500 ms;
clk <= '0';
wait for 500 ms;
end loop;
assert false report "End of test";
wait;
end process;
end testbench;

Why is my seven segment display only showing 0's?

I am trying to write code for my Nexys 4 DDR to display 4 digits which are chosen from a keypad.
They keypad is fed into port JA and then decoded and displayed on the seven segment displays. The numbers are supposed to shift left after a new key is pressed.
As of now, my code is generating a bitstream but the displays only show 0's and the reset button seems to be functioning. I'm not sure if this is a clock issue or an inconsistency somewhere in my code?
I've attached my design sources and my constraint file.
Thanks.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.std_logic_unsigned.all;
entity PmodKYPD_Nexsy4 is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
JA : inout STD_LOGIC_VECTOR (7 downto 0); -- PmodKYPD connected to Pmod JA
an : out STD_LOGIC_VECTOR (7 downto 0); -- Controls which position of the 8 seven segment displays to display
seg: out STD_LOGIC_VECTOR (6 downto 0)); -- digit to display on seven segment display
end PmodKYPD_Nexsy4;
architecture Behavioral of PmodKYPD_Nexsy4 is
component DisplayController is
Port ( DispVal : in STD_LOGIC_VECTOR (15 downto 0);
Selector : in STD_LOGIC_VECTOR (1 downto 0);
anode : out STD_LOGIC_VECTOR (7 downto 0);
segOut : out STD_LOGIC_VECTOR (6 downto 0));
end component;
signal Decode: STD_LOGIC_VECTOR (3 downto 0);
signal RegLast : STD_LOGIC_VECTOR (15 downto 0);
signal refresh : STD_LOGIC_VECTOR (19 downto 0);
signal LEDAct : std_logic_vector(1 downto 0);
signal Row : STD_LOGIC_VECTOR (3 downto 0);
signal Col : STD_LOGIC_VECTOR (3 downto 0);
signal sclk :STD_LOGIC_VECTOR(19 downto 0);
signal DecodeOut : STD_LOGIC_VECTOR (3 downto 0);
signal Reg : unsigned(15 downto 0) := (others => '0');
begin
Row <= JA(7 downto 4);
Col <= JA(3 downto 0);
process(clk,reset)
begin
if(reset='1') then
refresh <= (others => '0');
elsif(rising_edge(clk)) then
refresh <= refresh + 1;
end if;
end process;
LEDAct <= refresh(19 downto 18);
process(clk)
begin
if clk'event and clk = '1' then
-- 1ms
if sclk = "00011000011010100000" then
--C1
Col<= "0111";
sclk <= sclk+1;
-- check row pins
elsif sclk = "00011000011010101000" then
--R1
if Row = "0111" then
DecodeOut <= "0001"; --1
--R2
elsif Row = "1011" then
DecodeOut <= "0100"; --4
--R3
elsif Row = "1101" then
DecodeOut <= "0111"; --7
--R4
elsif Row = "1110" then
DecodeOut <= "1111"; --F (mod from "0000"; --0)
end if;
sclk <= sclk+1;
-- 2ms
elsif sclk = "00110000110101000000" then
--C2
Col<= "1011";
sclk <= sclk+1;
-- check row pins
elsif sclk = "00110000110101001000" then
--R1
if Row = "0111" then
DecodeOut <= "0010"; --2
--R2
elsif Row = "1011" then
DecodeOut <= "0101"; --5
--R3
elsif Row = "1101" then
DecodeOut <= "1000"; --8
--R4
elsif Row = "1110" then
DecodeOut <= "0000"; --0 (mod from "1111"; --F)
end if;
sclk <= sclk+1;
--3ms
elsif sclk = "01001001001111100000" then
--C3
Col<= "1101";
sclk <= sclk+1;
-- check row pins
elsif sclk = "01001001001111101000" then
--R1
if Row = "0111" then
DecodeOut <= "0011"; --3
--R2
elsif Row = "1011" then
DecodeOut <= "0110"; --6
--R3
elsif Row = "1101" then
DecodeOut <= "1001"; --9
--R4
elsif Row = "1110" then
DecodeOut <= "1110"; --E
end if;
sclk <= sclk+1;
--4ms
elsif sclk = "01100001101010000000" then
--C4
Col<= "1110";
sclk <= sclk+1;
-- check row pins
elsif sclk = "01100001101010001000" then
--R1
if Row = "0111" then
DecodeOut <= "1010"; --A
--R2
elsif Row = "1011" then
DecodeOut <= "1011"; --B
--R3
elsif Row = "1101" then
DecodeOut <= "1100"; --C
--R4
elsif Row = "1110" then
DecodeOut <= "1101"; --D
end if;
sclk <= "00000000000000000000";
else
sclk <= sclk+1;
end if;
end if;
end process;
SHIFT_REG : process(clk)
variable tmp : unsigned(15 downto 0);
begin
if clk'event and clk = '1' then
tmp := Reg;
tmp := tmp sll 4;
tmp(3 downto 0) := unsigned(DecodeOut);
Reg <= tmp;
end if;
end process;
C0: DisplayController port map (DispVal=>STD_LOGIC_VECTOR(Reg), Selector=>LEDAct, anode=>an, segOut=>seg );
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity DisplayController is
Port ( DispVal : in STD_LOGIC_VECTOR (15 downto 0);
Selector : in STD_LOGIC_VECTOR (1 downto 0);
anode : out STD_LOGIC_VECTOR (7 downto 0);
segOut : out STD_LOGIC_VECTOR (6 downto 0));
end DisplayController;
architecture Behavioral of DisplayController is
begin
process(Selector)
begin
case Selector is
when "00" =>
anode <= "11110111";
-- activate LED1 and Deactivate LED2, LED3, LED4
-- the first hex digit of the 16-bit number
case DispVal(15 downto 12) is -- active low to display segment
when "0000" => SegOut <= "1000000"; --0
when "0001" => SegOut <= "1111001"; --1
when "0010" => SegOut <= "0100100"; --2
when "0011" => SegOut <= "0110000"; --3
when "0100" => SegOut <= "0011001"; --4
when "0101" => SegOut <= "0010010"; --5
when "0110" => SegOut <= "0000010"; --6
when "0111" => SegOut <= "1111000"; --7
when "1000" => SegOut <= "0000000"; --8
when "1001" => SegOut <= "0010000"; --9
when "1010" => SegOut <= "0001000"; --A
when "1011" => SegOut <= "0000011"; --B
when "1100" => SegOut <= "1000110"; --C
when "1101" => SegOut <= "0100001"; --D
when "1110" => SegOut <= "0000110"; --E
when "1111" => SegOut <= "0001110"; --F
when others => Segout <= "0111111";
end case;
when "01" =>
anode <= "11111011";
-- activate LED2 and Deactivate LED1, LED3, LED4
-- the second hex digit of the 16-bit number
case DispVal(11 downto 8) is -- active low to display segment
when "0000" => SegOut <= "1000000"; --0
when "0001" => SegOut <= "1111001"; --1
when "0010" => SegOut <= "0100100"; --2
when "0011" => SegOut <= "0110000"; --3
when "0100" => SegOut <= "0011001"; --4
when "0101" => SegOut <= "0010010"; --5
when "0110" => SegOut <= "0000010"; --6
when "0111" => SegOut <= "1111000"; --7
when "1000" => SegOut <= "0000000"; --8
when "1001" => SegOut <= "0010000"; --9
when "1010" => SegOut <= "0001000"; --A
when "1011" => SegOut <= "0000011"; --B
when "1100" => SegOut <= "1000110"; --C
when "1101" => SegOut <= "0100001"; --D
when "1110" => SegOut <= "0000110"; --E
when "1111" => SegOut <= "0001110"; --F
when others => Segout <= "0111111";
end case;
when "10" =>
anode <= "11111101";
-- activate LED3 and Deactivate LED2, LED1, LED4
-- the third hex digit of the 16-bit number
case DispVal(7 downto 4) is -- active low to display segment
when "0000" => SegOut <= "1000000"; --0
when "0001" => SegOut <= "1111001"; --1
when "0010" => SegOut <= "0100100"; --2
when "0011" => SegOut <= "0110000"; --3
when "0100" => SegOut <= "0011001"; --4
when "0101" => SegOut <= "0010010"; --5
when "0110" => SegOut <= "0000010"; --6
when "0111" => SegOut <= "1111000"; --7
when "1000" => SegOut <= "0000000"; --8
when "1001" => SegOut <= "0010000"; --9
when "1010" => SegOut <= "0001000"; --A
when "1011" => SegOut <= "0000011"; --B
when "1100" => SegOut <= "1000110"; --C
when "1101" => SegOut <= "0100001"; --D
when "1110" => SegOut <= "0000110"; --E
when "1111" => SegOut <= "0001110"; --F
when others => Segout <= "0111111";
end case;
when "11" =>
anode <= "11111110";
-- activate LED4 and Deactivate LED2, LED3, LED1
-- the fourth hex digit of the 16-bit number
case DispVal(3 downto 0) is -- active low to display segment
when "0000" => SegOut <= "1000000"; --0
when "0001" => SegOut <= "1111001"; --1
when "0010" => SegOut <= "0100100"; --2
when "0011" => SegOut <= "0110000"; --3
when "0100" => SegOut <= "0011001"; --4
when "0101" => SegOut <= "0010010"; --5
when "0110" => SegOut <= "0000010"; --6
when "0111" => SegOut <= "1111000"; --7
when "1000" => SegOut <= "0000000"; --8
when "1001" => SegOut <= "0010000"; --9
when "1010" => SegOut <= "0001000"; --A
when "1011" => SegOut <= "0000011"; --B
when "1100" => SegOut <= "1000110"; --C
when "1101" => SegOut <= "0100001"; --D
when "1110" => SegOut <= "0000110"; --E
when "1111" => SegOut <= "0001110"; --F
when others => Segout <= "0111111";
end case;
end case;
end process;
end Behavioral;
## Clock signal
set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {clk}];
##7 segment display
set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { seg[0] }]; #IO_L24N_T3_A00_D16_14 Sch=ca
set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { seg[1] }]; #IO_25_14 Sch=cb
set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { seg[2] }]; #IO_25_15 Sch=cc
set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { seg[3] }]; #IO_L17P_T2_A26_15 Sch=cd
set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { seg[4] }]; #IO_L13P_T2_MRCC_14 Sch=ce
set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { seg[5] }]; #IO_L19P_T3_A10_D26_14 Sch=cf
set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { seg[6] }]; #IO_L4P_T0_D04_14 Sch=cg
set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { an[0] }]; #IO_L23P_T3_FOE_B_15 Sch=an[0]
set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { an[1] }]; #IO_L23N_T3_FWE_B_15 Sch=an[1]
set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { an[2] }]; #IO_L24P_T3_A01_D17_14 Sch=an[2]
set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { an[3] }]; #IO_L19P_T3_A22_15 Sch=an[3]
set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { an[4] }]; #IO_L8N_T1_D12_14 Sch=an[4]
set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { an[5] }]; #IO_L14P_T2_SRCC_14 Sch=an[5]
set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { an[6] }]; #IO_L23P_T3_35 Sch=an[6]
set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { an[7] }]; #IO_L23N_T3_A02_D18_14 Sch=an[7]
##Buttons
set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { reset }]; #IO_L9P_T1_DQS_14 Sch=btnc
##Pmod Header JA
set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { JA[0] }]; #IO_L20N_T3_A19_15 Sch=ja[1]
set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { JA[1] }]; #IO_L21N_T3_DQS_A18_15 Sch=ja[2]
set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { JA[2] }]; #IO_L21P_T3_DQS_15 Sch=ja[3]
set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { JA[3] }]; #IO_L18N_T2_A23_15 Sch=ja[4]
set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS33 } [get_ports { JA[4] }]; #IO_L16N_T2_A27_15 Sch=ja[7]
set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { JA[5] }]; #IO_L16P_T2_A28_15 Sch=ja[8]
set_property -dict { PACKAGE_PIN F18 IOSTANDARD LVCMOS33 } [get_ports { JA[6] }]; #IO_L22N_T3_A16_15 Sch=ja[9]
set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { JA[7] }]; #IO_L22P_T3_A17_15 Sch=ja[10]

Sequence Detector Output on FPGA using 3 Input Switches

I have created a bit sequence detector (for sequence 1110) using VHDL. I have used Moore’s State Machine to accomplish the task.
I am able to compile my code and get the desired output.
But on the FPGA board I am supposed to use SW0 as clock, SW1 as data input, SW2 as RESET, any of the LED as data output.
The problems I am facing:
I am unable to assign the clock signal to a switch, I always get an error. So I assigned the clock signal to the default clock signal on the board i.e. LOC = "E3" it work fine. But according to my question I need to assign it to a switch. How do do that?
I am unable to show the output on the fpga board i.e. the led lights up too fast for the naked eye once the data in pin is applied. Any suggestion on how to display the output using 3 input switch and an LED as output as per the above question?
The following code is my design implementation:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Design is
Port ( clock : in STD_LOGIC;
din : in STD_LOGIC;
rst : in STD_LOGIC;
dout : out STD_LOGIC);
end Design;
architecture Behavioral of Design is
type state is (st0, st1, st2, st3, st4);
signal present_state, next_state : state;
begin
synchronous_process: process (clock)
begin
if rising_edge(clock) then
if (rst = '1') then
present_state <= st0;
else
present_state <= next_state;
end if;
end if;
end process;
output_decoder : process(present_state, din)
begin
next_state <= st0;
case (present_state) is
when st0 =>
if (din = '1') then
next_state <= st1;
else
next_state <= st0;
end if;
when st1 =>
if (din = '1') then
next_state <= st2;
else
next_state <= st0;
end if;
when st2 =>
if (din = '1') then
next_state <= st3;
else
next_state <= st0;
end if;
when st3 =>
if (din = '1') then
next_state <= st3;
else
next_state <= st4;
end if;
when st4 =>
if (din = '1') then
next_state <= st1;
else
next_state <= st0;
end if;
when others =>
next_state <= st0;
end case;
end process;
next_state_decoder : process(present_state)
begin
case (present_state) is
when st0 =>
dout <= '0';
when st1 =>
dout <= '0';
when st2 =>
dout <= '0';
when st3 =>
dout <= '0';
when st4 =>
dout <= '1';
when others =>
dout <= '0';
end case;
end process;
end Behavioral;
The following is my testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity tb_moore is
end tb_moore;
architecture Behavioral of tb_moore is
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT Design
PORT(
clock : IN std_logic;
din : IN std_logic;
rst : IN std_logic;
dout : OUT std_logic
);
END COMPONENT;
--Inputs
signal clock : std_logic := '0';
signal din : std_logic := '0';
signal rst : std_logic := '0';
--Outputs
signal dout : std_logic;
-- Clock period definitions
constant clk_period : time := 20 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: Design PORT MAP (
clock => clock,
din => din,
rst => rst,
dout => dout
);
-- Clock process definitions
clk_process :process
begin
clock <= '0';
wait for clk_period/2;
clock <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
rst <= '1';
wait for 20 ns;
rst <= '0';
din <= '1';
wait for 20 ns;
din <= '1';
wait for 20 ns;
din <= '1';
wait for 20 ns;
din <= '1';
wait for 20 ns;
din <= '1';
wait for 20 ns;
din <= '0';
wait for 20 ns;
din <= '1';
wait for 20 ns;
din <= '1';
end process;
END;
and the following is the constrains file i used for the Nexys DDR4 FPGA Board.
## Clock signal
NET "clock" LOC = "E3" | IOSTANDARD = "LVCMOS33";
## Switches
NET "din" LOC=L16 | IOSTANDARD=LVCMOS33;
NET "rst" LOC=M13 | IOSTANDARD=LVCMOS33;
## LEDs
NET "dout" LOC=H17 | IOSTANDARD=LVCMOS33;

Design does not fit ispLEVER

Hi I am trying to create a .jed file from a vhdl file through ispLEVER the problem appears when I try to create the fuse map and a port of 1 bit named le can´t be assigned to pin 23 (The GAL22V10-15LP has 24 pins)
Here is my vhdl code
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity alarm is port (
clk: IN std_logic;
le : OUT std_logic;
a: IN std_logic_vector(3 downto 0);
b: IN std_logic_vector(3 downto 0);
x: OUT std_logic_vector(1 downto 0));
end alarm;
architecture arch_alarm of alarm is
type states is (state0, state1, state2, state3 );
signal stado_pres, stado_fut: states;
begin
p_estados: process(stado_pres,a,b) begin
case stado_pres is
when state0 =>
x <= "00";
le <= '0';
if a = NOT(b) then
stado_fut <= state1;
else
stado_fut <= state0;
end if;
when state1 =>
x <= "01";
if a = NOT(b) then
stado_fut <= state2;
else
stado_fut <= state0;
end if;
when state2 =>
x <= "10";
if a = NOT(b) then
stado_fut <= state3;
else
stado_fut <= state0;
end if;
when state3 =>
x <= "11";
if a = NOT(b) then
le <= '1';
end if;
stado_fut <= state0;
end case;
end process p_estados;
p_reloj: process(clk) begin
if(clk'event and clk= '1') then
stado_pres <= stado_fut;
end if;
end process p_reloj;
end arch_alarm;
And the error that appears is :
Input file: 'untitled.tt2'
Device 'p22v10g'
Note 4068: Signal le cannot be assigned (to pin 23) because
the register type of 'le' pin 23 is invalid.
Design does NOT fit
FIT complete. Time: 1 second.
Done: failed with exit code: 0001
EDIT
I have added the le to all states but now it shows me another error
Here is the code
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.std_arith.all;
entity alarm is port (
clk: IN std_logic;
le : OUT std_logic;
a: IN std_logic_vector(3 downto 0);
b: IN std_logic_vector(3 downto 0);
x: OUT std_logic_vector(1 downto 0));
end alarm;
architecture arch_alarm of alarm is
type states is (state0, state1, state2, state3 );
signal stado_pres, stado_fut: states;
begin
p_estados: process(stado_pres,a,b) begin
case stado_pres is
when state0 =>
x <= "00";
le <= '0';
if a = NOT(b) then
stado_fut <= state1;
else
stado_fut <= state0;
end if;
when state1 =>
x <= "01";
le <= '0';
if a = NOT(b) then
stado_fut <= state2;
else
stado_fut <= state0;
end if;
when state2 =>
x <= "10";
le <= '0';
if a = NOT(b) then
stado_fut <= state3;
else
stado_fut <= state0;
end if;
when state3 =>
x <= "11";
if a = NOT(b) then
le <= '1';
end if;
stado_fut <= state0;
end case;
end process p_estados;
p_reloj: process(clk) begin
if(clk'event and clk= '1') then
stado_pres <= stado_fut;
end if;
end process p_reloj;
end arch_alarm;
And the errors are :
Note 4059: Signal le cannot be assigned (to pin 23) because
there are too many terms for output le pin 23.
Note 4068: Signal le cannot be assigned (to pin 23) because
the register type of 'le' pin 23 is invalid.
Your le signal infers a latch. It is assigned in only two states. Assign it in all four.
too many terms for output le pin 23"
After doing so you now have too many terms for Pin 23. It's because
if a = NOT(b) then
le <= '1';
end if;
the comparison of `a and not b'.
Can you move le to an output with 10 terms (pin 23 has 8)? (stado_pres should be the output of two flip flops while stado_fut is the input to the flip flops).
Can you make this comparison a separate signal with a pin? The impact would be twice the fall through delay of the PAL.
Have you been supplied with any indication how your states are encoded? (As in are they duplicated in x?, is x a synonym for stado_pres?)
and as pwolf points out
I only looked at this distractedly for your second error message. le is still prone to a latch based on the lack of else assignment in state3.
Determining timing associated with a PAL is trivial. What is this used for?
Keeping with #David Koontz answer, le is still not fully defined in state3. Try completing the if statement to fully define le:
when state3 =>
x <= "11";
if a = NOT(b) then
le <= '1';
else
le <= '0';
end if;
stado_fut <= state0;
If your inputs a and b are synchronous to your input clk, I would suggest you rewrite the state machine to run synchronously as apposed to asynchronously. E.g.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.std_arith.all;
entity alarm is port (
clk: IN std_logic;
le : OUT std_logic;
a: IN std_logic_vector(3 downto 0);
b: IN std_logic_vector(3 downto 0);
x: OUT std_logic_vector(1 downto 0));
end alarm;
architecture arch_alarm of alarm is
type states is (state0, state1, state2, state3 );
signal stado_pres : states := state0; -- Initial condition
begin
p_estados: process(clk)
begin
if rising_edge(clk) then
case stado_pres is
when state0 =>
x <= "00";
le <= '0';
if a = NOT(b) then
stado_pres <= state1;
else
stado_pres <= state0;
end if;
when state1 =>
x <= "01";
le <= '0';
if a = NOT(b) then
stado_pres <= state2;
else
stado_pres <= state0;
end if;
when state2 =>
x <= "10";
le <= '0';
if a = NOT(b) then
stado_pres <= state3;
else
stado_pres <= state0;
end if;
when state3 =>
x <= "11";
if a = NOT(b) then
le <= '1';
else
le <= '0';
end if;
stado_pres <= state0;
end case;
end if;
end process p_estados;
end arch_alarm;
IMHO, writing synchronous logic is generally preferred to asynchronous logic as timing analysis is made easier and it's much simpler to debug. This also has the added benefit of removing all of the latches from your code, which maybe be the source of your issue.
Even if inputs a and b are not synchronous to input clk, you could consider doing a proper clock domain transfer of these buses to the clk domain.

Resources