VHDL simulation does not display a waveform - vhdl

I wrote code in VHDL and am using Active HDL Student edition to compile and simulate the code using a testbench. As I simulate for 500ns, the signals change but the signals on the waveform is stuck on U without anything displaying. I can't seem find what is causing this problem.
This is my code for the entity:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity idexreg is
port(
rst_bar : in std_logic;
clk : in std_logic;
immediate_in : in std_logic_vector(63 downto 0);
reg0_in : in std_logic_vector(63 downto 0);
reg1_in : in std_logic_vector(63 downto 0);
instruction_in : in std_logic_vector(3 downto 0);
pc_in : in std_logic_vector(3 downto 0);
immediate_out : out std_logic_vector(63 downto 0);
reg0_out : out std_logic_vector(63 downto 0);
reg1_out : out std_logic_vector(63 downto 0);
instruction_out : out std_logic_vector(3 downto 0);
pc_out : out std_logic_vector(3 downto 0)
);
end idexreg;
architecture idexreg_arch of idexreg is
begin
arch: process(clk, rst_bar)
begin
if rst_bar = '0' then
immediate_out <= std_logic_vector(x"0000000000000000");
reg0_out <= std_logic_vector(x"0000000000000000");
reg1_out <= std_logic_vector(x"0000000000000000");
instruction_out <= std_logic_vector(x"0");
pc_out <= std_logic_vector(x"0");
elsif falling_edge(clk) then
immediate_out <= immediate_in;
reg0_out <= reg0_in;
reg1_out <= reg1_in;
instruction_out <= instruction_in;
pc_out <= pc_in;
end if;
end process;
end idexreg_arch;
This is the code for the testbench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_arith.all;
entity idexreg_tb is
end idexreg_tb;
architecture test of idexreg_tb is
--input signals
signal rst_bar : std_logic;
signal clk: std_logic;
signal immediate_in : std_logic_vector(63 downto 0);
signal reg0_in : std_logic_vector(63 downto 0);
signal reg1_in : std_logic_vector(63 downto 0);
signal instruction_in : std_logic_vector(3 downto 0);
signal pc_in : std_logic_vector(3 downto 0);
--output signals
signal immediate_out : std_logic_vector(63 downto 0);
signal reg0_out : std_logic_vector(63 downto 0);
signal reg1_out : std_logic_vector(63 downto 0);
signal instruction_out : std_logic_vector(3 downto 0);
signal pc_out : std_logic_vector(3 downto 0);
-- boolean to signify end of simulation
signal end_sim : boolean := false;
constant period : time := 50ns;
begin
UUT: entity idexreg
port map(
rst_bar => rst_bar,
clk => clk,
immediate_in => immediate_in,
reg0_in => reg0_in,
reg1_in => reg1_in,
instruction_in => instruction_in,
pc_in => pc_in,
immediate_out => immediate_out,
reg0_out => reg0_out,
reg1_out => reg1_out,
instruction_out => instruction_out,
pc_out => pc_out);
-- Generate the Clock signal
clk_gen: process
begin
clk <= '0';
loop
wait for period/2;
clk <= not clk;
exit when end_sim = true;
end loop;
wait;
end process;
stim: process
begin
-- reset the register file first
rst_bar <= '0';
wait for 100ns;
rst_bar <= '1';
--Test 1
immediate_in <= std_logic_vector(x"AAAAAAAAAAAAAAAA");
reg0_in <= std_logic_vector(x"AAAAAAAAAAAAAAAA");
reg1_in <= std_logic_vector(x"AAAAAAAAAAAAAAAA");
instruction_in <= std_logic_vector(x"A");
pc_in <= std_logic_vector(x"1");
wait for 10ns;
--Test 2
immediate_in <= std_logic_vector(x"BBBBBBBBBBBBBBBB");
reg0_in <= std_logic_vector(x"BBBBBBBBBBBBBBBB");
reg1_in <= std_logic_vector(x"BBBBBBBBBBBBBBBB");
instruction_in <= std_logic_vector(x"B");
pc_in <= std_logic_vector(x"2");
wait for 30ns;
--Test 3
immediate_in <= std_logic_vector(x"CCCCCCCCCCCCCCCC");
reg0_in <= std_logic_vector(x"CCCCCCCCCCCCCCCC");
reg1_in <= std_logic_vector(x"CCCCCCCCCCCCCCCC");
instruction_in <= std_logic_vector(x"C");
pc_in <= std_logic_vector(x"3");
end_sim <= true;
wait;
end process;
end test;
Any help would be greatly appreciated!

With two other standard compliant simulators three classes of errors were found.
Semantic error:
UUT: entity idexreg
should be
UUT: entity work.idexreg
Without a use clause use.work.all; the declaration for previously analyzed entity idexreg won't be visible (unbound, this would account for 'U's). A selected named can be used when the name is not directly visible.
IEEE Std 1076-2008 12.3 Visibility
The meaning of the occurrence of an identifier at a given place in the text is defined by the visibility rules and also, in the case of overloaded declarations, by the overloading rules. The identifiers considered in this subclause include any identifier other than a reserved word or an attribute designator that denotes a predefined attribute. The places considered in this subclause are those where a lexical element (such as an identifier) occurs. The overloaded declarations considered in this subclause are those for subprograms and enumeration literals.
12.4 Use clauses
A use clause achieves direct visibility of declarations that are visible by selection.
(the fix shown above)
13.2 Design libraries
Every design unit except a context declaration and package STANDARD is assumed to contain the following implicit context items as part of its context clause:
library STD, WORK; use STD.STANDARD.all;
Note the library name WORK is made directly visible by the library clause but the design units analyzed into the library work are not made directly visible without a use clause.
back to 12.4 Use clauses:
Each selected name in a use clause identifies one or more declarations that will potentially become directly visible. If the suffix of the selected name is a simple name other than a type mark, or is a character literal or operator symbol, then the selected name identifies only the declaration(s) of that simple name, character literal, or operator symbol contained within the package or library denoted by the prefix of the selected name.
...
If the suffix is the reserved word all, then the selected name identifies all declarations that are contained within the package or library denoted by the prefix of the selected name.
There are also two additional error classes, the first your simulator does not require adherence by a design description.
The first, a syntax rule:
15.3 Lexical elements, separators, and delimiters
At least one separator is required between an identifier or an abstract literal and an adjacent identifier or abstract literal.
There's at least one successful commercial simulator out there that ignores this rule. It's harder to ignore it for -2008.
The second, another semantic rule:
9.3.6 Type conversions
— Array types—Two array types are closely related if and only if the types have the same dimensionality and the element types are closely related
Character string and std_logic_vector are not closely related for type conversion. You can drop the unneeded type conversions - bit string's type is from context:
9.3.6:
The type of the operand of a type conversion shall be determined by applying the rules of 12.5 to the operand considered as a complete context.
Which means all you see is the expanded bit string (15.8), e.g.:
std_logic_vector(x"0000000000000000")
as a string, an array type with a character element type, while std_logic_vector has a std_ulogic or std_logic element type (depending on the VHDL revision). That means the operand and type mark of the type conversion are not closely related.
This rule shouldn't be ignored.
9.3.2 Literals
String and bit string literals are representations of one-dimensional arrays of characters. The type of a string or bit string literal shall be determinable solely from the context in which the literal appears, excluding the literal itself but using the fact that the type of the literal shall be a one-dimensional array of a character type. The lexical structure of string and bit string literals is defined in Clause 15.
You could likewise use qualified expressions.
9.3.5 Qualified expressions
A qualified expression is a basic operation (see 5.1) that is used to explicitly state the type, and possibly the subtype, of an operand that is an expression or an aggregate.
Both methods are shown below, the amount of effort required dictated most were changed to qualified expression, requiring only an additional ' character.
Your code then will analyze successfully on any standard compliant VHDL tool:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.numeric_std.all;
entity idexreg is
port(
rst_bar : in std_logic;
clk : in std_logic;
immediate_in : in std_logic_vector(63 downto 0);
reg0_in : in std_logic_vector(63 downto 0);
reg1_in : in std_logic_vector(63 downto 0);
instruction_in : in std_logic_vector(3 downto 0);
pc_in : in std_logic_vector(3 downto 0);
immediate_out : out std_logic_vector(63 downto 0);
reg0_out : out std_logic_vector(63 downto 0);
reg1_out : out std_logic_vector(63 downto 0);
instruction_out : out std_logic_vector(3 downto 0);
pc_out : out std_logic_vector(3 downto 0)
);
end idexreg;
architecture idexreg_arch of idexreg is
begin
arch: process(clk, rst_bar)
begin
if rst_bar = '0' then
immediate_out <= std_logic_vector'(x"0000000000000000");
reg0_out <= std_logic_vector'(x"0000000000000000");
reg1_out <= std_logic_vector'(x"0000000000000000");
instruction_out <= std_logic_vector'(x"0");
pc_out <= std_logic_vector'(x"0");
elsif falling_edge(clk) then
immediate_out <= immediate_in;
reg0_out <= reg0_in;
reg1_out <= reg1_in;
instruction_out <= instruction_in;
pc_out <= pc_in;
end if;
end process;
end idexreg_arch;
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.numeric_std.all;
-- use ieee.std_logic_arith.all;
entity idexreg_tb is
end idexreg_tb;
architecture test of idexreg_tb is
--input signals
signal rst_bar : std_logic;
signal clk: std_logic;
signal immediate_in : std_logic_vector(63 downto 0);
signal reg0_in : std_logic_vector(63 downto 0);
signal reg1_in : std_logic_vector(63 downto 0);
signal instruction_in : std_logic_vector(3 downto 0);
signal pc_in : std_logic_vector(3 downto 0);
--output signals
signal immediate_out : std_logic_vector(63 downto 0);
signal reg0_out : std_logic_vector(63 downto 0);
signal reg1_out : std_logic_vector(63 downto 0);
signal instruction_out : std_logic_vector(3 downto 0);
signal pc_out : std_logic_vector(3 downto 0);
-- boolean to signify end of simulation
signal end_sim : boolean := false;
constant period : time := 50 ns;
begin
UUT: entity work.idexreg -- ERROR HERE was entity idexreg
port map (
rst_bar => rst_bar,
clk => clk,
immediate_in => immediate_in,
reg0_in => reg0_in,
reg1_in => reg1_in,
instruction_in => instruction_in,
pc_in => pc_in,
immediate_out => immediate_out,
reg0_out => reg0_out,
reg1_out => reg1_out,
instruction_out => instruction_out,
pc_out => pc_out);
-- Generate the Clock signal
clk_gen: process
begin
clk <= '0';
loop
wait for period/2;
clk <= not clk;
exit when end_sim = true;
end loop;
wait;
end process;
stim: process
begin
-- reset the register file first
rst_bar <= '0';
wait for 100 ns;
rst_bar <= '1';
--Test 1
immediate_in <= x"AAAAAAAAAAAAAAAA"; -- std_logic_vector'(x"AAAAAAAAAAAAAAAA");
reg0_in <= std_logic_vector'(x"AAAAAAAAAAAAAAAA");
reg1_in <= std_logic_vector'(x"AAAAAAAAAAAAAAAA");
instruction_in <= std_logic_vector'(x"A");
pc_in <= std_logic_vector'(x"1");
wait for 10 ns;
--Test 2
immediate_in <= std_logic_vector'(x"BBBBBBBBBBBBBBBB");
reg0_in <= std_logic_vector'(x"BBBBBBBBBBBBBBBB");
reg1_in <= std_logic_vector'(x"BBBBBBBBBBBBBBBB");
instruction_in <= std_logic_vector'(x"B");
pc_in <= std_logic_vector'(x"2");
wait for 30 ns;
--Test 3
immediate_in <= std_logic_vector'(x"CCCCCCCCCCCCCCCC");
reg0_in <= std_logic_vector'(x"CCCCCCCCCCCCCCCC");
reg1_in <= std_logic_vector'(x"CCCCCCCCCCCCCCCC");
instruction_in <= std_logic_vector'(x"C");
pc_in <= std_logic_vector'(x"3");
end_sim <= true;
wait;
end process;
end test;
And fixing the above mentioned errors gives you something besides 'U's:
.
immediate_in is the signal assignment in Test 1 not using a qualified expression relying instead on 9.3.2's rule for determining the type of a bit string literal. The innermost complete context (12.5) used to determine the bit string literal type is the assignment statement itself.
The method of assigning immediate_in would normally be widely used as the preferred method. The type is taken from the target of the assignment.

Related

VHDL-can't add numbers?

Hello I want to build a clock on my ALTERA DE2 that I can adjust the length of by pressing keys.
Now the problem is that when I convert from STD_LOGIC_VECTOR to UNSIGNED the code does not work:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--use ieee.std_logic_unsigned.all; Do not use with numeric_std
entity Adjust_Clock_4_buttens is
port(
clk,clk1 : in STD_LOGIC;
minutes_plus, minutes_minus,houres_plus,houres_minus : in STD_LOGIC;
minutes : IN STD_LOGIC_VECTOR(5 downto 0);
houres : IN STD_LOGIC_VECTOR(4 downto 0);
output_minutes : out STD_LOGIC_VECTOR(5 downto 0);
output_houres : out STD_LOGIC_VECTOR(4 downto 0);
LED_0 : OUT STD_LOGIC;
LED_1 : OUT STD_LOGIC;
LED_2 : OUT STD_LOGIC;
LED_3 : OUT STD_LOGIC
);
end entity Adjust_Clock_4_buttens ;
architecture behavioral of Adjust_Clock_4_buttens is
signal button1_r : std_logic_vector(2 downto 0);
signal button2_r : std_logic_vector(2 downto 0);
signal button3_r : std_logic_vector(2 downto 0);
signal button4_r : std_logic_vector(2 downto 0);
-- signal minutes_total : unsigned(5 downto 0) := (others => '0');
-- signal houres_total : unsigned(4 downto 0) := (others => '0');
signal minutes_total : unsigned(5 downto 0);
signal houres_total : unsigned(4 downto 0);
begin
process(clk)
begin
if (rising_edge(clk) )then
minutes_total<=unsigned(minutes);
houres_total<=unsigned(houres);
-- Shift the value of button in button_r
-- The LSB is unused and is there solely for metastability
button1_r <= button1_r(button1_r'left-1 downto 0) & minutes_plus;
button2_r <= button2_r(button2_r'left-1 downto 0) & minutes_minus;
button3_r <= button3_r(button3_r'left-1 downto 0) & houres_plus;
button4_r <= button4_r(button4_r'left-1 downto 0) & houres_minus;
if button1_r(button1_r'left downto button1_r'left-1) = "01" then -- Button1 rising --button1_r[2:1]
minutes_total <= (minutes_total + 1);
LED_0<='1';LED_1<='0';LED_2<='0';LED_3<='0';
elsif button2_r(button2_r'left downto button2_r'left-1) = "01" then -- Button2 rising --button1_r[2:1]
minutes_total <= (minutes_total-1 );
LED_0<='0';LED_1<='1';LED_2<='0';LED_3<='0';
end if;
if button3_r(button3_r'left downto button3_r'left-1) = "01" then -- Button1 rising --button1_r[2:1]
houres_total <= (houres_total + 1);
LED_0<='0';LED_1<='0';LED_2<='1';LED_3<='0';
elsif button4_r(button4_r'left downto button4_r'left-1) = "01" then -- Button2 rising --button1_r[2:1]
houres_total<= (houres_total-1 );
LED_0<='0';LED_1<='0';LED_2<='0';LED_3<='1';
end if;
end if;
end process;
output_minutes <= std_logic_vector(minutes_total);
output_houres <= std_logic_vector(houres_total);
end architecture behavioral ;
So in this code I get the time from another block the problem start when I try to add minutes and hours and for some reason it does not react to pressing of the keys. Could anyone explain maybe why is that?
The problem might be that you only have the clock in the sensitivity list of your process. Try adding the buttons in the sensitivity list, since they drive your if conditions. (Not sure if that's the problem but I guess it's worth a try)
minutes_total<=unsigned(minutes);
is on 2 lines, inside and outside of the process, which generates multiple line drivers, and will not work, ever!
(didn't read the rest of the code, there may be other problems, like hours not taking an e)
Now that it's inside the process, you need to rename minutes_total as minute_source, else you're incrementing the value only for the one clock cycle when you have a button edge!

VHDL - Index out range even If I made concurrent checking using when-else

I'm implementing a register file where I wanna read asynchronously and write on the rising edge.
I made concurrent checks on the addresses and the writing occurs inside a process.
However, it always cause me a fatal error and I don't know why!
Here's my code if anyone could help and tell me how can I read asynchronously and write on rising edge
Thank you!
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity RegFile is
port(
outData1 : out std_logic_vector(15 downto 0);
outData2 : out std_logic_vector(15 downto 0);
inData : in std_logic_vector(15 downto 0);
writeEn : in std_logic;
reg1Sel : in std_logic_vector(2 downto 0);
reg2Sel : in std_logic_vector(2 downto 0);
writeRegSel : in std_logic_vector(2 downto 0);
clk : in std_logic
);
end RegFile;
architecture Register_File of RegFile is
type registerFile is array(0 to 5) of std_logic_vector(15 downto 0);
signal registers : registerFile;
signal reg1Address,reg2Address : integer;
signal reg1FinalAddressing,reg2FinalAddressing : std_logic_vector(2 downto 0);
begin
--Conversion of logic vector to unsigned integer
reg1Address <= to_integer(unsigned(reg1Sel));
reg2Address <= to_integer(unsigned(reg2Sel));
reg1FinalAddressing <= reg1Sel when (reg1Address<6 ) else
(others => '0');
reg2FinalAddressing <= reg2Sel when (reg2Address<6 ) else
(others => '0');
outData1 <= registers(to_integer(unsigned(reg1FinalAddressing)));
outData2 <= registers(to_integer(unsigned(reg2FinalAddressing)));
process (clk) is
begin
-- Reading from Registers 1 and 2
if rising_edge(clk) then
-- Writing to Register file Case Enabled
if writeEn = '1' then
registers(to_integer(unsigned(writeRegSel))) <= inData;
-- Case a value being written to register file, it will be out simultaneously if
-- the register was already selected. (The updated values are being released instantly).
if reg1Sel = writeRegSel then
outData1 <= inData;
end if;
if reg2Sel = writeRegSel then
outData2 <= inData;
end if;
end if;
end if;
end process;
end Register_File;

VHDL 2008 can't drive a signal with an alias of an external name

Please take a look at the following code, specifically the 3 commented lines at the end. I simulated this with Questasim 10.6c:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity alias_extname_driving_signal is
port(
clk : in std_logic
);
end alias_extname_driving_signal;
architecture primary of alias_extname_driving_signal is
signal buried_control_vector16 : std_logic_vector(15 downto 0) := (others => '0');
begin
buried_control_vector16 <= std_logic_vector(unsigned(buried_control_vector16) + 1) when rising_edge(clk);
end architecture primary;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity alias_extname_driving_signal_tb is
end alias_extname_driving_signal_tb;
architecture primary of alias_extname_driving_signal_tb is
signal clk : std_logic := '0';
signal control_vector16 : std_logic_vector(15 downto 0) := (others => '0');
alias control_vector16_alias is control_vector16;
alias buried_control_vector16_alias is << signal .alias_extname_driving_signal_tb.uut.buried_control_vector16 : std_logic_vector(15 downto 0) >>;
signal vector16 : std_logic_vector(15 downto 0);
begin
clk <= not clk after 10 ns;
control_vector16 <= std_logic_vector(unsigned(control_vector16) + 1) when rising_edge(clk);
uut : entity work.alias_extname_driving_signal
port map(
clk => clk
);
-- vector16 <= << signal .alias_extname_driving_signal_tb.uut.buried_control_vector16 : std_logic_vector(15 downto 0) >>; -- this statement works
-- vector16 <= control_vector16_alias; -- this statement works
-- vector16 <= buried_control_vector16_alias; -- vector16 remains perpetually undefined with this statement
end architecture primary;
As you can see, I'm able to drive a signal with an external name, an alias of a local signal, but not an alias of an external name. Is there any way I can use an alias of an external name to drive a signal in vhdl-2008?
Thanks in advance for your help.
External names can only be declared AFTER the object being referenced is elaborated.
VHDL starts elaborating from the testbench. First it elaborates the declaration region. Then it elaborates the code region in order. If it finds a component, it elaborates it and any subcomponents. When it finishes elaborating the component (and any subcomponents) it picks up elaborating int the testbench where it left off.
Hence, you need to move your alias declaration to either a block statement or a process. The code for the block statement is as follows. Note the label with the block statement is required.
architecture primary of alias_extname_driving_signal_tb is
signal clk : std_logic := '0';
signal control_vector16 : std_logic_vector(15 downto 0) := (others => '0');
alias control_vector16_alias is control_vector16;
signal vector16 : std_logic_vector(15 downto 0);
begin
clk <= not clk after 10 ns;
control_vector16 <= std_logic_vector(unsigned(control_vector16) + 1) when rising_edge(clk);
uut : entity work.alias_extname_driving_signal
port map(
clk => clk
);
myblock : block
alias buried_control_vector16_alias is << signal .alias_extname_driving_signal_tb.uut.buried_control_vector16 : std_logic_vector(15 downto 0) >>;
begin
vector16 <= << signal .alias_extname_driving_signal_tb.uut.buried_control_vector16 : std_logic_vector(15 downto 0) >>; -- this statement works
vector16 <= control_vector16_alias; -- this statement works
vector16 <= buried_control_vector16_alias; -- vector16 remains perpetually undefined with this statement
end block myblock ;
end architecture primary;

Unable to split a Vector in VHDL

I am unable to update reg_1 and reg_2 vectors by splitting reg_mem?
This is my code in VHDL which i had written in MODELSIM:
In other program i tried to split another vector into two parts and store them into two different Vectors.It worked fine.But same syntax is not working in this code
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Register_unit is
port (
reg_read : in std_logic;
reg_write : in std_logic;
reg_mem : inout std_logic_vector(3 downto 0);
reg_start : inout std_logic_vector(3 downto 0);
reg_end : inout std_logic_vector(3 downto 0);
reg_write_comp : out std_logic;
reg_read_comp : out std_logic;
reg_1 : inout std_logic_vector(1 downto 0);
reg_2 : inout std_logic_vector(1 downto 0));
end Register_unit;
architecture Register_unit_arch of Register_unit is
begin
process (reg_read,reg_write)
begin
if (reg_read = '1' and reg_write = '0') then
reg_end <= reg_mem;
reg_read_comp <= '1';
elsif (reg_write = '1' and reg_read = '0') then
reg_mem <= reg_start;
reg_write_comp <= '1';
end if;
reg_1 <= reg_mem(1 downto 0); --reg_1 is not getting updated
reg_2 <= reg_mem(3 downto 2); --reg2 is not getting updated
end process;
end Register_unit_arch;
reg_1 and reg_2 is updated but they are updated to previous value of the reg_mem. This line;
reg_mem <= reg_start;
is not in effect until the end of process. You are making the reg_1 and reg_2 assignment before reg_mem has it's new value!
VHDL doesn't work top down like a programming language even if you are in a process.
In your case you should either use a variable (*) or directly assign from reg_start like this;
reg_1 <= reg_start(1 downto 0);
reg_2 <= reg_start(3 downto 2);
(*) variables are immediately assigned in a process, you can use them similar to programming language variables

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