I'm writing TDC based on Vernier method in Vivado. My board is VC707 with virtex 7 core. After I finished writing my vhdl code i started simulation . Unfortunately I'm still learning fpga and vhdl so I stuck with one problem.
At first i wanted to check my my input circuit so i write a simple testbench to simulate. I generate short time interval to check this part of TDC. After i start simulation two of my outputs are uninicialized and other outputs have no sense ( should be high edge but simulation show zeros on the output).
On outputs should be rising edges. This circuit is intended to shape signals for my ring oscillators.
My vhdl desing:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Uklad_WE is
Port ( Start : in STD_LOGIC;
Stop : in STD_LOGIC;
Reset : in STD_LOGIC;
Pulse_st : out STD_LOGIC;
Pulse_sp : out STD_LOGIC;
Encnt_st : out STD_LOGIC;
Encnt_sp : out STD_LOGIC);
end Uklad_WE;
architecture Behavioral of Uklad_WE is
signal dst1_out : std_logic;
signal dst2_out : std_logic;
signal dsp1_out : std_logic;
signal dsp2_out : std_logic;
signal INV_chain_13_o : std_logic;
signal INV_chain_15_o : std_logic;
signal gate_cnt1_o : std_logic;
signal gate_cnt2_o : std_logic;
signal dcnt1_out : std_logic;
signal dcnt2_out : std_logic;
component ffd
port(
D,CLK,R : in STD_LOGIC;
Q: out STD_LOGIC
);
end component;
component ffd_set
port(
D,S,CLK : in STD_LOGIC;
Q : out STD_LOGIC
);
end component;
component INV_chain_15
port(
input : in STD_LOGIC;
output : out STD_LOGIC;
cnt_sig : inout std_logic
);
end component;
component INV_chain_13
port(
input : in STD_LOGIC;
output : out STD_LOGIC;
cnt_sig : inout std_logic
);
end component;
begin
DST1: ffd port map(
D => '1',
CLK => Start,
R => Reset,
Q => dst1_out);
DST2 : ffd_set port map(
D => '0',
CLK => dst1_out,
S => INV_chain_13_o,
Q => dst2_out);
DSP1 : ffd port map(
D => dst1_out,
CLK => Stop,
R => Reset,
Q => dsp1_out);
DSP2 : ffd_set port map(
D => '0',
CLK => dsp1_out,
S => INV_chain_15_o,
Q => dsp2_out);
DCNT1 : ffd port map(
D => '1',
CLK => gate_cnt1_o,
R => Reset,
Q => dcnt1_out);
DCNT2 : ffd port map(
D => '1',
CLK => gate_cnt2_o,
R => Reset,
Q => dcnt2_out);
INV_chain_st : INV_chain_13 port map(
input => dst2_out,
output => INV_chain_13_o,
cnt_sig => gate_cnt1_o);
INV_chain_sp : INV_chain_15 port map(
input => dsp2_out,
output => INV_chain_15_o,
cnt_sig => gate_cnt2_o);
Pulse_st <= dst2_out;
Pulse_sp <= dsp2_out;
Encnt_st <= dcnt1_out;
Encnt_sp <= dcnt2_out;
end Behavioral;
My testbench :
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
entity symulacja_tdc_vo is
end symulacja_tdc_vo;
architecture Behavioral of symulacja_tdc_vo is
component Uklad_WE
Port(
Start : in STD_LOGIC;
Stop : in STD_LOGIC;
Reset : in STD_LOGIC;
Pulse_st : out STD_LOGIC;
Pulse_sp : out STD_LOGIC;
Encnt_st : out STD_LOGIC;
Encnt_sp : out STD_LOGIC);
end component;
--inputs
signal Start : STD_LOGIC := '0';
signal Stop : STD_LOGIC := '0';
signal Reset : STD_LOGIC := '0';
--outputs
signal Pulse_st : STD_LOGIC;
signal Pulse_sp : STD_LOGIC;
signal Encnt_st : STD_LOGIC;
signal Encnt_sp : STD_LOGIC;
begin
--uut
uut: Uklad_WE port map(
Start => Start,
Stop => Stop,
Reset => Reset,
Pulse_st => Pulse_st,
Pulse_sp => Pulse_sp,
Encnt_st => Encnt_st,
Encnt_sp => Encnt_sp);
-- stimuluis process
stim_proc1: process
begin
Start <= not Start after 5 ps;
wait for 500 ps;
end process;
stim_proc2: process
begin
Stop <= not Stop after 50 ps;
wait for 500 ps;
end process;
stim_proc3: process
begin
wait for 250 ps;
Reset <= not Reset;
wait for 500 ps;
end process;
end Behavioral;
Components code :
ffd - ffd with reset
library ieee;
use ieee.std_logic_1164.all;
entity ffd is
port (
D, CLK, R : in std_logic;
Q : out std_logic );
end ffd;
architecture Bech of ffd is
begin
process( CLK, R )
begin
if R = '0' then
Q <= '0';
elsif rising_edge(CLK) then
Q <= D;
end if;
end process;
end Bech;
ffd_set - ffd with set
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity ffd_set is
port (
D, CLK, S : in std_logic;
Q : out std_logic );
end ffd_set;
architecture Bech of ffd_set is
begin
process( CLK, S )
begin
if S = '0' then
Q <= '1';
elsif rising_edge(CLK) then
Q <= D;
end if;
end process;
end Bech;
INV_chain_13 - inverters chain
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity INV_chain_13 is
Port ( input : in STD_LOGIC;
output : out STD_LOGIC;
cnt_sig : inout STD_LOGIC);
end INV_chain_13;
architecture Behavioral of INV_chain_13 is
signal gate_o : std_logic_vector(12 downto 0);
begin
gate_o(0) <= input;
inv_g_chain : for i in 1 to gate_o'high generate
gate_o(i) <= not gate_o(i-1);
end generate;
gate_o(1) <= cnt_sig;
output <= gate_o(12);
end Behavioral;
INV_chain_15 - also inverters chain, only number of inv is diffrent
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity INV_chain_15 is
Port ( input : in STD_LOGIC;
output : out STD_LOGIC;
cnt_sig : inout STD_LOGIC);
end INV_chain_15;
architecture Behavioral of INV_chain_15 is
signal gate_o : std_logic_vector(14 downto 0);
begin
gate_o(0) <= input;
inv_g_chain : for i in 1 to gate_o'high generate
gate_o(i) <= not gate_o(i-1);
end generate;
gate_o(1) <= cnt_sig;
output <= gate_o(14);
end Behavioral;
RTL Analysis
This is schematic of my design
RTL form Vivado screenshot
Simulation
And major problem :
Simulation screenshot
Maybe it's vhdl code issue, I don't know every rule of vhdl programming yet, I hope someone with better experience can help me.
I think there is some problem with set and reset in ffd . I try many options but nothing helped.
First of all: you're learning VHDL, and you have a Virtex-7??? I'm programming VHDL for 15 years now, but often only work with spartans... Virtex is just too expensive. Restectp.
But anyhow
inv_g_chain : for i in 1 to gate_o'high generate
gate_o(i) <= not gate_o(i-1);
end generate;
What are you trying to do here? I expect you want to use inverters to get some delay? Only, in VHDL concurrent assignment is instantaneous, so it does not work. You should add the delay manually. E.g.:
gate_o(i) <= not gate_o(i-1) after 10 ns;
by the way, do you know that you could use generics, more links to have a variable inverter delay chain length? Then you could combine INV_chain_13 and INV_chain_15 into one entity.
Then you have multiple drivers for the same signal:
gate_o(1) <= not gate_o(0);
and
gate_o(1) <= cnt_sig;
Multiple drivers does not work properly. And what's up with cnt_sig being of the inout type? <= is not a bidirectional assignment. VHDL is not good at bidirectional assignments, so try a different approach.
You are trying to build an asynchronous system. It is possible, but quite difficult. Please consider making something synchronous first, to get some experience.... Now you're trying to do F1 at your first driving lesson.
Related
I am getting this error while trying to implement a D flip-flop and simulate it:
VRFC 10-718] formal port does not exist in entity .
Please compare the definition of block to its component
declaration and its instantiation to detect the mismatch.
I am new to the language and can't figure out why this happening.
Bellow is my VHDL code.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Interfata is
port(
clk : in std_logic;
data :in std_logic;
Q : out std_logic;
Qnot : out std_logic
);
end Interfata;
architecture Behavioral of Interfata is
component LATCH
port(
set : in std_logic;
reset : in std_logic;
data : out std_logic;
data_not : out std_logic
);
end component;
signal latch_set: std_logic;
signal latch_reset:std_logic;
begin
uut1: latch port map(
set => latch_set,
reset => latch_reset,
data => Q,
data_not => Qnot
);
process(clk,data)
begin
if(clk' event and clk='1') then
latch_set <= data;
latch_reset <= not data;
end if;
end process;
end Behavioral;
here's the latch.vhd code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity latch is
port(
set : in std_logic;
reset :in std_logic;
data : out std_logic;
data_not : out std_logic
);
end latch;
architecture Behavioral of latch is
signal data_temp : std_logic:='0';
signal data_not_temp : std_logic:='1';
begin
process(set, reset) begin
data_temp <= not(reset or data_not_temp);
data_not_temp <= not(set or data_temp);
data <= data_temp;
data_not <= data_not_temp;
end process;
end Behavioral;
I have a VHDL component that is connected to a UART receiver. The uart has 2 output signals, one for the byte received and one for a flag that is set to 1 when the byte is done being received.
I have written the following module that should increment a counter for every new char and show it lighting up some leds.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use ieee.numeric_std.all;
entity test is
port (
clk : in std_logic;
rst : in std_logic;
ena : in std_logic;
rx : in std_logic;
led0 : out std_logic;
led1 : out std_logic;
led2 : out std_logic;
led3 : out std_logic;
led4 : out std_logic;
led5 : out std_logic;
led6 : out std_logic;
led7 : out std_logic
);
end test;
architecture arch of test is
component UART_RX
generic (
g_CLKS_PER_BIT : integer := 115 -- Needs to be set correctly
);
port (
i_Clk : in std_logic;
i_RX_Serial : in std_logic;
o_RX_DV : out std_logic;
o_RX_Byte : out std_logic_vector(7 downto 0)
);
end component;
signal sig_Din : std_logic_vector(7 downto 0);
signal sig_Dout : std_logic_vector(7 downto 0);
signal sig_RxErr : std_logic;
signal sig_RxRdy : std_logic;
signal sig_TxBusy : std_logic;
signal sig_StartTx: std_logic;
begin
UUT : UART_RX
generic map (
g_CLKS_PER_BIT => 434
)
port map (
i_clk => clk,
i_rx_serial => rx,
o_rx_dv => sig_RxRdy,
o_rx_byte => sig_Dout
);
process(clk)
variable position : integer := 0;
variable position_v : std_logic_vector(7 downto 0) := "00000000";
begin
if(sig_RxRdy = '1') then
position := position + 1;
position_v := std_logic_vector((unsigned(position_v1), 1));
led0 <= position_v(0);
led1 <= position_v(1);
led2 <= position_v(2);
led3 <= position_v(3);
led4 <= position_v(4);
led5 <= position_v(5);
led6 <= position_v(6);
led7 <= position_v(7);
end if;
end process;
end arch;
Is there any problem with the implementation? Every new char i send ends up incrementing the counter by more than 1. And is not even the same value every time.
I must not be understanding how FPGAs actually work because this is simple and I can't get it to work.
You are using sig_RxRdy as condition for incrementing. But we can not see how that signal behaves as it comes out of a module for which we have no code.
From the behavior you describe the o_rx_dv output (where sig_RxRdy comes from) is likely to be high for more then one of your clk cycles. As the UART input comes from an external source the time it is high may be variable which makes that you counter increment differs.
Solution is to detect a rising edge on sig_RxRdy by using a delayed version:
prev_sig_RxRdy <= sig_RxRdy;
sig_RxRdy_rising <= sig_RxRdy and not prev_sig_RxRdy;
Then increment your counters on that signal. This only works if o_rx_dv is already synchronous to your clock.
Below is the testbench
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity prime_tb is
end prime_tb;
architecture Behavioral of prime_tb is
COMPONENT prime_tb
PORT(
clk : in std_logic;
reset : in std_logic;
seq_in : in std_logic_vector(15 downto 0);
seq_out : out std_logic
);
END COMPONENT;
signal reset : std_logic := '0';
signal clk : std_logic := '0';
signal seq_in : std_logic_vector(15 downto 0);
signal seq_out : std_logic;
constant clk_period : time := 10 ns;
begin
uut: prime_tb PORT MAP (
clk => clk,
reset => reset,
seq_in => seq_in,
seq_out => seq_out
);
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
stim_proc: process
begin
seq_in <= "0000000011111111";
wait for clk_period;
seq_in <= "0000000000001111";
wait for clk_period;
wait;
end process;
end Behavioral;
I am new to VHDL and I am writing a function that takes a 16-bit input binary value and determining if it is a prime number. The output is '0' or '1'('1' for true and '0' for false). But when I run the simulation, the waveform I got has uninitialized values. It appears that both of my seq_in and seq_out are uninitialized. See link below.
Error:
Can someone help me to fix it?
You have a typo in your UUT instantiation. You didn't mean this:
COMPONENT prime_tb
PORT(
clk : in std_logic;
reset : in std_logic;
seq_in : in std_logic_vector(15 downto 0);
seq_out : out std_logic
);
END COMPONENT;
and this:
uut: prime_tb PORT MAP (
clk => clk,
reset => reset,
seq_in => seq_in,
seq_out => seq_out
);
You meant this:
COMPONENT prime
PORT(
clk : in std_logic;
reset : in std_logic;
seq_in : in std_logic_vector(15 downto 0);
seq_out : out std_logic
);
END COMPONENT;
and this:
uut: prime PORT MAP (
clk => clk,
reset => reset,
seq_in => seq_in,
seq_out => seq_out
);
BTW: you're not driving the reset input to your UUT.
I have this very simple 16-bit and gate written in structural form in VHDL:
The files are uploaded here.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity and_16bit is
Port (
A : in std_logic_vector(15 downto 0);
B : in std_logic_vector(15 downto 0);
Clk : in STD_LOGIC;
--Rst : in STD_LOGIC;
C : out std_logic_vector(15 downto 0) );
end and_16bit;
architecture Behavioral of and_16bit is
component and_1bit is
Port (
A : in std_logic;
B : in std_logic;
C : out std_logic );
end component;
signal s : std_logic_vector(15 downto 0);
begin
ands: for i in 15 downto 0 generate
and_1bit_x: and_1bit port map (A => A(i), B => B(i), C => s(i));
end generate;
process(Clk)
begin
if rising_edge(Clk) then
C <= s;
end if;
end process;
end Behavioral;
In order to update the output in the rising edge of the clock, I have defined this "s" signal. I wonder if this is the correct way to update the output in structural VHDL codes? what should I do to scape the unknown output for the first output?
Any comments will be a great help.
It's better to put the sequential process into a submodule and instantiate it in the top-level (and_16bit). Then your top-level will be more structural.
You can have one instance for each bit as you did for and_1bit.
For example, this module is a 1-bit register.
entity dff_1bit is
Port (
D : in std_logic;
Clk : in std_logic;
Q : out std_logic );
end dff_1bit;
architecture Behavioral of dff_1bit is
begin
process(Clk)
begin
if rising_edge(Clk) then
Q <= D;
end if;
end process;
end Behavioral;
Then you can instantiate it in and_16bit, inside the same generate block.
dff_1bit_x: dff_1bit port map (D => s(i), Clk => Clk, Q => C(i));
How can I make a testbench for this full adder code. I'm a newbie and would appreciate any help.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Full_Adder is
PORT(a , b , C_In : IN STD_LOGIC; S,C_Out : OUT STD_LOGIC);
end Full_Adder;
architecture Behavioral of Full_Adder is
begin
S <= a XOR b XOR C_In;
C_Out <= (a AND b) OR (a AND C_In) OR (b AND C_In);
end Behavioral;
Here's a good reference, one of the first that came up when I googled how to write a testbench.
You should google first, give it an honest shot, then come back here with more specific questions.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Full_Adder_tb is
end Full_Adder_tb;
architecture Behavioral of Full_Adder_tb is
component Full_Adder is -- component declaration
port(
a : in std_logic;
b : in std_logic;
C_in : in std_logic;
S : out std_logic;
C_out : out std_logic
);
end component;
signal a: std_logic := '0'; -- signal declarations
signal b: std_logic := '0';
signal C_in: std_logic := '0';
signal S: std_logic;
signal C_out : std_logic;
begin
uut : Full_Adder -- component instantiation
port map(
a => a, -- signal mappings
b => b,
C_in => C_in,
S => S,
C_out => C_out);
process
begin
wait 10 ns; -- wait time
a <= '0'; b <= '0'; C_in <= '1'; -- example test vector
wait 10 ns;
-- Other test vectors and waits here
end process;
end Behavioral;