Why does incrementing a std_logic_vector give unknown value? - vhdl

I'm attempting to write a I2C bus master in VHDL - and thoroughly test it to ensure it works etc. In doing so, I've written the module and a subsequent test-bench to test it under different stimuli - namely changing addresses and data input after each sending cycle (which is when the busy goes low).
To do this, I first attempted to increment the value in the data bus and decrement the values in the address bus, using the techniques described in this question here. However, when I did this, rather than the address bus taking the new value, it takes an uninitialised value and the assignment statement doesnt seem to execute.
I then attempted to use an intermediate integer signal, however this produced the same results, however this means that the address & data buses take the correct value for the first cycle - but then don't increment and instead take a unknown state!
Ultimately my question is why do these errors occur - and how do I fix/avoid them?
My code for the I2C master module can be found here and the code for the I2CBus (testbench) can be found here. Any other information I can provide to help please just say!
Thanks very much,
David
-----Code using intermediate signals------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY I2CBus IS
END I2CBus;
ARCHITECTURE behavior OF I2CBus IS
COMPONENT IIC_Master
PORT(
CLOCK : IN std_logic;
RESET_N : IN std_logic;
ENA : IN std_logic;
ADR : IN std_logic_vector(6 downto 0);
RW : IN std_logic;
DAT_WR : IN std_logic_vector(7 downto 0);
DAT_RD : OUT std_logic_vector(7 downto 0);
BUSY : OUT std_logic;
SCL : INOUT std_logic;
SDA : INOUT std_logic;
ACK_ERR : BUFFER std_logic
);
END COMPONENT;
--Inputs
signal CLOCK : std_logic := '0';
signal RESET_N : std_logic; --active high
signal ENA : std_logic; --active high
signal ADR : std_logic_vector(6 downto 0);
signal RW : std_logic; --read high write low
signal DAT_WR : std_logic_vector(7 downto 0);
--BiDirs
signal SCL : std_logic;
signal SDA : std_logic;
--Outputs
signal DAT_RD : std_logic_vector(7 downto 0);
signal BUSY : std_logic;
signal ACK_ERR : std_logic;
-- Clock period definitions
constant CLOCK_period : time := 5 ns;
--Signals to vary
signal address : integer := 127;
signal input_data : integer := 0;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut : IIC_Master PORT MAP(
CLOCK => CLOCK,
RESET_N => RESET_N,
ENA => ENA,
ADR => ADR,
RW => RW,
DAT_WR => DAT_WR,
DAT_RD => DAT_RD,
BUSY => BUSY,
SCL => SCL,
SDA => SDA,
ACK_ERR => ACK_ERR
);
-- Clock process definitions
CLOCK_process : process
begin
CLOCK <= '0';
wait for CLOCK_period / 2;
CLOCK <= '1';
wait for CLOCK_period / 2;
end process;
-- Reset process
reset : process
begin
reset_n <= '0';
ADR <= "1111111"; --This doesn't seem to happen the first time?
DAT_WR <= "00000000"; --Nor does this?
RW <= '0';
wait for 50 ns;
reset_n <= '1';
ENA <= '1';
wait;
end process;
stim_proc : process
begin
DAT_WR <= std_logic_vector(to_unsigned(input_data, 8));
ADR <= std_logic_vector(to_unsigned(address, 7));
if input_data < 127 then
address <= address - 1;
input_data <= input_data + 1;
wait until BUSY = '0' and RESET_N = '1';
elsif unsigned(DAT_WR) > 126 then
wait;
end if;
end process;
end behavior;
------1st Stimulus Process w/out intermediate signals
stim_proc : process
begin
if input_data < 127 then
wait until BUSY = '0' and RESET_N = '1';
ADR <= std_logic_vector(unsigned(ADR) + 1);
DAT_WR <= std_logic_vector(unsigned(DAT_WR) + 1);
elsif unsigned(DAT_WR) > 126 then
wait;
end if;
end process;
Results from second simulation using intermediate signals

The usual cause of this is the resolution of multiple assignments to signals like ADR in several different processes. In hardware terms. this is equivalent to short circuiting together the output of several different ICs. (It doesn't work without special care, and can destroy your ICs).
So check that you are assigning ADR and similar signals in only one process, and if necessary, rewrite to combine those processes into one process.
If you need to connect several outputs together, there are 2 ways that work successfully, though I don't think it's the right approach here.
Wired-OR outputs (or Wired-AND). In Wired-OR scheme the signal is permanently pulled weakly low by an assignment like ADR <= (others -> 'L'); and this can be overridden by each output driving either 'Z' for low or '1' for high. This works because multiple outputs can safely drive the signal at once.
Tri-state outputs, with arbitration to make sure only one process drives the output at any time. The others all drive 'Z' or (others => 'Z') onto the same signal, to signify they are inactive.

The answer from Brian Drummond is correct. I just wand to explain in at your example. At time 0, both the reset as well as the stim_proc process assign the same value:
reset : process
begin
...
ADR <= "1111111";
...
end process;
and
stim_proc : process
begin
ADR <= std_logic_vector(to_unsigned(address, 7)); -- with address = 127
...
end process;
So, the result for ADR is "1111111". But after decrementing address (in original code with intermediate version), the stim_proc process assigns a different value (than the reset process) after it starts over. You see this in the waveform. When address gets 126, which is "1111110", only the lowest bit of ADR gets X because only this bit differs from "1111111" assigned in the reset process.
Solution 1
If you just want to initialize a signal, assign the initialization value at the signal declaration. (I think, this is what you want according to your VHDL comment.) That is:
signal ADR : std_logic_vector(6 downto 0) := (others => '1');
Solution 2
If you (really) want to assign "1111111" only for the first 50 ns seconds from the reset process, then you have to assign (others => 'Z') (tri-state), (others => 'Z') (weak pull-down) or (others => 'H') (weak pull-up) afterwards in this process to allow an "overriding" by the stim_proc process, e.g.:
reset : process
begin
ADR <= "1111111";
wait for 50 ns;
ADR <= (others => 'Z');
wait;
end process;

Related

VHDL: counter checking

I want to detect a external signal connection to a CPLD (only connected or not connected). My system clock is 1MHz and external signal is 4KHz. I have developed a logic that will detect rising edge of external signal and start a counter. If the counter is counting then external signal is connected and if the counter is not counting then external signal is not connected. I write the code but its not working, what is the problem? I am beginner in VHDL. Please help, How to check a counter running in vhdl?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity SYNC_detection1 is
Port ( SYNC : in STD_LOGIC;
CLK : in STD_LOGIC;
EDGE : out STD_LOGIC;
OUTPUT : out STD_LOGIC;
BITSOUT : out STD_LOGIC_VECTOR (3 downto 0)
);
end SYNC_detection1;
architecture workingarchi of SYNC_detection1 is
signal SYNC_reg : std_LOGIC := '0';
signal SYNC_edge : std_LOGIC := '0';
signal TEMP : std_LOGIC := '0';
signal counter : STD_LOGIC_VECTOR (3 downto 0);
begin
SYNC_edge_p : process(CLK)
begin
if (rising_edge(CLK)) then
SYNC_reg <= SYNC;
end if;
end process;
SYNC_edge <= not SYNC_reg and SYNC;
counter_p: process(CLK)
begin
if (rising_edge(CLK)) then
if SYNC_edge = '1' then
counter <= counter + 1;
if (counter = "0000") then
TEMP <= '1';
end if;
end if;
end if;
end process;
OUTPUT <= TEMP;
BITSOUT <= counter;
EDGE <= SYNC_edge;
end workingarchi;
If you just want to check that the counter is running and you don't want to write a testbench, which you should do by the way, you can put an if condition that if the counter equals to 1, then turn a led on in your board. something like this:
if counter = "0001" then
led <= '1';
end if;
if the led is ON then you counter is running.
first of all, you are managing an external clock and want to process it with your 1MHz internal clock, for this application you must use a synchronization block.
I will proceed as follow.
Manage the external SYNC signal as a clock, and use it to count the rising_edge,
another tips is to avoid std_logic_vector to count (using integer to count get the code more readable)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity SYNC_detection1 is
Port ( SYNC : in STD_LOGIC;
EDGE : out STD_LOGIC;
OUTPUT : out STD_LOGIC;
BITSOUT : out STD_LOGIC_VECTOR (3 downto 0)
);
end SYNC_detection1;
architecture workingarchi of SYNC_detection1 is
signal SYNC_edge : std_LOGIC := '0';
signal TEMP : std_LOGIC := '0';
signal counter : integer := 0;
begin
SYNC_edge_p : process(SYNC)
begin
SYNC_edge <= '0';
if (rising_edge(SYNC)) then
counter <= counter + 1;
SYNC_edge <= '1';
if (counter = 0) then
TEMP <= '1';
end if;
end if;
end process;
OUTPUT <= TEMP;
BITSOUT <= std_logic_vector(to_unsigned(counter, BITSOUT'length));
EDGE <= SYNC_edge;
end workingarchi;
With this implementation you now have your output signals in the 4KHz clock domain,
you just need to add a synchronization block for each output line with source clock 4KHz and destination clock 1MHz.
For the synchronization block just as reference I write the following block that is able to synchronize an edge:
library ieee;
use ieee.std_logic_1164.all;
entity edge_sync is
port(
data : in std_logic;
clk_src : in std_logic;
clk_dst : in std_logic;
line_out: out std_logic
);
end edge_sync;
architecture beha of edge_sync is
component ff_D is
port(
lineD : in std_logic;
clk : in std_logic;
lineQ : out std_logic
);
end component ff_D;
signal input_s : std_logic := '0';
signal meta : std_logic:= '0';
signal Q2_D3 : std_logic:= '0';
signal Q3 : std_logic:= '0';
begin
FFsrc : ff_D port map (
lineD => input_s,
clk => clk_src,
lineQ => meta
);
FFdst1 : ff_D port map(
lineD => meta,
clk => clk_dst ,
lineQ => Q2_D3
);
FFdst2 : ff_D port map(
lineD => Q2_D3,
clk => clk_dst ,
lineQ => Q3
);
input_s <= data;
line_out <= (not Q3) and Q2_D3;
end beha;
But on line you can find other implementations.
From your code:
SYNC_edge <= not SYNC_reg and SYNC;
This line could work only if SYNC changes between CLK rising edges.
Are you sure you are not generating the 2 clock synchronously? If the 2 clocks
are generated with 0 phase since they are multiple you'll never get an edge between the CLK rising edges, as consequences you don't see SYNC_edge change.
PS
You are facing with two main fpga subjects, clock domain crossing and metastability management, I suggest you to study theory material about these arguments.
It can help you to focus on hardware aspects as well as VHDL coding.
Regards

VHDL Altera Qartus random data in unsigned register after (others => 0) + 1

I'm having trouble figuring out why I'm getting problems with my clock enable timer in a UART controller. The counter is cntR. It should start counting from zero after a condition is met, yet it starts at zero and then switches to a random number instead of incrementing 0 to 1. Here's the process code where something bad happens:
process(reset, clock)
begin
if reset = '1' then
cntR <= (others => '0');
elsif rising_edge(clock) then
if rcv_reg = r_idle and rxd = '1' then
cntR <= (others => '0');
else
if cntR = DIVVALUE then
cntR <= (others => '0');
else
cntR <= cntR + 1;
end if;
end if;
end if;
end process;
here are the declarations (probably not that important):
entity SART is
generic(
INCLK : natural := 50000000;
BAUDRATE : natural := 9600;
CNT_WIDTH : natural := 14
);
port(
clock : in std_logic;
reset : in std_logic;
send : in std_logic;
rxd : in std_logic;
data_in : in std_logic_vector(7 downto 0);
data_ready : out std_logic;
clear_to_send : out std_logic;
txd : out std_logic;
data_out : out std_logic_vector(7 downto 0)
);
end SART;
-- Receiver FSM states
type RCV_STATE_TYPE is (
r_idle,
r_start,
r_data1,r_data2,r_data3,r_data4,r_data5,r_data6,r_data7,r_data8,
r_stop1
);
signal rcv_reg, rcv_next : RCV_STATE_TYPE;
signal cntR : unsigned(CNT_WIDTH-1 downto 0);
This is what I get from Signal Tap:
For the record, I'm using Altera Quartus 13.0.0 and a DE0-Nano with a Cyclone IV FPGA.
Thank you in advance for your input.
I managed to fix this problem. It turns out, that I didn't have an SDC file in the project and hence the TimeQuest Timing Analyzer report stated that my maximum clock frequency is 10 times higher that when I had the SDC file attached. After writing an SDC file containing only clock declarations I got a maximum clock frequency of about 7 MHz from TimeQuest. I generated a PLL to get a 5 MHz frequency clock and now everything works flawlessly.

Encoder Debounce VHDL

For practice, I attempted to make a VHDL code to run Rotary encoder hardware. It was full with debounce, quadrature decoder and an up/down counter codes.
Unfortunately, when running simulation with a testbench, my results were disappointing so I decided that each block needs to be analysed separately. For the debounce code, I created a symbol file and produced the circuit below
(clickable)
While attempting to debounce the testbench signal in simulation, I found out that my results were terrible so I believe I am missing something.
(clickable)
The VHDL code for the encoder block can be found here :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY debounce_a IS
GENERIC( counter_size : INTEGER := 8); --counter size (8 bits gives 51.6 us with 5MHz clock)
PORT(
clk : IN STD_LOGIC; --input clock
bounce_a : IN STD_LOGIC; --input signal to be debounced
result : OUT STD_LOGIC); --debounced signal
END debounce_a;
ARCHITECTURE logic OF debounce_a IS
SIGNAL flipflops : STD_LOGIC_VECTOR(1 DOWNTO 0); --input flip flops
SIGNAL counter_set : STD_LOGIC; --sync reset to zero
SIGNAL counter_out : STD_LOGIC_VECTOR(counter_size DOWNTO 0) := (OTHERS => '0'); --counter output
BEGIN
counter_set <= flipflops(0) xor flipflops(1); --determine when to start/reset counter
PROCESS(clk) -- occurs within a clock event
BEGIN
IF(clk'EVENT and clk = '1') THEN -- can be rising_edge(clk)
flipflops(0) <= bounce_a; -- adresses the signal as a set value
flipflops(1) <= flipflops(0);
If(counter_set = '1') THEN --reset counter because input is changing
counter_out <= (OTHERS => '0'); --set all bits to '0'
ELSIF(counter_out(counter_size) = '0') THEN --stable input time is not yet met
counter_out <= counter_out + 1;
ELSE --stable input time is met
result <= flipflops(1);
END IF;
END IF;
END PROCESS;
END logic;
It could be filled to the brim with unwanted logic because I had a limited idea of what I was doing and I took a friends general debounce code and edited it to try and fit my specific needs.
If anything extra is needed I am willing to provide. I feel like it's a pretty basic error but I just need any sort of help.
Here is a look on the testbench code that I used if that helps identify toggling properties :
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY decodeblock_vhd_tst IS
END decodeblock_vhd_tst;
ARCHITECTURE decodeblock_arch OF decodeblock_vhd_tst IS
-- constants
CONSTANT clk_period : TIME := 20 ns;
CONSTANT num_clk_cycles : INTEGER := 100;
-- signals
SIGNAL b_Input : STD_LOGIC;
SIGNAL b_output : STD_LOGIC;
SIGNAL CLOCK_50 : STD_LOGIC := '0';
COMPONENT decodeblock
PORT (
b_Input : IN STD_LOGIC;
b_output : OUT STD_LOGIC;
CLOCK_50 : IN STD_LOGIC
);
END COMPONENT;
BEGIN
i1 : decodeblock
PORT MAP (
-- list connections between master ports and signals
b_Input => b_Input,
b_output => b_output,
CLOCK_50 => CLOCK_50
);
init : PROCESS
-- variable declarations
BEGIN
b_input <= '0',
'1' after 1.1 ns,
'0' after 2.9 ns,
'1' after 5.1 ns,
'0' after 7.6 ns,
'1' after 9.9 ns,
'0' after 12.5 ns,
'1' after 15.4 ns,
'0' after 18.6 ns,
'1' after 22.1 ns,
'0' after 25.9 ns,
'1' after 29.7 ns,
'0' after 33.8 ns,
'1' after 38.2 ns;
-- variable declarations
for i in 1 to num_clk_cycles loop
CLOCK_50 <= not CLOCK_50;
wait for clk_period/2;
CLOCK_50 <= not CLOCK_50;
wait for clk_period/2;
end loop;
WAIT;
END PROCESS init;
always : PROCESS
-- optional sensitivity list
-- ( )
-- variable declarations
BEGIN
-- code executes for every event on sensitivity list
WAIT;
END PROCESS always;
END decodeblock_arch;

array of signals in VHDL?

i'm trying to define a 4096*16 RAM, i did like this:
entity Test is
port(
...
IR : inout std_logic_vector(15 downto 0);
AR : inout std_logic_vector(11 downto 0));
end test
architecture test1 of test is
type ram is array(4095 downto 0) of std_logic_vector(15 downto 0);
signal ram1 : ram := (others => (others => '0'));
begin
AR <= "000000000000";
ram1(0) <= "0010000000000100";
...
...
process(arguments)
IR <= ram1(conv_integer(AR));
my problem is, when i give ram1 values, and then give ram1 values to an output port, its ones (1s) become Unknown (X) in Isim
i get "00X000000X00" for IR in isim
Here is a synchronous design for your RAM entity:
library IEEE;
use IEEE.std_logic_1164.all;
USE ieee.numeric_std.ALL;
entity Test is
port(
clock : in std_logic; -- clock
IR : inout std_logic_vector(15 downto 0); -- data port
AR : in std_logic_vector(11 downto 0); -- address port
write_enable : in std_logic -- '1' -> write, '0' -> read
);
end test;
architecture test1 of Test is
type ram is array(0 to 4095) of std_logic_vector(15 downto 0);
-- the actual ram
signal ram1 : ram := (others => (others => '0'));
-- internal signal for reading data
signal IR_out : std_logic_vector(15 downto 0) := (others => 'Z');
begin
-- only apply our own signal to the data port
-- during read
IR <= IR_out when write_enable = '0' else (others => 'Z');
proc: process(clock) is
begin
if rising_edge(clock) then
if write_enable = '1' then
-- write to RAM
ram1(to_integer(unsigned(AR))) <= IR;
else
-- read from RAM
IR_out <= ram1(to_integer(unsigned(AR)));
end if;
end if; -- rising edge
end process;
end; -- architecture
and here is a testbench for it:
library IEEE;
use IEEE.std_logic_1164.all;
entity Testbench is
end Testbench;
architecture TB of Testbench is
component Test
port(
clock : in std_logic; -- clock
IR : inout std_logic_vector(15 downto 0); -- data port
AR : in std_logic_vector(11 downto 0); -- address port
write_enable : in std_logic -- '1' -> write, '0' -> read
);
end component;
-- define signals
signal clock : std_logic := '0';
-- our internal signals
signal IRtest : std_logic_vector(15 downto 0) := (others => 'Z');
signal ARtest : std_logic_vector(11 downto 0) := (others => '0');
signal write_enable_test : std_logic := '0';
begin
-- Instantiate a RAM to be tested and connect it to our signals
uut: Test PORT MAP (
clock => clock,
AR => ARtest,
IR => IRtest,
write_enable => write_enable_test
);
-- clock generator (10 MHz)
clockgen : process
begin
clock <= '0';
wait for 50ns;
clock <= '1';
wait for 50ns;
end process;
-- generate signals to test the RAM
stimulus : process
begin
-- write data into ram
ARtest <= "000000000000";
IRtest <= "0010000000000100";
write_enable_test <= '1';
wait for 100 ns;
-- read a different address back from RAM
ARtest <= "000000000001";
IRtest <= (others => 'Z');
write_enable_test <= '0';
wait for 100 ns;
-- read the original address back from ram
ARtest <= "000000000000";
IRtest <= (others => 'Z');
write_enable_test <= '0';
wait for 100 ns;
wait;
end process;
end; -- architecture
The testbench essentially writes the value to the RAM in the first clock cycle, reads a different address in the second clock cycle and then reads the contents of the original address in the third clock cycle.
The waveform output for the testbench is:
Note that you'll get the contents of the ram at the output port of the RAM entity only on the next rising edge of the clock cycle.
You can fiddle with the design and testbench here: http://www.edaplayground.com/x/5w8
I saw also an asynchronous (not using if rising_edge(clock)) example here: http://www.edaplayground.com/x/3Zs
When using ISim, I assume you use Xilinx FPGA. In that case, take a looks at the Xilinx, HDL Coding Practices for inferring different kind of elements, e.g. RAMs.
Also, only use inout at the toplevel of the design, and even if the RAM is at the top level, then separate the inout from the RAM, so the synthesis tool can implement the different parts of the design, like IO elements and RAMs, correctly.
An example of coding style for inferred RAM, based on the above paper, is:
process (clk)
begin
if (rising_edge(clk)) then
if (we = '1') then
mem(conv_integer(addr)) <= di ;
else
do <= mem(conv_integer(addr));
end if;
end if;
end process;

Why Does This VHDL Work in Sumulation and Does not Work on the Virtex 5 Device

I have spent the whole day trying to solve the following problem. I am building a small averaging multichannel oscilloscope and I have the following module for storing the signal:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
entity storage is
port
(
clk_in : in std_logic;
reset : in std_logic;
element_in : in std_logic;
data_in : in std_logic_vector(11 downto 0);
addr : in std_logic_vector(9 downto 0);
add : in std_logic; -- add = '1' means add to RAM
-- add = '0' means write to RAM
dump : in std_logic;
element_out : out std_logic;
data_out : out std_logic_vector(31 downto 0)
);
end storage;
architecture rtl of storage is
component bram is
port
(
clk : in std_logic;
we : in std_logic;
en : in std_logic;
addr : in std_logic_vector(9 downto 0);
di : in std_logic_vector(31 downto 0);
do : out std_logic_vector(31 downto 0)
);
end component bram;
type state is (st_startwait, st_add, st_write);
signal current_state : state := st_startwait;
signal next_state : state := st_startwait;
signal start : std_logic;
signal we : std_logic;
signal en : std_logic;
signal di : std_logic_vector(31 downto 0);
signal do : std_logic_vector(31 downto 0);
signal data : std_logic_vector(11 downto 0);
begin
ram : bram port map
(
clk => clk_in,
we => we,
en => en,
addr => addr,
di => di,
do => do
);
process(clk_in, reset, start)
begin
if rising_edge(clk_in) then
if (reset = '1') then
current_state <= st_startwait;
else
start <= '0';
current_state <= next_state;
if (element_in = '1') then
start <= '1';
end if;
end if;
end if;
end process;
process(current_state, start, dump)
variable acc : std_logic_vector(31 downto 0);
begin
element_out <= '0';
en <= '1';
we <= '0';
case current_state is
when st_startwait =>
if (start = '1') then
acc(11 downto 0) := data_in;
acc(31 downto 12) := (others => '0');
next_state <= st_add;
else
next_state <= st_startwait;
end if;
when st_add =>
if (add = '1') then
acc := acc + do;
end if;
we <= '1';
di <= acc;
next_state <= st_write;
when st_write =>
if (dump = '1') then
data_out <= acc;
element_out <= '1';
end if;
next_state <= st_startwait;
end case;
end process;
end rtl;
Below is the BRAM module as copied from the XST manual. This is a no-change type of BRAM and I believe there is the problem. The symptom is that, while this simulates fine, I read only zeroes from the memory when I use the design on the device.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity bram is
port
(
clk : in std_logic;
we : in std_logic;
en : in std_logic;
addr : in std_logic_vector(9 downto 0);
di : in std_logic_vector(31 downto 0);
do : out std_logic_vector(31 downto 0)
);
end bram;
architecture rtl of bram is
type ram_type is array (0 to 999) of std_logic_vector (31 downto 0);
signal buf : ram_type;
begin
process(clk, en, we)
begin
if rising_edge(clk) then
if en = '1' then
if we = '1' then
buf(conv_integer(addr)) <= di;
else
do <= buf(conv_integer(addr));
end if;
end if;
end if;
end process;
end rtl;
What follows is a description of the chip use and the expected output. "clk_in" is a 50 MHz clock. "element_in" is '1' for 20 ns and '0' for 60 ns. "addr_in" iterates from 0 to 999 and changes every 80 ns. "element_in", "data_in", and "addr" are all aligned and synchronous. Now "add" is '1' for 1000 elements, then both "add" and "dump" are zero for 8000 elements and, finally "dump" is '1' for 1000 elements. Now, if I have a test bench that supplies "data_in" from 0 to 999, I expect data_out to be 0, 10, 20, 30, ..., 9990 when "dump" is '1'. That is according to the simulation. In reality I get 0, 1, 2, 3, ..., 999....
Some initial issues to address are listed below.
The process(current_state, start, dump) in storage entity looks like it is
intended to implement a combinatorial element (gates), but the signal (port)
data_in is not in the sensitivity list.
This is very likely to cause a difference between simulation and synthesis
behavior, since simulation will typically only react to the signals in the
sensitivity list, where synthesis will implement the combinatorial design and
react on all used signals, but may give a warning about incomplete sensitivity
list or inferred latches. If you are using VHDL-2008 then use can use a
sensitivity list of (all) to have the process sensitivity to all used
signals, and otherwise you need to add missing signals manually.
The case current_state is in process(current_state, start, dump) lacks an
when others => ..., so the synthesis tool has probably given you a warning
about inferred latches. This should be fixed by adding the when others =>
with and assign all signals driven by the process to the relevant value.
The use clause lists:
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
But both of these should not be used at the same time, since they declare some
of the same identifiers, for example is unsigned declared in both. Since the
RAM uses std_logic_unsigned I suggest that you stick with that only, and
delete use of numeric_std. For new code I would though recommend use of
numeric_std.
Also the process(clk_in, reset, start) in storage entity implements a
sequential element (flip flop) sensitive to only rising edge of clk_in, so
the two last signals in sensitivity list ..., reset, start) are unnecessary,
but does not cause a problem.

Resources