implementing a 50ns delay in VHDL - vhdl

I'm sending data to and A/D converter and I need the command data to be delayed at least 50ns from clk_19khz. Here is what I have so far.
How do I insert a delay of 50ns which is a requirement for the A/D between the clk_19khz and my first Dout bit to the A/D?
I'm using a Xilinx FPGA. Thanks for the help!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity PSOL is
Port ( clk : in STD_LOGIC;
clk_19khz : OUT std_logic;
Dout :out std_logic);
end PSOL;
architecture Behavioral of PSOL is
signal temp : std_logic;
signal count : integer range 0 to 1301 := 0; --1301
signal temp2 : std_logic;
signal dcount : integer range 0 to 11 := 0; --
signal start : std_logic := '1'; -- indicates the start of
signal parity : std_logic := '1'; --used to varify data sent
signal stop : std_logic := '0'; --indicate when word/command has
--signal chip_select : bit :='1'; -- active low
begin
process (clk)
begin
if (clk' EVENT AND clk='1') then
if (count = 1301) then --1301
temp <= not(temp);
count <=0;
else
count <= count + 1;
end if;
end if;
end process;
clk_19khz <= temp;
temp2 <= temp;
process (temp2)
begin
If (temp2' EVENT and temp2 ='0') then
dcount <= dcount + 1;
parity <= '1';
stop <= '0';
start <='1';
if (dcount < 12 and start = '1' and stop = '0') then
CASE dcount is
when 1 => Dout <= start; -- need delay 50ns before this
when 2 => Dout <= '0';
when 3 => Dout <= '1';
when 4 => Dout <= '0';
when 5 => Dout <= '1';
when 6 => Dout <= '0';
when 7 => Dout <= '0';
when 8 => Dout <= '1';
when 9 => Dout <= '1';
when 10 => Dout <= parity;
when 11 => Dout <= '0';
when others => null;
end case;
end if;
end if;
--dcount <= 0;
--start <='1';
end process;
end Behavioral;

Your clock (50 MHz) has a period of 20 ns. So you'll need a modulo-3 counter to count a delay of at least 3 clock pulses which gives a delay of 60 ns.
Declarations:
signal delay_en : std_logic;
signal delay_us : unsigned(1 downto 0) := (others => '0');
signal delay_ov : std_logic;
Usage:
process(clk)
begin
if rising_edge(clk) then
if (delay_en = '1') then
delay_us <= delay_us + 1;
else
delay_us <= (others => '0');
end if;
end if;
end process;
delay_ov <= '1' when (delay_us = 2) else '0';
Your current implementation needs to drive delay_en while it's waiting for the timespan. If the delay is over, it emits the signal delay_ov (ov = overflow). This can be used by your solution to go on the in algorithm. Your code should also deassert delay_en, what clears the counter to 0.

Related

Different Clock Domain VHDL

I'm making a custom hardware ARINC 429 Core.
For now I have described the module in transmission (TX-FSM), according to the ARINC 429 standard and a FIFO in transmission from which it takes the data and sends them to the outside.
The FIFO works at a frequency of 2MHz (clk2M), while TX-FSM can generate a frequency of 100kb / s or 12.5kb / s (clk429) from 2MHz as per standard.
Since the FIFO works at a higher frequency (2 MHz), and the TX-FSM works at a lower frequency (100 kb/s), when the TX-FSM requests a data from the FIFO by raising the "TX_FIFO_rd" signal ("rd_en" on FIFO ), the FIFO supplies all the data contained within it, since in the FIFO clock domain the "rd_en" signal remains high for several cycles.
The FIFO should only provide one data at a time. Once the data has been transmitted, the TX-FSM will request the next data.
How can I make the FIFO and TX-FSM work in sync using a single clock?
FIFO VHDL code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity FIFO is
generic (
FIFO_WIDTH : natural := 32;
FIFO_DEPTH : integer := 10;
ALMOST_FULL_LEVEL : integer := 8;
ALMOST_EMPTY_LEVEL : integer := 2
);
port (
reset : in std_logic;
clk : in std_logic;
-- FIFO Write Interface
wr_en : in std_logic;
wr_data : in std_logic_vector(FIFO_WIDTH-1 downto 0);
ALMOST_FULL : out std_logic;
FULL : out std_logic;
-- FIFO Read Interface
rd_en : in std_logic;
rd_data : out std_logic_vector(FIFO_WIDTH-1 downto 0);
ALMOST_EMPTY : out std_logic;
EMPTY : out std_logic
);
end FIFO;
architecture rtl of FIFO is
type t_FIFO_DATA is array (0 to FIFO_DEPTH) of std_logic_vector(FIFO_WIDTH-1 downto 0);
signal r_FIFO_DATA : t_FIFO_DATA := (others => (others => '0'));
signal r_WR_INDEX : integer range 0 to FIFO_DEPTH -1 := 0;
signal r_RD_INDEX : integer range 0 to FIFO_DEPTH -1 := 0;
-- # Words in FIFO, has extra range to allow for assert conditions
signal r_FIFO_COUNT : integer range -1 to FIFO_DEPTH+1 := 0;
signal w_FULL : std_logic;
signal w_EMPTY : std_logic;
begin
-- FIFO process
-------------------------------------------------------------------
-------------------------------------------------------------------
WRITE_INDEX : process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
r_WR_INDEX <= 1;
else
if (wr_en = '1' and w_FULL = '0') then
if r_WR_INDEX = FIFO_DEPTH-1 then
r_WR_INDEX <= 1;
else
r_WR_INDEX <= r_WR_INDEX + 1;
end if;
end if;
end if;
end if;
end process;
READ_INDEX : process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
r_RD_INDEX <= 0;
else
if (rd_en = '1' and w_EMPTY = '0') then
if r_RD_INDEX = FIFO_DEPTH-1 then
r_RD_INDEX <= 0;
else
r_RD_INDEX <= r_RD_INDEX + 1;
end if;
end if;
end if;
end if;
end process;
COUNT_INDEX : process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
r_FIFO_COUNT <= 0;
else
if (wr_en = '1' and rd_en = '0') then
r_FIFO_COUNT <= r_FIFO_COUNT + 1;
elsif (wr_en = '0' and rd_en = '1') then
if r_FIFO_COUNT > 0 then
r_FIFO_COUNT <= r_FIFO_COUNT - 1;
end if;
end if;
end if;
end if;
end process;
Write_Data : process (clk) is
begin
if rising_edge(clk) then
if wr_en = '1' then
r_FIFO_DATA(r_WR_INDEX) <= wr_data;
end if;
end if;
end process;
rd_data <= r_FIFO_DATA(r_RD_INDEX);
w_FULL <= '1' when r_FIFO_COUNT = FIFO_DEPTH else '0';
w_EMPTY <= '1' when r_FIFO_COUNT = 0 else '0';
ALMOST_FULL <= '1' when r_FIFO_COUNT > ALMOST_FULL_LEVEL else '0';
ALMOST_EMPTY <= '1' when r_FIFO_COUNT < ALMOST_EMPTY_LEVEL else '0';
FULL <= w_FULL;
EMPTY <= w_EMPTY;
end rtl;
TX-FSM code
-- Arinc 429 trasmitter interface
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Tx is
port
(
--INPUT
clk2M : in std_logic; -- clock signal
reset : in std_logic; -- reset signal
enable : in std_logic; -- enable signal
en_parity : in std_logic; -- enable parity bit
parity : in std_logic; -- odd/even parity
speed : in std_logic; -- speed 100kbps or 12.5kbps
gap : in std_logic; -- gap between two messages: 4 or 64 bit of gap
TX_FIFO_ep : in std_logic; -- TX FIFO EMPTY
a429TX_in : in std_logic_vector (31 downto 0); -- data in
--OUTPUT
a429TX_outA : out std_logic; -- positive out
a429TX_outB : out std_logic; -- negative out
TX_FIFO_rd : out std_logic -- TX FIFO READ
);
end entity;
architecture RTL_A429TX of Tx is
-- FSM state name
type state_type is (IDLE,START, PAR,TRANSMITTING,WAITING);
signal state : state_type;
-- FSM register
signal shift_reg : std_logic_vector (31 downto 0);
signal shift_counter : std_logic_vector (4 downto 0);
signal gap_counter : std_logic_vector (6 downto 0);
-- speed clock register
signal clk429 : std_logic;
signal clk429_counter : integer;
signal clk429_max_count : integer;
signal clk429_half_count : integer;
begin
-- speed clock process
-------------------------------------------------------------------
-------------------------------------------------------------------
-- select speed process
process (speed)
begin
if (speed = '1') then
clk429_max_count <= 19; -- 100kbs/s
clk429_half_count <= 10;
else
clk429_max_count <= 159; -- 12.5kbs/s
clk429_half_count <= 80;
end if;
end process;
-- clock429 generate speed process
process (clk2M, reset)
begin
if (reset = '1') then
clk429 <= '0';
elsif rising_edge(clk2M) then
if (clk429_counter <= clk429_half_count ) then
clk429 <= '1';
else
clk429 <= '0';
end if;
end if;
end process;
-- counter activity process
process (clk2M, reset)
begin
if (reset = '1') then
clk429_counter <= 0;
elsif rising_edge(clk2M) then
if (clk429_counter >= clk429_max_count) then
clk429_counter <= 0;
else
clk429_counter <= clk429_counter + 1;
end if;
end if;
end process;
-------------------------------------------------------------------
-------------------------------------------------------------------
-- a429TX interface process
process (clk429, reset)
variable p : std_logic;
begin
if reset = '1' then
state <= IDLE;
shift_reg <= (others => '0');
shift_counter <= (others => '0');
gap_counter <= (others => '0');
a429TX_outA <= '0';
a429TX_outB <= '0';
TX_FIFO_rd <= '0';
elsif rising_edge(clk429) then
case state is
when IDLE => -- idle state
if (enable = '1') then
if (gap = '1') then
gap_counter <= "0000100"; -- 4
else
gap_counter <= "1000000"; -- 64
end if;
if TX_FIFO_ep = '0' then
TX_FIFO_rd <= '1';
state <= START;
else
state <= IDLE;
end if;
else
state <= IDLE;
end if;
when START =>
-- data formatting
TX_FIFO_rd <= '0';
shift_reg <= a429TX_in(31 downto 8)& a429TX_in(0) & a429TX_in(1) & a429TX_in(2) & a429TX_in(3) & a429TX_in(4) & a429TX_in(5) & a429TX_in(6) & a429TX_in(7);
shift_counter <= "11111";
if ( en_parity = '1') then
state <= PAR;
else
state <= TRANSMITTING;
end if;
when PAR => -- parity state
--TX_FIFO_rd <= '0';
p := '0';
for I in 31 downto 0 loop
p := p xor shift_reg(I);
end loop;
if (parity = '1') then
shift_reg(31) <= p; -- odd
else
shift_reg(31) <= not p; -- even
end if;
state <= TRANSMITTING;
when TRANSMITTING => -- transmission state
--TX_FIFO_rd <= '0';
a429TX_outA <= shift_reg(0);
a429TX_outB <= not shift_reg(0);
shift_reg <= shift_reg(0) & shift_reg(31 downto 1);
if (shift_counter = "00000") then
state <= WAITING;
else
shift_counter <= shift_counter -1;
state <= TRANSMITTING;
end if;
when WAITING => -- wait state. generate gap
a429TX_outA <= '0';
a429TX_outB <= '0';
if (gap_counter > 0) then
gap_counter <= gap_counter - 1;
state <= WAITING;
else
state <= IDLE;
end if;
when others => -- default
state <= IDLE;
end case;
elsif falling_edge (clk429) then
a429TX_outA <= '0';
a429TX_outB <= '0';
end if;
end process;
clk429 <= clk429;
end architecture;
Thanks for your help.
Run both FIFOs at the 2 MHz clk2M, and then generate a single cycle enable indication on TX_FIFO_rd when FIFO read data transfer is required.
Thereby you can get the benefit from synchronous design, without the hazzle of handling multiple clock domains.
Also, it is not good (but actually very bad :-) synchronous design practice to generate internal clock like the clk429, since it results in error prune design and more complex timing closure with Static Timing Analysis (STA). Instead make an enable signal that is asserted a single cycle, run the design on the clk2M, and the only update the relevant state when the enable signal is high.

VHDL Vivado Combinatorial Loop Alert

I am trying to implement a simple ALU:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity simple_alu is
Port (
clk : in std_logic;
rst : in std_logic;
op : in std_logic_vector (1 downto 0);
in0 : in std_logic_vector (31 downto 0);
in1 : in std_logic_vector (31 downto 0);
res : out std_logic_vector (31 downto 0);
done_flag : out std_logic
);
end simple_alu;
architecture Behavioral of simple_alu is
type state_type is (start, add, sub, mul, pow, done);
signal state, next_state : state_type := start;
signal status : std_logic := '0';
signal inter, shift_reg, zero : std_logic_vector (31 downto 0) := (others => '0');
begin
SYNC_PROC: process (clk, rst)
begin
if (rst = '0') then
if rising_edge(clk) then
state <= next_state;
res <= inter;
done_flag <= status;
end if;
else
state <= start;
res <= (others => '0');
done_flag <= '0';
end if;
end process;
--MEALY State-Machine - Outputs based on state and inputs
OUTPUT_DECODE: process (state, in0, in1, shift_reg)
variable result, temp : std_logic_vector (31 downto 0);
variable flag : std_logic := '0';
begin
shift_reg <= in1;
temp := temp;
flag := flag;
result := result;
case state is
when start =>
result := std_logic_vector(to_signed(1, 32));
temp := in0;
flag := '0';
when add => result := std_logic_vector(signed(in0) + signed(in1));
when sub => result := std_logic_vector(signed(in0) - signed(in1));
when mul => result := std_logic_vector(resize(signed(in0) * signed(in1), 32));
when pow =>
if (shift_reg(shift_reg'low) = '1') then
result := std_logic_vector(resize(signed(result) * signed(temp), 32));
else
result := result;
end if;
temp := std_logic_vector(resize(signed(temp) * signed(temp), 32));
shift_reg <= std_logic_vector(shift_right(signed(shift_reg), 1));
when done =>
result := result;
flag := '1';
when others =>
end case;
inter <= result;
status <= flag;
end process;
NEXT_STATE_DECODE: process (state, op, shift_reg, zero, rst) -- rst indicates that one input (op, in0 or in1) changed
begin
--declare default state for next_state to avoid latches
next_state <= state; --default is to stay in current state
case (state) is
when start =>
case (op) is
when "00" => next_state <= add;
when "01" => next_state <= sub;
when "10" => next_state <= mul;
when "11" => next_state <= pow;
when others => next_state <= done;
end case;
when add => next_state <= done;
when sub => next_state <= done;
when mul => next_state <= done;
when pow =>
if (shift_reg = zero) then
next_state <= done;
else
next_state <= pow;
end if;
when done =>
if (rst = '1') then
next_state <= start;
end if;
when others =>
end case;
end process;
end Behavioral;
This seems to be working, at least in this testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity simple_alu_tb is
end simple_alu_tb;
architecture Behavioral of simple_alu_tb is
component simple_alu is
Port (
clk : in std_logic;
rst : in std_logic;
op : in std_logic_vector (1 downto 0);
in0 : in std_logic_vector (31 downto 0);
in1 : in std_logic_vector (31 downto 0);
res : out std_logic_vector (31 downto 0);
done_flag : out std_logic
);
end component;
signal clk : std_logic := '0';
signal rst : std_logic := '0';
signal op : std_logic_vector (1 downto 0) := (others => '0');
signal in0 : std_logic_vector (31 downto 0) := (others => '0');
signal in1 : std_logic_vector (31 downto 0) := (others => '0');
signal res : std_logic_vector (31 downto 0) := (others => '0');
signal done_flag : std_logic := '0';
constant clk_period : time := 1 ns;
begin
--Instantiate the Unit Under Test (UUT)
uut: simple_alu Port Map (
clk => clk,
rst => rst,
op => op,
in0 => in0,
in1 => in1,
res => res,
done_flag => done_flag
);
-- Clock process definitions
clk_process :process
begin
clk <= '1';
wait for clk_period/2;
clk <= '0';
wait for clk_period/2;
end process;
stim_proc: process
begin
wait for 2*clk_period;
rst <= '1';
wait for clk_period;
rst <= '0';
wait for 4*clk_period;
op <= "00"; -- add
in0 <= std_logic_vector(to_signed(12, 32));
in1 <= std_logic_vector(to_signed(3, 32));
rst <= '1';
wait for clk_period;
rst <= '0';
wait for 2*clk_period;
assert (res = std_logic_vector(to_signed(15, 32))) report "addition failed" severity failure;
wait for 4*clk_period;
op <= "01"; -- sub
in0 <= std_logic_vector(to_signed(12, 32));
in1 <= std_logic_vector(to_signed(3, 32));
rst <= '1';
wait for clk_period;
rst <= '0';
wait for 2*clk_period;
assert (res = std_logic_vector(to_signed(9, 32))) report "subtraction failed" severity failure;
wait for 4*clk_period;
op <= "10"; -- mul
in0 <= std_logic_vector(to_signed(12, 32));
in1 <= std_logic_vector(to_signed(3, 32));
rst <= '1';
wait for clk_period;
rst <= '0';
wait for 2*clk_period;
assert (res = std_logic_vector(to_signed(36, 32))) report "multiplication failed" severity failure;
wait for 4*clk_period;
op <= "11"; -- pow
in0 <= std_logic_vector(to_signed(12, 32));
in1 <= std_logic_vector(to_signed(7, 32));
rst <= '1';
wait for clk_period;
rst <= '0';
wait for 4*clk_period;
assert (res = std_logic_vector(to_signed(35831808, 32))) report "power failed" severity failure;
wait for 4*clk_period;
op <= "11"; -- pow
in0 <= std_logic_vector(to_signed(12, 32));
in1 <= std_logic_vector(to_signed(6, 32));
rst <= '1';
wait for clk_period;
rst <= '0';
wait for 4*clk_period;
assert (res = std_logic_vector(to_signed(2985984, 32))) report "power failed" severity failure;
wait;
end process;
end Behavioral;
I would like to implement that as AXI4-lite component. So I generate the wrapper, adapt the write process and instantiate my module as follows:
...
process (S_AXI_ACLK)
variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0);
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
-- command_reg <= (others => '0');
-- done_flag <= '0';
slv_reg1 <= (others => '0');
slv_reg2 <= (others => '0');
-- slv_reg3 <= (others => '0');
else
loc_addr := axi_awaddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB);
if (slv_reg_wren = '1') then
case loc_addr is
when b"00" =>
for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-4) loop -- write to command register only
if ( S_AXI_WSTRB(byte_index) = '1' ) then
-- Respective byte enables are asserted as per write strobes
-- slave registor 0
command_reg(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
end if;
end loop;
when b"01" =>
for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
if ( S_AXI_WSTRB(byte_index) = '1' ) then
-- Respective byte enables are asserted as per write strobes
-- slave registor 1
slv_reg1(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
end if;
end loop;
when b"10" =>
for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
if ( S_AXI_WSTRB(byte_index) = '1' ) then
-- Respective byte enables are asserted as per write strobes
-- slave registor 2
slv_reg2(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
end if;
end loop;
-- when b"11" => -- do not write to reg3
-- for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
-- if ( S_AXI_WSTRB(byte_index) = '1' ) then
-- -- Respective byte enables are asserted as per write strobes
-- -- slave registor 3
-- slv_reg3(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
-- end if;
-- end loop;
when others =>
command_reg <= command_reg;
done_flag <= done_flag;
slv_reg1 <= slv_reg1;
slv_reg2 <= slv_reg2;
-- slv_reg3 <= slv_reg3;
end case;
end if;
end if;
end if;
end process;
...
-- Add user logic here
-- byte0 byte1 byte2 byte3
slv_reg0 <= done_flag & "0000000" & "00000000" & "00000000" & command_reg;
alu : simple_alu
port map (
clk => S_AXI_ACLK,
rst => slv_reg_wren, -- reset on every write to a register, high active
op => command_reg(1 downto 0),
in0 => slv_reg1,
in1 => slv_reg2,
res => slv_reg3,
done_flag => done_flag
);
-- User logic ends
But when I try to generate the bitstream for my wrapper design which includes the Zync UltraScale+ MPSoC, AXI Interconnect, Processor System Reset and my AXI Peripheral I get the following error:
ERROR: [DRC LUTLP-1] Combinatorial Loop Alert: 1 LUT cells form a combinatorial loop. This can create a race condition. Timing analysis may not be accurate. The preferred resolution is to modify the design to remove combinatorial logic loops. If the loop is known and understood, this DRC can be bypassed by acknowledging the condition and setting the following XDC constraint on any one of the nets in the loop: 'set_property ALLOW_COMBINATORIAL_LOOPS TRUE [get_nets <myHier/myNet>]'. One net in the loop is design_1_i/simple_alu_0/U0/simple_alu_v1_0_S00_AXI_inst/alu/state[0]_i_2_n_0. Please evaluate your design. The cells in the loop are: design_1_i/simple_alu_0/U0/simple_alu_v1_0_S00_AXI_inst/alu/state[0]_i_2.
ERROR: [DRC LUTLP-1] Combinatorial Loop Alert: 1 LUT cells form a combinatorial loop. This can create a race condition. Timing analysis may not be accurate. The preferred resolution is to modify the design to remove combinatorial logic loops. If the loop is known and understood, this DRC can be bypassed by acknowledging the condition and setting the following XDC constraint on any one of the nets in the loop: 'set_property ALLOW_COMBINATORIAL_LOOPS TRUE [get_nets <myHier/myNet>]'. One net in the loop is design_1_i/simple_alu_0/U0/simple_alu_v1_0_S00_AXI_inst/alu/state[1]_i_3_n_0. Please evaluate your design. The cells in the loop are: design_1_i/simple_alu_0/U0/simple_alu_v1_0_S00_AXI_inst/alu/state[1]_i_3.
Please excuse the huge amount of code, I couldn't find a way to show the error with a smaller example.
I tried the solution proposed here:
set_property SEVERITY {Warning} [get_drc_checks LUTLP-1]
But that did nothing. I also tried setting set_property ALLOW_COMBINATORIAL_LOOPS TRUE for the two nets but that leaves me unsure about the functionality of my circuit. I am using Vivado v2018.3, my target is the Ultra96 from Avnet. Any clues?
EDIT: I have updated the code to reflect the current implementation, I get warnings about latches for result_reg, flag_reg and temp_reg. How do I resolve those?
After a long struggle I finally came up with this solution:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity simple_alu is
Port (
clk : in std_logic;
rst : in std_logic;
op : in std_logic_vector (1 downto 0);
in0 : in std_logic_vector (31 downto 0);
in1 : in std_logic_vector (31 downto 0);
res : out std_logic_vector (31 downto 0);
done_flag : out std_logic
);
end simple_alu;
architecture Behavioral of simple_alu is
type state_type is (start, add, sub, mul, pow, done);
signal state, next_state : state_type := start;
signal result, next_result, temp, next_temp, shift_reg, next_shift_reg, zero : std_logic_vector (31 downto 0) := (others => '0');
signal next_done_flag : std_logic := '0';
begin
SYNC_PROC: process (clk, rst)
begin
if rising_edge(clk) then
if (rst = '1') then
state <= start;
else
state <= next_state;
res <= next_result;
result <= next_result;
temp <= next_temp;
shift_reg <= next_shift_reg;
done_flag <= next_done_flag;
end if;
end if;
end process;
--MEALY State-Machine - Outputs based on state and inputs
OUTPUT_DECODE: process (state, result, in0, in1, temp, shift_reg)
begin
next_done_flag <= '0';
next_result <= result;
next_shift_reg <= shift_reg;
next_temp <= temp;
case state is
when start =>
next_result <= std_logic_vector(to_signed(1, 32));
next_temp <= in0;
next_shift_reg <= in1;
when add => next_result <= std_logic_vector(signed(in0) + signed(in1));
when sub => next_result <= std_logic_vector(signed(in0) - signed(in1));
when mul => next_result <= std_logic_vector(resize(signed(in0) * signed(in1), 32));
when pow =>
if (shift_reg(shift_reg'low) = '1') then
next_result <= std_logic_vector(resize(signed(result) * signed(temp), 32));
else
next_result <= result;
end if;
next_temp <= std_logic_vector(resize(signed(temp) * signed(temp), 32));
next_shift_reg <= std_logic_vector(shift_right(signed(shift_reg), 1));
when done => next_done_flag <= '1';
when others =>
end case;
end process;
NEXT_STATE_DECODE: process (state, op, shift_reg, zero)
begin
--declare default state for next_state to avoid latches
next_state <= state; --default is to stay in current state
case (state) is
when start =>
case (op) is
when "00" => next_state <= add;
when "01" => next_state <= sub;
when "10" => next_state <= mul;
when "11" => next_state <= pow;
when others => next_state <= done;
end case;
when add => next_state <= done;
when sub => next_state <= done;
when mul => next_state <= done;
when pow =>
if (shift_reg = zero) then
next_state <= done;
else
next_state <= pow;
end if;
when done =>
when others =>
end case;
end process;
end Behavioral;
The problem was that I did not understand how hardware description works, now I know a little (at least I hope so..). Especially how clocked and unclocked processes are connected (save intermediate results in registers). I will leave this question up just in case another beginner stumbles upon the same issue. If you think I should remove it, please state that in a comment and I will do so.
Here are some resources that helped me:
this question and in particular the accepted answer
some rules I picked up somewhere:
Don't read from the signals to which you write.
Have a correct sensitivity list (all signals that you read should be in the sensitivity list)
Make sure that all signals to which your write are assigned in every path. (for example: in each branch of an if-else-statement)
For processes which use variable, make sure every variable is initialized a default value before reading it (in another variable or signal ).

What is Simulator 45-1 Error in Xilinx Vivado?

I have been trying to make a generic sequence detector. When i try to simulate my design, I get a simulator 45-1 Fatal run time error. Can somebody please help me with this. Here is my Test bench and design.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Sequence_tb is
end Sequence_tb;
architecture Behavioral of Sequence_tb is
component sequence is
Generic(width: integer;
sequence: std_logic_vector);
Port(din,CLK,RST:in std_logic;
dout: out std_logic;
temp: buffer std_logic_vector(0 to width-1));
end component;
constant CLK_period: time := 10ns;
constant width: integer := 4;
constant sequence0: std_logic_vector(width-1 downto 0) := "1010";
signal din,CLK,RST,dout: std_logic := '0';
signal temp : std_logic_vector(0 to width-1) := (others=>'0');
begin
uut: sequence generic map(width=>width,sequence=>sequence0)
port map(din=>din,CLK=>CLK,RST=>RST,dout=>dout,temp=>temp);
CLK_proc: process
begin
CLK <= not CLK;
wait for CLK_period;
end process;
RST_proc: process
begin
RST <= '1';
wait for 20 ns;
RST <= '0';
wait;
end process;
din_proc: process
begin
din <= '1';
wait for 30 ns;
din <= '0';
wait for 10 ns;
din <= '1';
wait for 10 ns;
din <= '0';
wait for 10 ns;
din <= '1';
wait for 10 ns;
wait;
end process;
end Behavioral;
Design File:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Sequence is
Generic(width: integer;
sequence: std_logic_vector);
Port (din, CLK, rst: in std_logic;
dout: out std_logic;
temp: buffer std_logic_vector(0 to width-1));
end Sequence;
architecture Beh of Sequence is
subtype statetype is integer range 0 to width-1;
signal prstate,nxstate: statetype := 0;
begin
process(RST,CLK)
begin
if RST='1' then
temp <= (others => '0');
nxstate <= 0;
elsif CLK'event and CLK='1' then
temp(prstate) <= din;
for k in prstate downto 0 loop
if temp(k downto 0) = sequence(k downto 0) then
nxstate <= k;
exit;
else temp <= temp(1 to width-1) & '0';
end if;
end loop;
end if;
prstate <= nxstate;
end process;
dout <= '1' when prstate = width-1 and din = sequence(sequence'left) else '0';
end Beh;

Configuring an RS232 to USB cable with VHDL

i'm in the process of configuring an RS232 to USB cable with VHDL and i seem to have a problem. I don't know how to configure a dual-port RAM. I have attempted searching on answers to that and i found some code but i don't completely understand how to apply this code. This code can be found in this link --> http://www.asic-world.com/examples/vhdl/ram_dp_ar_aw.html.
Please help as soon as possible, i'm in desperate need of this information.
----------------------------------------------------------------------------------
-- Create Date : 14:06:22 12/08/2013
-- Designer Name : Sarin anand k
-- Module Name : UART - Behavioral
-- Project Name : RS232 transmitter
----------------------------------------------------------------------------------
-- spartan 3 starter kit
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use ieee.std_logic_unsigned.all;
library UNISIM;
use UNISIM.VComponents.all;
entity uart is
port(
sys_clk : in std_logic; --50Mhz
reset : in std_logic;
data_in : in std_logic_vector(7 downto 0); -- switch
load : in std_logic; --push button
Tx : out std_logic
);
end uart;
architecture Behavioral of uart is
type T_state is (IDLE,STORAGE,START, DATA, STOP);
-- baud rate = 115200, bit duration required is 1/115200 = 8680 ns
-- for a 50MHz clock, period is 20 ns. So each bit is 8680/20 = 434 clock cycles
constant bit_dur : std_logic_vector(15 downto 0) := X"01B3"; -- 434 clocks
constant start_bit : std_logic := '0';
constant stop_bit : std_logic := '1';
signal baud_cnt : std_logic_vector(23 downto 0) := X"000000"; -- 115200
signal baud_en : std_logic;
signal temp : std_logic_vector(7 downto 0);
signal baud_rate_cnt : std_logic_vector(7 downto 0):=(others => '0');
signal bit_cnt_start : std_logic;
signal baud_flag : std_logic;
signal state : T_state;
begin
-----------------------------------------------------------------------------------------------------
---- baud clock
------------------------------------------------------------------------------------------------------
baud_rate: process(sys_clk) begin
if rising_edge(sys_clk) then
if (reset = '1') then
baud_cnt <= X"000000";
baud_en <= '0';
end if;
if (baud_cnt = bit_dur)then
baud_en <= '1'; -- data in flag
baud_cnt <= X"000000";
elsif(bit_cnt_start = '1') then
baud_cnt<= baud_cnt + '1';
baud_en <= '0';
end if;
end if;
end process baud_rate;
---------------------------------------------------------------------------------------------------------------
-- baud clock counter
----------------------------------------------------------------------------------------------------------------
baud_counter: process(sys_clk) begin
if(rising_edge (sys_clk)) then
if(reset = '1') then
baud_rate_cnt <=( others => '0');
baud_flag <= '0';
end if;
if( baud_rate_cnt = "1000") then
baud_flag <= '1';
baud_rate_cnt <=( others => '0');
elsif( state = DATA and baud_en ='1') then
baud_rate_cnt <= baud_rate_cnt + '1';
baud_flag <= '0';
end if;
end if;
end process baud_counter;
--------------------------------------------------------------------------------------------------------------------
-- State machine to control the data flow
----------------------------------------------------------------------------------------------------------------------
control_flow: process (sys_clk) begin
if(rising_edge (sys_clk)) then
if (reset = '1') then
bit_cnt_start <= '0';
state <= IDLE;
end if;
case state is
when IDLE =>
state <= STORAGE;
when STORAGE =>
if (load = '1') then
state <= START;
bit_cnt_start <= '1';
end if;
when START =>
if (baud_en ='1') then
state <= DATA;
end if;
when DATA =>
if ((baud_en ='1') and (baud_flag = '1')) then
state <= STOP;
end if;
when STOP =>
if (baud_en = '1') then
state <= IDLE;
bit_cnt_start <= '0';
end if;
when others =>
state <= IDLE;
end case;
end if;
end process control_flow;
------------------------------------------------------------------------------------------------------------------------
-- Data Transmission
-------------------------------------------------------------------------------------------------------------------------
data_trans: process (sys_clk) begin
if (rising_edge(sys_clk)) then
if (reset = '1') then
temp <= (others => '0');
end if;
-- Data Mux
case state is
when IDLE =>
temp <= (others => '0');
when STORAGE =>
temp <= data_in;
when START =>
Tx <= start_bit;
when DATA =>
Tx <= temp(0);
if ( baud_en = '1') then
temp <= '0' & temp(7 downto 1) ;
Tx <= temp(0);
end if;
when STOP =>
Tx <= stop_bit;
when others =>
Tx <= '1';
end case;
end if;
end process data_trans;
end Behavioral;

VHDL Counter result giving X

I am attempting to build a counter in VHDL. Eventual goal is to hook the "do_count" to a button. The total will be converted to BCD and displayed on a 7-segment display. Push the button, watch the numbers increment.
I'm using ModelSim and I can see the internal "counter_value" correctly increment by 1. But the output signal "total" becomes "000X" then "00X0" during my two test "do_count"s. Why am I getting an X'd signal?
I've moved the "output <= current_value" around inside the process, outside the process, inside the 'if's, etc. Still the "000X".
I've tried using a variable 'tmp' inside the process.
count_up : process(clk) is
variable tmp : unsigned (15 downto 0 );
begin
tmp := current_value;
-- snip
if do_count='1' then
current_value <= tmp + to_unsigned(1,16);
end if;
Still I get the "000X".
Full code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity d_counter is
port ( rst : in std_logic;
clk : in std_logic;
do_count : in std_logic;
total : out unsigned (15 downto 0)
);
end entity d_counter;
architecture counter_arch of d_counter is
signal current_value : unsigned (15 downto 0) := (others=>'0');
begin
count_up : process(clk) is
begin
if rst='1' then
current_value <= (others=>'0');
total <= (others=>'0');
elsif rising_edge(clk) then
if do_count='1' then
current_value <= current_value + to_unsigned(1,16);
end if;
end if;
end process count_up;
total <= current_value;
end architecture counter_arch;
Testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity test_counter is
begin
end entity test_counter;
architecture run_test_counter of test_counter is
signal t_rst : std_logic := '1';
signal t_clk : std_logic := '0';
signal t_do_count : std_logic;
signal t_total : unsigned( 15 downto 0 );
component d_counter is
port ( rst : in std_logic;
clk : in std_logic;
do_count : in std_logic;
total : out unsigned( 15 downto 0 )
);
end component d_counter;
begin
uut : d_counter
port map( rst => t_rst,
clk => t_clk,
do_count => t_do_count,
total => t_total );
clock : process is
begin
t_clk <= '0'; wait for 10 ns;
t_clk <= '1'; wait for 10 ns;
end process clock;
stimulus : process is
begin
t_rst <= '1';
t_do_count <= '0';
t_total <= (others =>'0');
wait for 15 ns;
t_rst <= '0';
wait for 10 ns;
t_do_count <= '1';
wait for 10 ns;
t_do_count <= '0';
wait for 10 ns;
t_do_count <= '1';
wait for 10 ns;
t_do_count <= '0';
wait for 10 ns;
wait;
end process stimulus;
end architecture run_test_counter;
Update 03-Oct-2012.
BOTH the answers helped. Moving "total <= current_value" inside the process (From #simon) and removing the extra "t_total <= (others =>'0');" (From #peter-bennett) in my testbench was required. I had to do both to get rid of the X's.
It looks like your mistake is in your testbench. The signal t_total is mapped to the total output of your counter component, yet you are writing to it with the t_total <= (others => '0') assignment. If you remove this I think your problem will go away.
uut : d_counter
port map( rst => t_rst,
clk => t_clk,
do_count => t_do_count,
total => t_total );
clock : process is
begin
t_clk <= '0'; wait for 10 ns;
t_clk <= '1'; wait for 10 ns;
end process clock;
stimulus : process is
begin
t_rst <= '1';
t_do_count <= '0';
t_total <= (others =>'0'); <-- Do not assign to t_total (its an output)
Your code write multi-driven with "total". You should delete assigment in process count_up.
count_up : process(clk) is
begin
if rst='1' then
current_value <= (others=>'0');
total <= (others=>'0'); --> Remove it
elsif rising_edge(clk) then
if do_count='1' then
current_value <= current_value + to_unsigned(1,16);
end if;
end if;
end process count_up;
total <= current_value; -- Keep it

Resources