I want to implement a Serializer/Deserializer (SerDes) in VHDL. Actually, it is more like a simple Shift register. The shift register store a value and shifts to convert information from parallel to serial.The output of the register is 16 bits. It has an 16-bit Parallel input, which allows us to load the register with a new value. The load input allows to load a new value when a falling edge of the clock arrives.
Moreover, I also made a testBench with two SerDes component connected together to implement a sort of loop/ring. Unfortunately, I don't know why when I send a data with the value "1234" from the parallel input I receive "3412" in my parallel output : waveform testBench.
Below my code :
SerDes.vhd :
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity SerDes is
generic (
Dbits : integer := 16
);
Port (
serial_clk : in STD_LOGIC;
clk : in STD_LOGIC;
rstn : in STD_LOGIC;
load : in STD_LOGIC;
enable : in STD_LOGIC;
serial_in : in STD_LOGIC;
parallel_in : in STD_LOGIC_VECTOR(Dbits-1 downto 0);
dout : out STD_LOGIC;
parallel_out : out STD_LOGIC_VECTOR(Dbits-1 downto 0)
);
end SerDes;
architecture Behavioral of SerDes is
signal rx_counter : integer := 0 ;
signal shift_reg : STD_LOGIC_VECTOR(Dbits-1 downto 0);
type TYPE_STATE is (Idle,ShiftIn);
signal CURRENT_STATE : TYPE_STATE := Idle;
signal serial_clock_D : STD_LOGIC := '0';
begin
serialization : process(serial_clk,rstn) --Envoyer une donnée parallèle et la récupérer sur la sortie série
begin
if (rstn = '0') then
shift_reg <= (others => '0');
rx_counter <= 0;
serial_clock_D <= '0';
CURRENT_STATE <= Idle;
elsif (clk = '1' and clk'event) then
case CURRENT_STATE is
when Idle =>
if (enable = '1') then
CURRENT_STATE <= ShiftIn;
else
CURRENT_STATE <= Idle;
end if;
if (load = '1') then
shift_reg <= parallel_in;
end if;
parallel_out <= shift_reg;
rx_counter <= 0;
when ShiftIn =>
if(serial_clk = '1' and serial_clock_D = '0') then
shift_reg <= shift_reg(14 downto 0) & serial_in;
end if;
if (rx_counter = Dbits-1) then
CURRENT_STATE <= Idle;
else
rx_counter <= rx_counter + 1;
end if;
end case;
end if;
end process;
dout <= shift_reg(15);
end Behavioral;
SERDESTestbench.vhd :
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity SERDES_Testbench is
-- Port ( );
end SERDES_Testbench;
architecture Behavioral of SERDES_Testbench is
constant Dbits : integer := 16;
component SerDes is
generic (
Dbits : integer := 16
);
Port (
serial_clk : in STD_LOGIC;
clk : in STD_LOGIC;
rstn : in STD_LOGIC;
load : in STD_LOGIC;
enable : in STD_LOGIC;
serial_in : in STD_LOGIC;
parallel_in : in STD_LOGIC_VECTOR(Dbits-1 downto 0);
dout : out STD_LOGIC;
parallel_out : out STD_LOGIC_VECTOR(Dbits-1 downto 0)
);
end component;
signal serial_clk : STD_LOGIC := '0';
signal clk : STD_LOGIC := '0';
signal rstn : STD_LOGIC;
signal load : STD_LOGIC := '1';
signal enable : STD_LOGIC := '0';
signal serial_in : STD_LOGIC;
signal parallel_in : STD_LOGIC_VECTOR(Dbits-1 downto 0) := (others => '0');
signal dout : STD_LOGIC;
signal parallel_out : STD_LOGIC_VECTOR(Dbits-1 downto 0);
signal dout2 : STD_LOGIC;
signal parallel_out2 : STD_LOGIC_VECTOR(Dbits-1 downto 0);
signal end_of_simu : STD_LOGIC := '0';
begin
SR1 : SerDes
generic map(
Dbits => Dbits
)
Port map(
serial_clk => serial_clk,
clk => clk,
rstn => rstn,
load => load,
enable => enable,
serial_in => dout2,
parallel_in => parallel_in,
dout => dout,
parallel_out => parallel_out
);
SR2 : SerDes
generic map(
Dbits => Dbits
)
Port map(
serial_clk => serial_clk,
clk => clk,
rstn => rstn,
load => load,
enable => enable,
serial_in => dout,
parallel_in => parallel_in,
dout => dout2,
parallel_out => parallel_out2
);
stimulus : process
begin
rstn <= '0';
wait for 100 ns;
rstn <= '1';
wait for 100 ns;
parallel_in <= X"1234";
enable <= '1';
wait;
end process;
clocking : process
begin
IF end_of_simu /= '1' THEN
clk <= not clk;
wait for 5 ns;
ELSE
assert false report "end of test" severity note;
WAIT;
END IF;
end process;
sclk_gen : process
begin
IF end_of_simu /= '1' THEN
serial_clk <= not serial_clk;
wait for 100 ns;
ELSE
assert false report "end of test" severity note;
WAIT;
END IF;
end process;
end Behavioral;
Related
I'm new to fpga and VHDL in general (I'm using a fpga aprox. 2 weeks now). I am trying to create a project that lights up LEDs in order. First of all I made a falling edge detector for the button. And then I created a std_logic_vector for LEDs. But I can't detect a signal change in fallen edge detection. Because of that I can't change LED state. There is my testbench for simulation. I don't have any idea what's going on. Thanks for your answers and sorry for my bad English.
Code:
library ieee;
use ieee.std_logic_1164.all;
entity sequential_led is
end sequential_led;
architecture seq_led of sequential_led is
signal clk : std_logic := '0';
--signal rst : std_logic := '1';
--signal rstb : std_logic := '1';
signal i : natural := 0;
signal dus_next : std_logic := '0';
signal dusen : std_logic := '0';
signal button : std_logic := '0';
signal led : std_logic_vector(7 downto 0);
begin
clk <= not clk after 1 ns;
button <= not button after 2 ns;
falling:
process begin
if rising_edge(clk) then
dus_next <= button;
end if;
wait for 100 ns;
end process falling;
dusen <= (not button) and dus_next;
led_changes:
process begin
if dusen = '1' then
i <= i + 1;
if i = 7 then
i <= 0;
end if;
end if;
led(7-i) <= '0';
led(i) <= '1';
wait for 100 ns;
end process led_changes;
end architecture;
UPDATE: First of all very big thanks to DomasAquinas and Martin Thompson! After 3 days of work, I finally finished my little LED project.
Change: I've made sure all of processes has a sensivity trigger.
For falling process I've included 'clk' signal for sensivity.
For led_change process I've included 'dusen' signal for sensivity.
Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity sequential_led is
port(
clk : in std_logic;
button : in std_logic;
led : out std_logic_vector(7 downto 0) := (others => '0')
);
signal dus_next : std_logic;
signal i : natural range 0 to 7;
signal dusen : std_logic := '0';
end sequential_led;
architecture seq_led of sequential_led is
begin
falling:
process(clk) begin
if rising_edge(clk) then
dus_next <= button;
end if;
end process falling;
dusen <= (not button) and dus_next;
led_changes:
process(dusen) begin
if dusen = '1' then
i <= i + 1;
if i = 7 then
i <= 0;
end if;
led(i) <= '1';
led(i+7) <= '0';
end if;
end process led_changes;
end architecture;
I have a vhdl code written for a shifter made with d-flip flops and multiplexers which runs and checks with successful syntax. However, now that i'm working on the testbench i'm running into some errors.
The VHDL Code is:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY MUX41 IS
PORT (i3, i2, i1, i0 : IN BIT;
s: IN BIT_VECTOR(1 DOWNTO 0);
o: OUT BIT);
END MUX41;
ARCHITECTURE arch_mux41 OF MUX41 IS
BEGIN
PROCESS(i3, i2, i1, i0, s)
BEGIN
CASE s IS
WHEN "00" => o <= i0;
WHEN "01" => o <= i1;
WHEN "10" => o <= i2;
WHEN "11" => o <= i3;
WHEN OTHERS => NULL;
END CASE;
END PROCESS;
END arch_mux41;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY DFF IS
PORT(d, clk : IN BIT;
q, qb : OUT BIT);
END DFF;
ARCHITECTURE arch_dff OF DFF IS
BEGIN
PROCESS(clk)
VARIABLE q_temp : BIT;
BEGIN
IF(clk'EVENT AND clk='1')THEN
q_temp := d;
END IF;
q <= q_temp;
qb <= NOT q_temp;
END PROCESS;
END arch_dff;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY UShift IS
PORT(clk, il, ir : IN BIT;
s: IN BIT_VECTOR(1 DOWNTO 0);
i : IN BIT_VECTOR(3 DOWNTO 0);
q : OUT BIT_VECTOR(3 DOWNTO 0));
END UShift;
ARCHITECTURE struct OF UShift IS
COMPONENT MUX41
PORT (i3, i2, i1, i0 : IN BIT;
s: IN BIT_VECTOR(1 DOWNTO 0);
o: OUT BIT);
END COMPONENT;
COMPONENT DFF
PORT(d, clk : IN BIT;
q, qb : OUT BIT);
END COMPONENT;
FOR U1, U2, U3, U4: MUX41 USE ENTITY WORK.MUX41(arch_mux41);
FOR U5, U6, U7, U8: DFF USE ENTITY WORK.DFF(arch_dff);
SIGNAL o: BIT_VECTOR(3 DOWNTO 0);
SIGNAL qb: BIT_VECTOR(3 DOWNTO 0);
SIGNAL qt:BIT_VECTOR(3 DOWNTO 0);
BEGIN
U1:MUX41 PORT MAP(il,qt(2), i(3), qt(3), s, o(3));
U2:MUX41 PORT MAP(qt(3), qt(1), i(2), qt(2), s, o(2));
U3:MUX41 PORT MAP(qt(2), qt(0), i(1), qt(1), s, o(1));
U4:MUX41 PORT MAP(qt(1), ir, i(0), qt(0), s, o(0));
U5:DFF PORT MAP(o(3), clk, qt(3), qb(3));
U6:DFF PORT MAP(o(2), clk, qt(2), qb(2));
U7:DFF PORT MAP(o(1), clk, qt(1), qb(1));
U8:DFF PORT MAP(o(0), clk, qt(0), qb(0));
q <= qt;
END struct;
The error messages that come up only appear when checking for the syntax in the testbench. They state that the entity does not match component port for "clk", "il", "ir", "i", "s", and "q". Does anyone have any ideas on what I may have wrong? I have read some suggestions online for similar issue but none have applied actually applied to this particular code.
The testbench is:
LIBRARY ieee;
USE IEEE.STD_LOGIC_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY UShift_test IS
END UShift_test;
ARCHITECTURE behavior OF UShift_test IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT UShift
PORT(clk : IN std_logic; il : IN std_logic; ir : IN std_logic; i : IN std_logic_vector(3 downto 0); s:IN std_logic_vector(1 downto 0);
q : OUT std_logic_vector(3 downto 0));
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal il : std_logic := '0';
signal ir : std_logic := '0';
signal s : std_logic_vector(1 downto 0) := (others => '0');
signal i : std_logic_vector(3 downto 0) := (others => '0');
--Outputs
signal q : std_logic_vector(3 downto 0);
-- Clock period definitions
constant clk_period : time := 20 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: UShift PORT MAP (
clk => clk,
il => il,
ir => ir,
s => s,
i => i,
q => q);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
---- test clr
ir<= '0';
wait for 40ns;
---- test parallel loading
ir<= '1';
s<= "11";
i<= "0010";
wait for 40ns;
---- test shift right
s<= "01";
il<='1';
wait;
end process;
END;
Yes. Here is the entity for UShift:
ENTITY UShift IS
PORT(clk, il, ir : IN BIT;
s: IN BIT_VECTOR(1 DOWNTO 0);
i : IN BIT_VECTOR(3 DOWNTO 0);
q : OUT BIT_VECTOR(3 DOWNTO 0));
END UShift;
Here is the corresponding component in UShift_test:
COMPONENT UShift
PORT(clk : IN std_logic; il : IN std_logic; ir : IN std_logic; i : IN std_logic_vector(3 downto 0); s:IN std_logic_vector(1 downto 0);
q : OUT std_logic_vector(3 downto 0));
END COMPONENT;`:
As you can see, they are different. Unless you use a configuration with a port map which includes type conversion functions, the component and entity should be identical. I highly recommend you don't try to fix this using a configuration, instead I recommend you change the types to match. You have used type BIT in your designs, which is unusual. Unless there is a good reason for that, I'd change type BIT to type STD_LOGIC (and the corresponding vectors, obviously).
And, why are you using component instantiation? Direct instantiation is easier and is less typing and the extra flexibility offered by component instantiation is usually not required. Here is an example that compares the two methods: https://www.edaplayground.com/x/2QrS.
I made my FSM in VHDL and now I want to use the debounce code with port mapping.
Though I have difficulties with the associations. In fact I want to insett the debouncebutton component among the signals that are driving the FSM.
entity myFSM is
Port ( CLK : in STD_LOGIC;
RST : in STD_LOGIC;
IN0 : in STD_LOGIC;
IN1 : in STD_LOGIC;
IN2 : in STD_LOGIC;
LED : out STD_LOGIC_VECTOR (7 downto 0));
end myFSM;
architecture Behavioral of myFSM is
type state is (A, B, C);
signal currentS, nextS: state;
component debouncebutton
Port ( clk : in std_logic; -- connect it to the Clock of the board
rst : in std_logic; -- connect it to the Reset Button of the board
input : in std_logic; -- connect it to the Push Button of the board
output : out std_logic -- connect it to your circuit
);
end component;
begin
myFSM_comb: process (currentS, IN0, IN1, IN2)
begin
case currentS is
when A => LED <= "11111111";
if IN0 = '1' then nextS<=B;
elsif IN1 = '1' then nextS<=C;
else nextS<=A;
end if;
when B => LED <= "11000011";
if IN0 = '1' then nextS<=C;
elsif IN1 = '1' then nextS<=A;
else nextS<=B;
end if;
when C => LED <= "00111100";
if IN0 = '1' then nextS<=A;
elsif IN1 = '1' then nextS<=B;
else nextS<=C;
end if;
end case;
end process;
myFSM_synch: process(CLK,RST)
begin
if (RST='1') then currentS<=A;
elsif (rising_edge(CLK)) then currentS<= nextS;
end if;
end process ;
begin
db0 : debounce
port map
(
clk => CLK,
rst => RST,
input => IN0,
output
end Behavioral;
I marked up your code by renaming IN0 to INP0 in the port declaration, declared a signal in the architecture with the name INO to keep from changing every occurrence of the name, removed an extraneous begin and renamed the instantiated component from debounce to debouncebutton to match the component declaration:
library ieee;
use ieee.std_logic_1164.all;
entity myFSM is
Port ( CLK : in STD_LOGIC;
RST : in STD_LOGIC;
INP0 : in STD_LOGIC; -- name changed
IN1 : in STD_LOGIC;
IN2 : in STD_LOGIC;
LED : out STD_LOGIC_VECTOR (7 downto 0));
end myFSM;
architecture Behavioral of myFSM is
type state is (A, B, C);
signal currentS, nextS: state;
component debouncebutton
Port ( clk : in std_logic; -- connect it to the Clock of the board
rst : in std_logic; -- connect it to the Reset Button of the board
input : in std_logic; -- connect it to the Push Button of the board
output : out std_logic -- connect it to your circuit
);
end component;
signal IN0: std_logic; --- added
begin
myFSM_comb: process (currentS, IN0, IN1, IN2)
begin
case currentS is
when A => LED <= "11111111";
if IN0 = '1' then nextS<=B;
elsif IN1 = '1' then nextS<=C;
else nextS<=A;
end if;
when B => LED <= "11000011";
if IN0 = '1' then nextS<=C;
elsif IN1 = '1' then nextS<=A;
else nextS<=B;
end if;
when C => LED <= "00111100";
if IN0 = '1' then nextS<=A;
elsif IN1 = '1' then nextS<=B;
else nextS<=C;
end if;
end case;
end process;
myFSM_synch: process(CLK,RST)
begin
if (RST='1') then currentS<=A;
elsif (rising_edge(CLK)) then currentS<= nextS;
end if;
end process ;
-- begin -- syntax error you have a begin before process myFSB_comb
db0 : debouncebutton --- was debounce, needs to match component declaration
port map (
clk => CLK,
rst => RST,
input => INP0, -- renamed input port
output=> IN0 -- newly declared signal INO
);
end Behavioral;
This allowed the new input port INP0 to be associated to the formal input on debouncebutton and the formal output to be connected to the newly declared signal IN0.
You could also go to all the trouble of simply declaring a new signal for the output association and changing instances of the name IN0 other than the port declaration for myFSM.
Your modified code above analyzes. Without creating an entity/architecture pair for debouncebutton it can't be elaborated (or simulated).
I have a problem: I've tried to simulate my project by the testbench, but ModelSim wrote this message:
Error: C:/.../testbench.vhd(62): (vcom-1136) Unknown identifier "arst".
And the same message for each other ports of testbench's component.
Also, next one type of messages, for internal signals of testbench:
Error: C:/.../testbench.vhd(63): (vcom-1484) Unknown formal identifier ARST_STIM
Top-entity top_test and each other entities in one common folder with testbench, so I do not understand what is a reason of the problem. I've posted the code of my testbench below:
-- Created:
-- by - Desmond.UNKNOWN (DESMOND-PC)
-- at - 00:52:37 07.03.2016
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY testbench IS
END testbench;
ARCHITECTURE rtl OF testbench IS
-- Architecture declarations
-- Internal signal declarations
-- Component declarations
COMPONENT top_test
PORT (
arst : IN std_logic;
bithigh : IN std_logic_vector(31 DOWNTO 0);
bitlow : IN std_logic_vector(31 DOWNTO 0);
ca_bh10 : OUT std_logic;
ch_ca_data : IN std_logic_vector(31 DOWNTO 0);
ch_s : IN std_logic_vector(31 DOWNTO 0);
clk120MHz : IN std_logic;
clk240Mhz : IN std_logic;
clock_value_high : IN std_logic_vector(31 DOWNTO 0);
clock_value_low : IN std_logic_vector(31 DOWNTO 0);
dac_1 : OUT std_logic_vector(15 downto 0);
dac_2 : OUT std_logic_vector(15 downto 0);
freq_setup : IN std_logic_vector(31 DOWNTO 0);
led : OUT std_logic;
level : IN std_logic_vector(31 DOWNTO 0);
out_symb : OUT std_logic;
pps : IN std_logic
);
END COMPONENT;
--------------------------------------
signal LED,CA_OUT,MOD_OUT : std_logic;
signal ARST_STIM,CLK_120MHZ,CLK_240MHZ,PPS_STIM : std_logic := '0';
signal BIT_HIGH_STIM,BIT_LOW_STIM,LEVEL_STIM,CA_DATA_STIM,FREQ_STIM,CLK_LOW_STIM,CLK_HIGH_STIM,CH_SELECT_STIM : std_logic_vector (31 downto 0);
signal DAC_1, DAC_2 : std_logic_vector (15 downto 0);
--------------------------------------
constant CLK_120MHZ_PERIOD : TIME := 8.33 ns;
constant CLK_240MHZ_PERIOD : TIME := 4.15 ns;
-------------------------------------
BEGIN
U_0 : top_test
PORT MAP (
ARST_STIM => arst,
CLK_120MHZ => clk120MHz ,
CLK_240MHZ => clk240Mhz,
PPS_STIM => pps,
BIT_HIGH_STIM => bithigh ,
BIT_LOW_STIM => bitlow,
LEVEL_STIM => level,
CA_DATA_STIM => ch_ca_data,
FREQ_STIM => freq_setup,
CLK_LOW_STIM => clock_value_low,
CLK_HIGH_STIM => clock_value_high,
CH_SELECT_STIM => ch_s,
DAC_1 => dac_1,
DAC_2 => dac_2,
CA_OUT => ca_bh10,
LED => led,
MOD_OUT => out_symb
);
--------------------------
CLK_GENERATION : process
begin
CLK_120MHZ <= not CLK_120MHZ after (CLK_120MHZ_PERIOD/2);
CLK_240MHZ <= not CLK_240MHZ after (CLK_240MHZ_PERIOD/2);
end process CLK_GENERATION;
----------------------------
STIM_PROC : process
begin
ARST_STIM <= '1';
PPS_STIM <= '0';
wait for 100 ns;
CH_SELECT_STIM <= (others=>'0');
CLK_LOW_STIM <= "00010111010110001110001000011001";
CLK_HIGH_STIM <= "00000000000000000000000000000001";
FREQ_STIM <= "00000010001000100010001000100010";
LEVEL_STIM <= "00000000000000000000000000110010";
CA_DATA_STIM <= "00000000000000000000000000000110";
BIT_LOW_STIM <= "00100110100101111011000000000000";
BIT_HIGH_STIM <= "10101010010010111110100001010101";
wait for 1800 ns;
PPS_STIM <= '1';
wait for 100 ns;
PPS_STIM <= '0';
wait for 1000 ns;
CH_SELECT_STIM <= "00000000000000000000000000000001";
wait for 999999000 ns;
PPS_STIM <= '1';
wait for 100 ns;
PPS_STIM <= '0';
wait for 10000000 ns;
end process STIM_PROC;
END rtl;
I am trying to write a testbench but Vivado tells me that I have a Syntax error on a specific line. I am not able to realize what have I done wrong. Can anyone help.
Here is my tb code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.Numeric_Std.all;
entity mmu_tb is
end mmu_tb;
architecture test of mmu_tb is
component mmu
port (
virt : in std_logic_vector(15 downto 0);
phys : out std_logic_vector(15 downto 0);
clock : in std_logic;
we : in std_logic;
datain : in std_logic_vector(7 downto 0)
);
end component;
signal virt std_logic_vector(15 downto 0);
signal phys std_logic_vector(15 downto 0);
signal clock std_logic;
signal we std_logic;
signal datain std_logic_vector(7 downto 0);
constant clock_period: time := 10 ns;
signal stop_the_clock: boolean;
begin
mmu : mmu port map ( virt => virt,
phys => phys,
clock => clock,
we => we,
datain => datain);
stimulus : process
begin
-- whatever
end process;
clocking: process
begin
while not stop_the_clock loop
clock <= '1', '0' after clock_period / 2;
wait for clock_period ;
end loop;
wait;
end process;
end test;
And here is the error I get:
[HDL 9-806] Syntax error near "std_logic_vector". ["C:/ram/ram/ram.srcs/sim_1/new/mmu_tb.vhd":20]
Thank you for your time.
Missing :, so line 20 should be:
signal virt : std_logic_vector(15 downto 0);
and similar for subsequent lines.