Unexpected value when reading ROM in the first clock pulse - vhdl

I'm trying to create a ROM where a number of values is stored and, after receiving a clock pulse, one of its values is read and then sent to the output while the counter that keeps track of the current position in the ROM is increased by 1. The problem that i found is that the ROM value is not retrieved as it should be in the first clock event.
Entity code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity memoria is
Port ( clock, reset :in STD_LOGIC;
valor : out STD_LOGIC_VECTOR(7 downto 0);
vazia : out STD_LOGIC);
end memoria;
architecture Behavioral of memoria is
type ROM is array (0 to 4) of STD_LOGIC_VECTOR(7 downto 0); --Read only memory
constant mem : ROM := (b"00000000", b"00000001", b"00000010", b"00000011", b"11111111"); --"11111111" is the stop value
signal mem_value : STD_LOGIC_VECTOR(7 downto 0);
begin
process(clock, reset)
variable counter : integer := 0;
begin
if reset = '1' then
valor <= "11111111";
vazia <= '1';
elsif clock'event and clock = '1' then
mem_value <= mem(counter); --gets the current memory value
if mem_value = "11111111" then --checks if the value read is the stop one
vazia <= '1';
else
vazia <= '0';
end if;
valor <= mem_value; --sends the memory value read to the output
if counter < 4 then
counter := counter + 1; --increases counter by one
end if;
else
valor <= "11111111";
vazia <= '0';
end if;
end process;
end Behavioral;
Test Bench
ENTITY memoria_tb IS
END memoria_tb;
ARCHITECTURE behavior OF memoria_tb IS
--Inputs
signal clock : std_logic;-- := '0';
signal reset : std_logic := '0';
--Outputs
signal valor : std_logic_vector(7 downto 0);
signal vazia : std_logic;
-- Clock period definitions
constant clock_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: entity work.memoria PORT MAP (
clock => clock,
reset => reset,
valor => valor,
vazia => vazia
);
-- Clock process definitions
clock_process :process
begin
clock <= '0';
wait for clock_period/2;
clock <= '1';
wait for clock_period/2;
end process;
END;
Image of the error
I would like to know how to get the first ROM value in the first clock pulse instead of UUUUUUUU. Thanks for the help.

The problem was that the outputs should always be assigned after the process as noted in this post https://forums.xilinx.com/t5/General-Technical-Discussion/Counter-implementation-in-vhdl/td-p/570433.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity memoria is
Port ( clock, reset :in STD_LOGIC;
valor : out STD_LOGIC_VECTOR(7 downto 0);
vazia : out STD_LOGIC);
end memoria;
architecture Behavioral of memoria is
type ROM is array (0 to 4) of STD_LOGIC_VECTOR(7 downto 0); --Read only memory
constant mem : ROM := (b"00000000", b"00000001", b"00000010", b"00000011", b"11111111"); --"11111111" is the stop value
signal mem_value : STD_LOGIC_VECTOR(7 downto 0);
signal empty : STD_LOGIC;
begin
process(clock, reset)
variable counter : integer := 0;
begin
if reset = '1' then
mem_value <= "11111111";
empty <= '1';
elsif clock'event and clock = '1' then
mem_value <= mem(counter); --gets the current memory value
if mem_value = "11111111" then --checks if the value read is the stop one
empty <= '1';
else
empty <= '0';
end if;
if counter < 4 then
counter := counter + 1; --increases counter by one
end if;
else
mem_value <= "11111111";
empty <= '0';
end if;
end process;
valor <= mem_value; --sends the memory value read to the output
vazia <= empty;
end Behavioral;

Related

How can I add a maximum value to my bidirectional 4bit counter (loop)?

I have this code which is a bidirectional counter that loops around.
I now want to add an input (maybe from switches or something), which controls the maximum value of the counter, for example if the max value from the input is "0111" the counter will count up to 0111 and then loop back around to 0000, and if the counter is counting down to 0000 it will loop back to 0111. I'm getting a bit confused on how/where I should do this because I've used nested ifs to implement an enable and reset input.
Here is the code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity UPDOWN_COUNTER is
Port ( clk: in std_logic; -- clock input
reset: in std_logic; -- reset input
up_down: in std_logic; -- up or down
enable: in std_logic; -- enable
max: in std_logic_vector(3 downto 0); -- max value counter
counter: out std_logic_vector(3 downto 0) -- output 4-bit counter
);
end UPDOWN_COUNTER;
architecture Behavioral of UPDOWN_COUNTER is
signal counter_updown: std_logic_vector(3 downto 0);
begin
process(clk,reset,enable,max)
begin
if(enable ='1') then
if(rising_edge(clk)) then
if(reset='1') then
counter_updown <= x"0";
elsif(up_down='1') then
counter_updown <= counter_updown - x"1"; -- count down
else
counter_updown <= counter_updown + x"1"; -- count up
end if;
end if;
end if;
end process;
counter <= counter_updown;
end Behavioral;
Here is the test bench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity tb_counters is
end tb_counters;
architecture Behavioral of tb_counters is
component UPDOWN_COUNTER
Port ( clk: in std_logic; -- clock input
reset: in std_logic; -- reset input
up_down: in std_logic; -- up or down input
enable: in std_logic; -- enable input
max: in std_logic_vector(3 downto 0); -- max value counter
counter: out std_logic_vector(3 downto 0) -- output 4-bit counter
);
end component;
signal reset,clk,enable,up_down: std_logic;
signal max,counter:std_logic_vector(3 downto 0);
begin
dut: UPDOWN_COUNTER port map (clk => clk, reset=>reset,enable => enable, up_down => up_down, max => max,counter => counter);
-- Clock
clock_process :process
begin
clk <= '0';
wait for 10 ns;
clk <= '1';
wait for 10 ns;
end process;
stim_proc: process
begin
max <= "1000"; -- Test value for Counter max value
enable <= '1';
reset <= '1';
up_down <= '0';
wait for 20 ns;
reset <= '0';
wait for 300 ns;
up_down <= '1';
--
wait for 50 ns;
enable <= '0';
wait for 50 ns;
enable <= '1';
wait;
end process;
end Behavioral;
You've specified a synchronous reset. There's at least one synthesis issue, where enable is inferred to gate the clock. The numeric package has been switched to ieee.numeric_std in the following (the example can be modified for the non-standard Synopsys numeric package):
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity updown_counter is
port (
clk: in std_logic;
reset: in std_logic;
up_down: in std_logic;
enable: in std_logic;
max: in std_logic_vector(3 downto 0);
counter: out std_logic_vector(3 downto 0)
);
end entity updown_counter;
architecture behavioral of updown_counter is
signal counter_updown: unsigned(3 downto 0);
begin
process (clk) -- other signals evaluated inside clock edge
begin
if rising_edge(clk) then
if enable = '1' then -- don't gate the clock
if reset = '1' then
counter_updown <= (others => '0');
elsif up_down = '1' then -- down
if counter_updown = 0 then
counter_updown <= unsigned(max);
else
counter_updown <= counter_updown - 1;
end if;
else -- count up
if counter_updown = unsigned(max) then
counter_updown <= (others => '0');
else
counter_updown <= counter_updown + 1;
end if;
end if;
end if;
end if;
end process;
counter <= std_logic_vector(counter_updown);
end architecture behavioral;
And that gives:
with your testbench.
This is the similar to #user1155120's answer (which I recommend you accept as the answer), but I've used an asynchronous reset instead. Also added a generic to specify the number bits in the counter.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity UpdownCounter is
generic
(
COUNTER_BITS: natural := 4
);
port
(
clk: in std_logic; -- clock input
reset: in std_logic; -- reset input
up_down: in std_logic; -- up or down input
enable: in std_logic; -- enable input
max: in std_logic_vector(COUNTER_BITS - 1 downto 0); -- max value counter
counter: out std_logic_vector(COUNTER_BITS - 1 downto 0) -- output N-bit counter
);
end UpdownCounter;
architecture V1 of UpdownCounter is
signal counter_updown: unsigned(COUNTER_BITS - 1 downto 0);
begin
process(clk, reset)
begin
if reset then
-- Do asynchronous reset.
counter_updown <= (others => '0');
elsif rising_edge(clk) then
-- Do synchronous stuff.
if enable then
if up_down then
-- Count down to zero cyclically.
if counter_updown = 0 then
counter_updown <= unsigned(max);
else
counter_updown <= counter_updown - 1;
end if;
else
-- Count up to max cyclically.
if counter_updown = unsigned(max) then
counter_updown <= (others => '0');
else
counter_updown <= counter_updown + 1;
end if;
end if;
end if;
end if;
end process;
counter <= std_logic_vector(counter_updown);
end V1;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity UpdownCounter_TB is
end UpdownCounter_TB;
architecture V1 of UpdownCounter_TB is
component UpdownCounter
generic
(
COUNTER_BITS: natural := 4
);
port
(
clk: in std_logic; -- clock input
reset: in std_logic; -- reset input
up_down: in std_logic; -- up or down input
enable: in std_logic; -- enable input
max: in std_logic_vector(COUNTER_BITS - 1 downto 0); -- max value counter
counter: out std_logic_vector(COUNTER_BITS - 1 downto 0) -- output 4-bit counter
);
end component;
signal reset, clk, enable, up_down: std_logic;
signal max, counter: std_logic_vector(3 downto 0);
signal halt_clk: boolean := false;
begin
DUT: UpdownCounter
generic map
(
COUNTER_BITS => 4
)
port map
(
clk => clk,
reset => reset,
enable => enable,
up_down => up_down,
max => max,
counter => counter
);
-- Clock
ClockProocess :process
begin
while not halt_clk loop
clk <= '0';
wait for 10 ns;
clk <= '1';
wait for 10 ns;
end loop;
wait;
end process;
StimulusProcess: process
begin
max <= "1000"; -- Test value for Counter max value
enable <= '1';
reset <= '1';
up_down <= '0';
wait for 20 ns;
reset <= '0';
wait for 300 ns;
up_down <= '1';
--
wait for 50 ns;
enable <= '0';
wait for 50 ns;
enable <= '1';
wait for 1000 ns;
halt_clk <= true;
wait;
end process;
end V1;

FIFO using vhdl

I am writing a VHDL for fifo , but when i simulate there is no output?i cantt view the output in behavioral simulation.its like There's no data in data_in for read to be writing to the output of fifo.In my code is to write data into the FIFO first push the data onto the DataIn bus and then strobe the WriteEn input high for one clock cycle.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use std.textio.all;
use IEEE.NUMERIC_STD.ALL;
entity fifo_mem is
port ( clk : in std_logic;
reset : in std_logic;
enr : in std_logic;
enw : in std_logic;
data_in : in std_logic_vector (15 downto 0); --input data
data_out : out std_logic_vector(15 downto 0); --output data
fifo_empty : out std_logic;
fifo_full : out std_logic );
end fifo_mem;
architecture Behavioral of fifo_mem is
type fifo_type is array(0 to 10) of bit_vector (15 downto 0);
signal memory : fifo_type :=(others => (others => '0'));
signal readptr,writeptr : integer := 0; --read and write pointers.
signal empty,full : std_logic ;
impure function InitRamFromFile (RamFileName : in string) return fifo_type is
FILE RamFile : text is in RamFileName;
variable RamFileLine : line;
variable RAM : fifo_type;
begin
for I in 0 to 10 loop
readline (RamFile, RamFileLine);
read (RamFileLine, RAM(I));
end loop;
return RAM;
end function;
signal RAM : fifo_type :=InitRamFromFile("C:\Users\hp\Desktop\file\file1.txt");
begin
fifo_empty <= empty;
fifo_full <= full;
process(Clk,reset)
--this is the number of elements stored in fifo at a time.
--this variable is used to decide whether the fifo is empty or full.
variable num_elem : integer := 0;
begin
if(reset = '1') then
data_out <= (others => '0');
empty <= '0';
full <= '0';
readptr <= 0;
writeptr <= 0;
num_elem := 0;
elsif(rising_edge(Clk)) then
if(enr = '1' and empty = '0') then --read
data_out <=to_stdlogicvector(RAM(readptr));
readptr <= readptr + 1;
num_elem := num_elem-1;
end if;
if(enw ='1' and full = '0') then --write
RAM(writeptr)<= to_bitvector(data_in);
writeptr <= writeptr +1;
num_elem := num_elem+1;
end if;
if(readptr = 10) then --resetting read pointer.
readptr <= 0;
end if;
if(writeptr = 10) then --resetting write pointer.
writeptr <= 0;
end if;
--setting empty and full flags.
if(num_elem = 0) then
empty <= '1';
else
empty <= '0';
end if;
if(num_elem = 10) then
full <= '1';
else
full <= '0';
end if;
end if;
end process;
end Behavioral;

ISim shows U for all outputs

I have a simple VHDL design and test bench that does not produce the expected output. ISim shows 'U' for all the outputs until the 'running' state is achieved (myState='1'). Then they show 0 and X values. The first PROCESS block should set all outputs to '0' when ENABLE is '0'. The test bench toggles ENABLE 0-1-0 to insure an event triggers the process, but the outputs stay at 'U'. Is the problem in the design, the test, or both?
VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity TestHarness1 is
port (
ADAT_WDCLK : in std_logic;
ADAT_BCLK: in std_logic;
ADAT_OUT12: in std_logic;
ENABLE: in std_logic;
PCM_FS : out std_logic;
PCM_CLK : out std_logic;
PCM_DIN : out std_logic
);
end TestHarness1;
architecture Behavioral of TestHarness1 is
--type state is (STOPPED, RUNNING);
signal tmp : std_logic;
signal myState : std_logic;
begin
PCM_DIN <= tmp;
-- State management process
process (ENABLE, ADAT_WDCLK) begin -- Eval on input changes
if (ENABLE = '0') then
myState <= '0'; --STOPPED;
PCM_FS <= '0'; -- All outputs muted
PCM_CLK <= '0';
tmp <= '0';
else
if (myState = '0' and rising_edge(ADAT_WDCLK)) then
-- Move to running state only at start of a frame
myState <= '1'; --RUNNING;
end if;
end if;
end process;
-- Output process
process (ADAT_WDCLK, ADAT_BCLK, myState) variable counter: integer := 0; begin
-- Only do something if we are in running state, process above
-- sets outputs when stopped.
if (myState = '1') then
-- Pass the clocks through, inverting the bit clock
PCM_FS <= ADAT_WDCLK;
PCM_CLK <= not ADAT_BCLK;
-- Generate fixed bit pattern data '11000101'
if rising_edge(ADAT_WDCLK) then
-- This would happen naturally since there are 4 bytes per word clock
counter := 0;
end if;
if falling_edge(ADAT_WDCLK) then
-- This would happen naturally since there are 4 bytes per word clock
counter := 0;
end if;
if rising_edge(ADAT_BCLK) then -- Change data state only on falling edge of output PCM_CLK
if counter = 0 or counter = 1 or counter = 5 or counter = 7 then
tmp <= '1';
else
tmp <= '0';
end if;
if (counter = 7) then
counter := 0; -- Reset counter
else
counter := counter + 1; -- Just inc counter
end if;
end if;
end if;
end process;
end Behavioral;
Test Bench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY TH1TestBench3 IS
END TH1TestBench3;
ARCHITECTURE behavior OF TH1TestBench3 IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT TestHarness1
PORT(
ADAT_WDCLK : IN std_logic;
ADAT_BCLK : IN std_logic;
ADAT_OUT12 : IN std_logic;
ENABLE : IN std_logic;
PCM_FS : OUT std_logic;
PCM_CLK : OUT std_logic;
PCM_DIN : OUT std_logic
);
END COMPONENT;
--Inputs
signal ADAT_WDCLK : std_logic := '0';
signal ADAT_BCLK : std_logic := '0';
signal ADAT_OUT12 : std_logic := '0';
signal ENABLE : std_logic := '0';
--Outputs
signal PCM_FS : std_logic;
signal PCM_CLK : std_logic;
signal PCM_DIN : std_logic;
-- Clock period definitions. Note WDCLK is defined in terms of the bit clock
-- to insure they are exactly in sync.
constant ADAT_BCLK_period : time := 326 ns; -- About 3.072MHz (https://www.sensorsone.com/frequency-to-period-calculator/)
constant ADAT_WDCLK_period : time := ADAT_BCLK_period * 64; -- 48KHz
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: TestHarness1 PORT MAP (
ADAT_WDCLK => ADAT_WDCLK,
ADAT_BCLK => ADAT_BCLK,
ADAT_OUT12 => ADAT_OUT12,
ENABLE => ENABLE,
PCM_FS => PCM_FS,
PCM_CLK => PCM_CLK,
PCM_DIN => PCM_DIN
);
-- Clock process definitions
ADAT_WDCLK_process :process
begin
ADAT_WDCLK <= '0';
wait for ADAT_WDCLK_period/2;
ADAT_WDCLK <= '1';
wait for ADAT_WDCLK_period/2;
end process;
ADAT_BCLK_process :process
begin
ADAT_BCLK <= '1';
wait for ADAT_BCLK_period/2;
ADAT_BCLK <= '0';
wait for ADAT_BCLK_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
wait for 100 ns;
ENABLE <= '1';
wait for 100 ns;
ENABLE <= '0';
wait for 7500 ns;
ENABLE <= '1';
wait for ADAT_WDCLK_period*10;
-- insert stimulus here
wait;
end process;
END;
ISim shows the ENABLE pulse early in the simulation, but the outputs remain 'U' until the rising edge of the WCLK with ENABLE=1. Then they start to change (as designed) but they show some X values.
Modified VHDL
For reference, here is the modified VHDL that resolves the problem of U's and X's in the simulation output. However, there is a functional problem with the PCM_DIN output... seems like it is delayed one (BCLK) cycle. I expected it to be '1' as soon as ADAT_WDCLK goes high the first time after ENABLE. But it does not go to '1' until a BLCK cycle later.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity TestHarness1 is
port (
ADAT_WDCLK : in std_logic;
ADAT_BCLK: in std_logic;
ADAT_OUT12: in std_logic;
ENABLE: in std_logic;
PCM_FS : out std_logic;
PCM_CLK : out std_logic;
PCM_DIN : out std_logic
);
end TestHarness1;
architecture Behavioral of TestHarness1 is
--type state is (STOPPED, RUNNING);
signal tmp : std_logic;
signal myState : std_logic;
begin
PCM_DIN <= tmp;
-- State management process
process (ENABLE, ADAT_WDCLK) begin -- Eval on input changes
if (ENABLE = '0') then
myState <= '0'; --STOPPED;
else
if (myState = '0' and rising_edge(ADAT_WDCLK)) then
-- Move to running state only at start of a frame
myState <= '1'; --RUNNING;
end if;
end if;
end process;
-- Output process
process (ADAT_WDCLK, ADAT_BCLK, myState) variable counter: integer := 0; begin
-- Only do something if we are in running state
if (myState = '0') then
PCM_FS <= '0'; -- All outputs muted
PCM_CLK <= '0';
tmp <= '0';
elsif (myState = '1') then
-- Pass the clocks through, inverting the bit clock
PCM_FS <= ADAT_WDCLK;
PCM_CLK <= not ADAT_BCLK;
if rising_edge(ADAT_BCLK) then -- Generate fixed serial bit pattern
if counter = 0 or counter = 1 or counter = 5 or counter = 7 then
tmp <= '1';
else
tmp <= '0';
end if;
if (counter = 7) then
counter := 0; -- Reset counter
else
counter := counter + 1; -- Just inc counter
end if;
end if;
end if;
end process;
end Behavioral;
ISim of the above (including the internal myState signal)... why is PCM_DIN delayed one BCLK cycle?
Regarding the 'X' (Forcing Unknown) values you are seeing:
You are driving the signals PCM_FS, PCM_CLK and tmp from multiple processes, which results in the simulator being unable to resolve the value being driven. You need to fix this such that they are only being driven from one process, or drive 'Z' when they are not in use.
Regarding the 'U' values, they exist because you have no initial values for the signals. Once you write the signals for the first time (after the enable), they will be assigned for the first time.

Logic for an FPGA to output an analog clock on a VGA screen

I am implementing an analog clock which will display an hour and minute hand on a vga screen 640x480 with clock centered at 480x480. The clock will update once a minute. The timing diagram below shows the timing for HSYNC and VSYNC and their position relative to a 26.25MHz clock.
This is my first course in VHDL, I want to know what I am missing in clock.vhd and how to write the test bench effectively so I can get the output
I have a separate component called counter.vhd which gets instantiated twice in clock.vhd, one as the horizontal counter and one as the vertical counter.
Here is my code for counter.vhd, clock.vhd and my testbench which is not complete.
counter.vhd
entity counter is
Port ( clk : STD_LOGIC;
reset : STD_LOGIC;
ena : STD_LOGIC;
rollover_out : STD_LOGIC;
address : STD_LOGIC_VECTOR(7 downto 0);
sync : STD_LOGIC
);
-- Generics
generic (count_value :=800;
sync_start :=10;
sync_end :=20
);
end counter;
architecture Behavioral of counter is
signal temp : STD_LOGIC_VECTOR(9 downto 0); -- counts to 800
process (clk, reset)
if (reset = 0) then
temp <="000000";
sync <='1';
rollover_out <='0';
else (clk'event & clk = 1);
rollover_out <='0';
temp <= temp+"000000";
if (temp = count_value - 1) then
temp <="000000"
rollover_out <= '1';
end if;
if (sync_start = temp) then
sync <= '0';
end if;
if (sync_end = temp) then
sync <= '1';
end if;
end if;
end process;
address <= temp (8 downto 1);
begin
-- 800 horizontal sync counter
process(h_count_reg,h_end,pixel_tick)
begin
if (pixel_tick = '1') then -- 25MHz 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;
-- 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;
end Behavioral;
clock.vhd
entity clock 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 clock;
architecture Behavioral of clock is
-- VGA 640x480 sync parameters
constant HD: integer:=640; -- horizontal display area
constant HF: integer:=16; -- horizontal front porch
constant HB: integer:=48; -- horizontal back porch
constant HR: integer:=96; -- horizontal retrace "sync pulse"
constant VD: integer:=480; -- vertical display area
constant VF: integer:=10; -- vertical front porch
constant VB: integer:=33; -- vertical back porch
constant VR: integer:=2; -- vertical retrace "sync pulse"
-- mod2 counter to generate a 25MHz enable tick
signal mod2_reg : std_logic;
signal mod2_next : std_logic;
-- sync counters for the horizontal and vertical scans
signal v_count_reg : unsigned(9 downto 0);
signal v_count_next : unsigned(9 downto 0);
signal h_count_reg : unsigned(9 downto 0);
signal h_count_next : unsigned(9 downto 0);
-- output buffer
signal v_sync_reg : unsigned(9 downto 0);
signal h_sync_reg : unsigned(9 downto 0);
signal v_sync_next : unsigned(9 downto 0);
signal h_sync_next : unsigned(9 downto 0);
-- status signal
signal h_end : std_logic;
signal v_end : std_logic;
signal pixel_tick : std_logic;
component counter
generic (count_value :=800;
sync_start :=10;
sync_end :=20
);
Port (clk : STD_LOGIC;
reset : STD_LOGIC;
ena : STD_LOGIC;
rollover_out : std_logic;
sync : STD_LOGIC;
address : std_logic_vector(9 downto 0)
);
signal carry : std_logic;
end component;
horizontal: counter
generic map (count_value :=800;
sync_start :=10;
sync_end :=20
);
PORT MAP (clk <= clk;
reset <= reset;
ena <= '1';
rollover_out <= carry;
sync <= hsync
address <= open
);
vertical: counter
generic map (count_value :=525;
sync_start := 2;
sync_end := 4
);
Port map (clk <= clk;
reset <= reset;
ena <= carry;
rollover_out <= open;
sync <= vsync;
address <= open
);
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 <=(others=>'0');
h_sync_reg <=(others=>'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;
-- mod2 circuit to generate 25MHz enable tick
mod2_next <= not mod2_reg;
-- 25MHz pixel tick
pixel_tick <= '1' when mod2_reg = '1' else '0';
-- status
h_end <= -- end of horizontal counter
'1' when h_count_reg = (HD+HF+HB+HR-1) else --799
'0';
v_end <= -- end of vertical counter
'1' when v_count_reg = (VD+VF+VB+VR-1) else --524
'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;
testbench
ENTITY clock_tb IS
END clock_tb;
ARCHITECTURE behavior OF clock_tb IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT clock
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 COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal reset : std_logic := '0';
--Outputs
signal hsync : std_logic;
signal vsync : std_logic;
signal video_on : std_logic;
signal p_tick : std_logic;
signal pixel_x : std_logic_vector(9 downto 0);
signal pixel_y : std_logic_vector(9 downto 0);
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: clock PORT MAP (
clk => tb_clk,
reset => tb_reset,
hsync => tb_hsync,
vsync => tb_vsync,
video_on => tb_video_on,
p_tick => tb_p_tick,
pixel_x => tb_pixel_x,
pixel_y => tb_pixel_y
);
-- 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
-- hold reset state for 100 ns.
wait for 100 ns;
wait for clk_period*10;
-- insert stimulus here
wait;
end process;
END;
If I understand the question correctly, you need to segment your task up into two sections.
First you need a design that when given the 26.25MHz clock will generate the HSYNC, VSYNC and video data signals to be put out on the pins of the FPGA.
Second you need to fill in that video data with an RGB / YCbCr bitmap of pixel data that represent a graphic for the clock hands. This block would take in the video timing signals and the clock and then fill the video data in.
How you generate the clock hands is the tricky part and I suspect where the person running the course is looking for some ingenuity to solve that particular problem.
Start small and build up. Try and get the design together to generate the timing signals and put a flat block of colour or black and white on the screen. It is possible to create a testbench that will then save that pixel data to a file which can be processed into a bitmap, so that you can see what the result would be in simulation before you get to hardware.

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?

Resources