Synthesizable wait statement in VHDL - vhdl

I am writing a VHDL code to control AD7193 via SPI communication. ADC is controlled and configured via number of con-chip registers, DOUT/RDY (SPI_miso) goes low to indicate the completion of conversion. These are the code and timing characteristics (Please see Here) of AD7193.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity MainADC is port (
clk : in std_logic; -- OSC 50MHz
rst : in std_logic; -- Reset clock
sclk : out std_logic; -- out clock
cs : out std_logic; -- Chip select
spi_mosi: out std_logic; -- Write register
start : in std_logic; -- Start Conversion
spi_miso: in std_logic); -- Read register/Single channel, 24 bits
end MainADC;
architecture Behavior of MainADC is
signal outclk : std_logic;
signal clk_sel : std_logic; -- Clock Control
signal CommMode: std_logic_vector(7 downto 0) :="00001000"; -- Communications register==> next stage: Mode Register
signal Mode : std_logic_vector(23 downto 0) := "001010000000000001100000"; -- Single conversion mode
signal CommRead: std_logic_vector(7 downto 0) := "01011000"; -- Communications register==> next stage: Read Data
begin
cs <= '0'; -- Hardwired low
process(clk, rst) -- Clock_gen 500KHz
variable cnt : integer range 0 to 500 :=1;
begin
if (rst='1') then
cnt := 0;
outclk <= '0';
elsif (clk = '1' and clk'event) then
cnt := cnt + 1;
if (cnt = 50) then
cnt := 0;
outclk <= not outclk;
end if;
end if;
end process;
process(clk_sel)
begin
if (clk_sel='0') then
sclk <= '1'; --Clock Idle High
else
sclk <= outclk; --Provide Clock Cycles
end if;
end process;
process (outclk) -- SPI Comm
variable i : integer :=0;
variable data_temp: std_logic_vector(23 downto 0) :=(others=>'0');
begin
if (start = '0') then
clk_sel <= '0';
i:=0;
else
if falling_edge(outclk) then
i:=i+1;
if (i>=0 and i<=7) then -- Communications register==> next stage: Mode Register (8 bits)
clk_sel <= '1';
CommMode(7 downto 1) <= CommMode(6 downto 0);
CommMode(0) <= CommMode(7);
spi_mosi <= CommMode(7);
elsif (i=8) then
clk_sel <= '0'; --Clock Idle High
elsif (i>=9 and i<=32) then -- Single conversion mode (24 bits)
clk_sel <= '1';
Mode(23 downto 1) <= Mode(22 downto 0);
Mode(0) <= Mode(23);
spi_mosi <= Mode(23);
elsif (i=33) then
clk_sel <= '0'; --Clock Idle High
wait until (spi_miso'event and spi_miso='0'); --Wait for Ready Read Signal (DOUT/DRY)
elsif (i>=34 and i<= 41) then -- Communications register==> next stage: Read Data
clk_sel <= '1';
CommRead(7 downto 1) <= CommRead(6 downto 0);
CommRead(0) <= CommRead(7);
spi_mosi <= CommRead(7);
elsif (i=42) then
clk_sel <= '0'; --Clock Idle High
elsif (i>=43 and i<= 66) then
clk_sel <= '1';
data_temp(23 downto 0) := data_temp(22 downto 0) & spi_miso; --Read Data
elsif (i>=66 and i<=566) then -- Waiting for ADC Power Up after Conversion (~1ms)
clk_sel <= '0'; --Clock Idle High
elsif (i=567) then
i:=0;
end if;
end if;
end if;
end process;
end Behavior;
As far as I know Wait Until statement supports for vhdl synthesis, but I received this error: "Error (10441): VHDL Process Statement error at Main ADC.vhd(53): Process Statement cannot contain both a sensitivity list and a Wait Statement". How can I solve this error? Is there any other way to hold counter and waiting for DOUT/RDY event to know when conversion is complete for read data? Any opinions are appreciated! Thank you.

The error message is due to a VHDL language semantic restriction.
The wait until implies you're using spi_miso as a clock, and it looks like you're requiring a flip flop to toggle as a result of i counter reaching 33, before progressing to 34.
The error about the sensititvity list item (outclock) and the wait statement is telling you you can't use two different clocks in this process.
If there is no metastability issue with outclk, instead of waiting don't increment i unless spio_miso = 0 when i = 33. You could also evaluate i before incrementing it (the equivalent of making i a signal).
This may deserve simulation before synthesis. There may be other issues lurking in there.
Your VHDL analyzes with a couple of changes:
if falling_edge(outclk) then
if ( i /= 33 or spi_miso = '0' ) then
i:= i + 1;
end if;
if (i>=0 and i<=7) then -- Communications register==> next stage: Mode Register (8 bits)
clk_sel <= '1';
CommMode(7 downto 1) <= CommMode(6 downto 0);
CommMode(0) <= CommMode(7);
spi_mosi <= CommMode(7);
elsif (i=8) then
clk_sel <= '0'; --Clock Idle High
elsif (i>=9 and i<=32) then -- Single conversion mode (24 bits)
clk_sel <= '1';
Mode(23 downto 1) <= Mode(22 downto 0);
Mode(0) <= Mode(23);
spi_mosi <= Mode(23);
-- elsif (i=33) then
-- clk_sel <= '0'; --Clock Idle High
-- wait until (spi_miso'event and spi_miso='0'); --Wait for Ready Read Signal (DOUT/DRY)
elsif (i>=34 and i<= 41) then -- Communications register==>
(And I normally wouldn't put parentheses around an if statement expression.)

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 VGA sync circuit

Can some one please tell me how this circuit increments h_count_reg and v_count_reg?? I don't really see it. Also what do they mean by the output is buffered exactly? It's just delayed by one pixel? don't really see that either. thanks!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity vgaController is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
hsync : out STD_LOGIC;
vsync : out STD_LOGIC;
video_on : out STD_LOGIC;
p_tick : out STD_LOGIC;
pixel_x : out STD_LOGIC_VECTOR (9 downto 0);
pixel_y : out STD_LOGIC_VECTOR (9 downto 0));
end vgaController;
architecture Behavioral of vgaController is
-- VGA 640 -by - 480 sync p a r a m e t e r s
constant HD: integer:=640; --horizontal display area
constant HF: integer:=16 ; --h. front porch
constant HB: integer:=48 ; --h. back porch
constant HR: integer:=96 ; --h. retrace "Sync Pulse"
constant VD: integer:=480; -- vertical display area
constant VF: integer:=10 ; -- v. front porch
constant VB: integer:=33 ; -- v. back porch
constant VR: integer:=2 ; -- v. retrace "sync pulse"
-- mod-2 counter
signal mod2_reg, mod2_next : std_logic;--mod-2 counter to generate the 25-MHz enable tick
-- sync counters, two counters for the horizontal and vertical scans
signal v_count_reg, v_count_next : unsigned(9 downto 0);
signal h_count_reg, h_count_next : unsigned(9 downto 0);
--To remove
--potential glitches, output buffers are inserted for the hsync and vsync signals. This leads
--to a one-clock-cycle delay. add a similar buffer for the rgb signal in the pixel
--generation circuit to compensate for the delay.
-- output buffer
signal v_sync_reg, h_sync_reg: std_logic;
signal v_sync_next ,h_sync_next : std_logic;
--status signal
signal h_end , v_end , pixel_tick: std_logic;
begin
--register
process(clk,reset)
begin
if (reset='1') then
mod2_reg <='0';
v_count_reg <=(others=>'0');
h_count_reg <=(others=>'0');
v_sync_reg <='0';
h_sync_reg <='0';
elsif(clk'event and clk='1')then
mod2_reg <=mod2_next;
v_count_reg <=v_count_next;
h_count_reg <=h_count_next;
v_sync_reg <=v_sync_next;
h_sync_reg <=h_sync_next;
end if;
end process;
--mod-2 circuit to generate 25 MHz enable tick
mod2_next <= not mod2_reg;
-- 25 MHz pixel tick
pixel_tick <= '1' when mod2_reg = '1' else '0';
--status
h_end <= --end of horizonal counter
'1' when h_count_reg = (HD+HF+HB+HR-1) else --799
'0';
v_end <= --end of vertial counter
'1' when v_count_reg = (VD+VF+VB+VR-1) else --524
'0';
-- mod-800 horizontal sync counter
process(h_count_reg,h_end,pixel_tick)
begin
if (pixel_tick='1') then --25 MHz tick
if h_end='1' then
h_count_next <= (others=>'0');
else
h_count_next <= h_count_reg+1;
end if;
else
h_count_next <= h_count_reg;
end if;
end process;
-- mode-525 vertical sync counter
process(v_count_reg,h_end,v_end,pixel_tick)
begin
if (pixel_tick='1' and h_end='1') then
if (v_end='1') then
v_count_next <= (others=>'0');
else
v_count_next <= v_count_reg+1;
end if;
else
v_count_next <= v_count_reg;
end if;
end process;
-- horizontal and vertial sync, buffered to avoid glitch
h_sync_next <=
'1' when (h_count_reg >= (HD+HF)) --656
and (h_count_reg <= (HD+HF+HR-1)) else --751
'0';
v_sync_next <=
'1' when (v_count_reg >= (VD+VF)) --490
and (v_count_reg <= (VD+VF+VR-1)) else --491
'0';
--video on/off
video_on <= '1' when (h_count_reg < HD) and (v_count_reg < VD) else '0';
--output signals
hsync <= h_sync_reg;
vsync <= v_sync_reg;
pixel_x <= std_logic_vector(h_count_reg);
pixel_y <= std_logic_vector(v_count_reg);
p_tick <= pixel_tick;
end Behavioral;
The vertical and horizontal counters are spread across two processes:
--register
process(clk,reset)
begin
if (reset='1') then
mod2_reg <='0';
v_count_reg <=(others=>'0');
h_count_reg <=(others=>'0');
v_sync_reg <='0';
h_sync_reg <='0';
elsif(clk'event and clk='1')then
mod2_reg <=mod2_next;
v_count_reg <=v_count_next;
h_count_reg <=h_count_next;
v_sync_reg <=v_sync_next;
h_sync_reg <=h_sync_next;
end if;
end process;
Where in the elsif condition the counters are loaded from v_count_next and h_count_next, which are produced in two different processes:
-- mod-800 horizontal sync counter
process(h_count_reg,h_end,pixel_tick)
begin
if (pixel_tick='1') then --25 MHz tick
if h_end='1' then
h_count_next <= (others=>'0');
else
h_count_next <= h_count_reg+1;
end if;
else
h_count_next <= h_count_reg;
end if;
end process;
-- mode-525 vertical sync counter
process(v_count_reg,h_end,v_end,pixel_tick)
begin
if (pixel_tick='1' and h_end='1') then
if (v_end='1') then
v_count_next <= (others=>'0');
else
v_count_next <= v_count_reg+1;
end if;
else
v_count_next <= v_count_reg;
end if;
end process;
(And about now you could imagine it's a good idea to actually label process statements).
As far as the "buffered":
--To remove
--potential glitches, output buffers are inserted for the hsync and vsync signals. This leads
--to a one-clock-cycle delay. add a similar buffer for the rgb signal in the pixel
--generation circuit to compensate for the delay.
-- output buffer
signal v_sync_reg, h_sync_reg: std_logic;
signal v_sync_next ,h_sync_next : std_logic;
--status signal
signal h_end , v_end , pixel_tick: std_logic;
Those are the last two assignments in the --register process above. And from the comments the one clock delay through flip flops is to remove combinatoric glitches caused by relational operators:
h_sync_next <=
'1' when (h_count_reg >= (HD+HF)) --656
and (h_count_reg <= (HD+HF+HR-1)) else --751
'0';
v_sync_next <=
'1' when (v_count_reg >= (VD+VF)) --490
and (v_count_reg <= (VD+VF+VR-1)) else --491
'0';
Just for interest, here's a single-process refactoring of the above.
It's considerably shorter and, to my eyes at least, much easier to understand, modify and get right. Multiple trivial processes with unnecessary signals simply to communicate between them obscure the design (as you noted!) - and provide a fertile breeding ground for bugs.
One warning : I have not verified that this is an exact implementation of your design; if you choose to use it, that would be your responsibility.
Opinions welcome.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity vgaController is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
hsync : out STD_LOGIC;
vsync : out STD_LOGIC;
video_on : out STD_LOGIC;
p_tick : out STD_LOGIC;
pixel_x : out STD_LOGIC_VECTOR (9 downto 0);
pixel_y : out STD_LOGIC_VECTOR (9 downto 0));
end vgaController;
architecture Behavioral of vgaController is
-- VGA 640 -by - 480 sync p a r a m e t e r s
constant HD: integer:=640; --horizontal display area
constant HF: integer:=16 ; --h. front porch
constant HB: integer:=48 ; --h. back porch
constant HR: integer:=96 ; --h. retrace "Sync Pulse"
constant VD: integer:=480; -- vertical display area
constant VF: integer:=10 ; -- v. front porch
constant VB: integer:=33 ; -- v. back porch
constant VR: integer:=2 ; -- v. retrace "sync pulse"
-- derived constants to make code clearer
constant H_Last : integer := HD+HF+HB+HR-1;
constant H_Sync_First : integer := HD+HF;
constant H_Sync_Last : integer := HD+HF+HR-1;
constant V_Last : integer := VD+VF+VB+VR-1;
constant V_Sync_First : integer := VD+VF;
constant V_Sync_Last : integer := VD+VF+VR-1;
-- sync counters, two counters for the horizontal and vertical scans
signal v_count : unsigned(9 downto 0);
signal h_count : unsigned(9 downto 0);
--status signal
signal pixel_tick: std_logic;
begin
--register
process(clk,reset)
begin
if (reset='1') then
pixel_tick <= '0';
v_count <= (others=>'0');
h_count <= (others=>'0');
vsync <= '0';
hsync <= '0';
elsif(clk'event and clk='1')then
pixel_tick <= not pixel_tick;
-- H and V pixel counters
if pixel_tick = '1' then
if h_count = h_last then
h_count <= (others=>'0');
-- and start the next line
if v_count = v_last then
v_count <= (others=>'0');
else
v_count <= v_count + 1;
end if;
else
h_count <= h_count + 1;
end if;
end if;
-- default assignments for sync
hsync <= '0';
vsync <= '0';
-- H and V sync pulses
if h_count >= H_Sync_First and h_count <= H_Sync_Last then
hsync <= '1';
end if;
if v_count >= V_Sync_First and v_count <= V_Sync_Last then
vsync <= '1';
end if;
end if;
end process;
--video on/off ... was unregistered so I'll leave it that way
video_on <= '1' when (h_count < HD) and (v_count < VD) else '0';
--output signals
pixel_x <= std_logic_vector(h_count);
pixel_y <= std_logic_vector(v_count);
p_tick <= pixel_tick;
end Behavioral;
The buffers (register is a better name, because it's not an output buffer) are needed -- not only to suppress glitches --, but rather then to ensure equal output delay timings for every pin (v_sync, h_sync and color). If you do not use the registers before your downstream output buffer, you will get bad color effects on the screen.
Please be aware, that your x,y coordinate counter circuit addresses the next pixel not the current. So there must be a delays between the counter values and h/v_sync depending on the delay between counter -> get-pixel-information -> pixel color output.

Asynchrony in vhdl: SPI Slave - Low VIOLATION issue on post-route simulation

I have implemented very simple SPI slave interface: 8 bit, MSB first, pol=1 pha=1. CS pin and 'Z' state of SO is not required. Max SPI SCK is 8 MHz. System clock 50 MHz
Code:
entity spi_slave_if is Port (
si : in STD_LOGIC;
sck : in STD_LOGIC;
so : out STD_LOGIC;
clk : in std_logic;
reset : in std_logic;
data_out : in std_logic_vector(7 downto 0); -- data for send
data_in : out std_logic_vector(7 downto 0); -- received data
transaction_done : out std_logic);
end spi_slave_if;
architecture Behavioral of spi_slave_if is
signal cur_bit, prev_bit: unsigned(2 downto 0);
begin
process(sck) begin
if falling_edge(sck) then
so <= data_out(to_integer(cur_bit));
end if;
end process;
process(sck, reset) begin
if (reset = '1') then
data_in <= (others => '0');
cur_bit <= to_unsigned(7, 3);
elsif rising_edge(sck) then
data_in(to_integer(cur_bit)) <= si;
cur_bit <= cur_bit - 1;
end if;
end process;
process(clk, reset)
variable td_raised: boolean;
begin
if reset = '1' then
prev_bit <= to_unsigned(7, 3);
td_raised := false;
transaction_done <= '0';
elsif falling_edge(clk) then
prev_bit <= cur_bit;
if td_raised then
transaction_done <= '0';
td_raised := false;
elsif (to_integer(prev_bit) = 0 and to_integer(cur_bit) = 7 ) then
transaction_done <= '1';
td_raised := true;
end if;
end if;
end process;
end Behavioral;
In testbench I try to model async master interface(with random data bytes) and random delays:
loop
UNIFORM(seed1, seed2, rand);
int_rand := INTEGER(TRUNC(rand*255.0)); -- rescale to 0..255
test_1_transact(125 ns, std_logic_vector(to_unsigned(int_rand, 8)));
wait for 1us; -- model async delay
wait for ((rand*0.00000001)*1 sec);
wait for ((rand*0.000000001)*1 sec);
wait for ((rand*0.0000000001)*1 sec);
end loop;
Where test_1_transact is:
procedure test_1_transact(constant prd : time; constant si_data &colon; std_logic_vector (7 downto 0)) is begin
data_out <= not si_data; --for back test invert dorward data
wait for 20ns; -- wait for data apply
FOR i IN 7 downto 0 LOOP
si <= si_data(i);
sck <= '0'; wait for prd / 2;
sck <= '1'; wait for prd / 2;
END LOOP;
end procedure;
When I do behevioral simulation code works fine all time.
But when I try to perform post route simulation, code also works first 47us, but then it failed, ISIM say me:
at 49422978 ps(3), Instance /test_spi_slv_if/uut/prev_bit_0/ : Warning: /X_FF HOLD Low VIOLATION ON I WITH RESPECT TO CLK;
Expected := 0.048 ns; Observed := 0.036 ns; At : 49422.978 ns
at 49922978 ps(3), Instance /test_spi_slv_if/uut/prev_bit_0/ : Warning: /X_FF HOLD Low VIOLATION ON I WITH RESPECT TO CLK;
Expected := 0.048 ns; Observed := 0.036 ns; At : 49922.978 ns
And on this moment transaction_done don't work.
Is there in vhdl some way to solve this?

Bit shift register vhdl varying size

I'm trying to get two outputs (pulse(0) and pulse(1)) to deliver a short one clock pulse. The latency between these pulses needs to be controlled by some input value. So 0x1 = 1 clock cycle etc.
At the moment, once the trigger switches on, it stays on
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use work.ipbus.all;
<...snip>
architecture rtl of trig_latency is
signal ack : std_logic;
signal s_level : unsigned(pulse'range);
signal s_level_d1 : std_logic;
signal bit_shift : std_logic_vector(addr_width downto 0);
signal latency: integer:=5;
begin
latency <= to_integer(unsigned(in_data(addr_width -1 downto 0))) when addr_width > 0 else 0;
process(clk)
begin
if rising_edge(clk) then
if ipbus_in.ipb_strobe='1' and ipbus_in.ipb_write = '1' then
s_level <= s_level + 1;
s_level_d1<=s_level(s_level'left);
else
s_level<=(others=>'0);
end if;
bit_shift <= bit_shift(bit_shift'high-1 downto 0) & (s_level(s_level'left) and (not s_level_d1));
ipbus_out.ipb_rdata <= (others => '0');
ack <= ipbus_in.ipb_strobe and not ack;
pulse(0) <= s_level(s_level'left) and (not s_level_d1);
pulse(1)<=bit_shift(latency);
end if;
end process;
ipbus_out.ipb_ack <= ack;
ipbus_out.ipb_err <= '0';
end rtl;
Why can't you just shift your bits the whole way and ignore the fact that they go above N. The usual VHDL shifter uses the & to concatenate the shifted register with the new value:
bit_shift <= bit_shift(bit_shift'high-1 downto 0) & s_level;
That should produce your shift register just fine.
The pulse(1) <= bit_shift(N) ought to work fine.

VHDL shift register with enable

I am newbie to VHDL. I am implementing serial in serial out 72 bit shift register using VHDL. When the enable signal is high, I want the shift register to shift 72 times, irrespective of whether enable continues to be high or low. I have written the following code which is working only when the enable is high. Can anyone please help me to shift data once enable is high and then does not depend on enable to shift the data?
library ieee;
use ieee.std_logic_1164.all;
entity SR is
port(clk, din, rst, enable : in std_logic;
sr_out : inout std_logic_vector(71 downto 0));
end SR;
architecture behavioral of SR is
signal shift_reg: std_logic_vector(71 downto 0);
begin
process (clk, rst)
begin
if (rst = '0') then
shift_reg <= (others => '0');
elsif (clk'event and clk = '1') then
if enable= '1' then
shift_reg(70 downto 0) <= shift_reg(71 downto 1);
shift_reg(71) <= din;
end if;
end if;
end process;
sr_out <= shift_reg;
end behavioral;
Thanks a lot!
I think you need an RS-FlipFlop which is set by a start signal. Its output is your enable signal. The start signal also starts a 72 clock cycle counter. When the counter rolls over (or reaches zero, depending on its direction) you reset the FlipFlop which results in a disabled shift register.
edit: In addition you can add a gate to the start signal which blocks new start impulses while the counter is active. So you can be sure your data is only shifted with a multiple of 72 bits.
You need a two states machine to do so. Here's a very good idea of how to do it. I'm pretty sure it does what you need or is very close to.
library ieee;
use ieee.std_logic_1164.all;
entity SR is
port(
clk : in std_logic;
din : in std_logic;
rst : in std_logic;
enable : in std_logic;
sr_out : inout std_logic_vector(71 downto 0)
);
end SR;
architecture behavioral of SR is
signal shift_reg : std_logic_vector(71 downto 0);
signal shift_cnt : integer range 0 to 72 := 0;
type T_STATE_TYPE is (IDLE, COUNTING);
signal current_state : T_STATE_TYPE;
begin
p_shift_counter : process(clk,rst)
begin
if rst = '1' then
current_state <= IDLE;
shift_cnt <= 0;
elsif rising_edge(clk) then
if (current_state = IDLE) then --no enable detected yet
shift_cnt <= 0;
if enable = '1' then
current_state <= COUNTING;
end if;
elsif (current_state = COUNTING) then --will stay in that state until it finishes counting
if (shift_cnt < 72) then
shift_reg(0) <= din;
for i in 0 to 71 loop shift_reg(i+1) <= shift_reg(i); end loop; --shifting register
shift_cnt <= shift_cnt + 1;
else
current_state <= IDLE; --finished counting
end if;
end if;
end if;
end process;
sr_out <= shift_reg;
end behavioral;

Resources