Refilling Ram vhdl - vhdl

After writing to each address of Ram and then reading every address of Ram, how would I reinitialize the Ram so that when I write to it again a second time it starts off as if it were the first time writing to it or in other words a clean slate.
Breakdown:
1) write to RAM
2) read from Ram
3) set all ram values back to 0? or can I just go ahead and provide address = 0 begin writing from 0-23 again?
Here is my Ram:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity Ram is
Port(
clk : in std_logic;
address : in std_logic_vector(4 downto 0);
write_en : in std_logic;
data_in : in std_logic_vector(15 downto 0);
data_out : out std_logic_vector(15 downto 0)
);
end Ram;
architecture Behavioral of Ram is
type ram_type is array(0 to 23) of std_logic_vector(15 downto 0);
signal Memory : ram_type;
begin
process(clk)
begin
if(rising_edge(clk)) then
if(write_en = '1') then
Memory(to_integer(unsigned(address))) <= data_in;
end if;
data_out <= Memory(to_integer(unsigned(address)));
end if;
end process;
end behavioral;

If you are intending to infer BRAMs in your device it cannot be reset. reset BRAMs is done as part of device configuration. You can always write zeroes (or whetever your initial state is back to the Memory to reinitialize)
However, if you don't care whether it will be synthesized into BRAMs I think the most clean way of doing this is adding a reset port to your system and change your process to take the reset into account. When you want to reset the memory you apply a reset at the input port.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity Ram is
Port(
clk : in std_logic;
rstn : in std_logic;
address : in std_logic_vector(4 downto 0);
write_en : in std_logic;
data_in : in std_logic_vector(15 downto 0);
data_out : out std_logic_vector(15 downto 0)
);
end Ram;
architecture Behavioral of Ram is
type ram_type is array(0 to 23) of std_logic_vector(15 downto 0);
signal Memory : ram_type;
begin
process(clk)
begin
if(rising_edge(clk)) then
if(rstn ='0') then
Memory <= (OTHERS => (OTHERS => '0'));
elsif(write_en = '1') then
Memory(to_integer(unsigned(address))) <= data_in;
end if;
data_out <= Memory(to_integer(unsigned(address)));
end if;
end process;
end behavioral;
An additional remark on your code example. If you intend to infer BRAMs your code is "read-before-write". This will result in slower BRAM performance according to WP231 (https://www.xilinx.com/support/documentation/white_papers/wp231.pdf)

Related

Can't resolve multiple constant drivers for net

I wrote this code. I want to count the numbers that I pressed they key_0 and if I press 2 times then the red led will turn on, how ever I get this error:
Can't resolve multiple constant drivers for net.
The thing is that I try to torn on 2 process at the same time how ever this tow process have the same variable: duty_cycle_counter.
What is the problem?
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity Pwm_control is
generic(display_resolution : INTEGER := 8);
port(
key_0 : in BIT;
green_led : out BIT;
red_led : out BIT
);
end Pwm_control;
architecture Behavioral of Pwm_control is
signal counter : std_logic_vector(display_resolution downto 0);
signal general_counter : std_logic_vector(23 downto 0); -- general_counter is for the clock divider , can get till 23
signal step_10_dc : STD_LOGIC_VECTOR(8 downto 0); --10 step PWM
signal step_5_dc : STD_LOGIC_VECTOR(8 downto 0); --5 step PWM
signal starting_value_0 : STD_LOGIC_VECTOR(8 downto 0); --0 step PWM
signal duty_cycle_counter : STD_LOGIC_VECTOR(8 downto 0);
begin
starting_value_0 <= "000000000";
step_5_dc <= "000011010";
step_10_dc <= "000110011";
duty_cycle_counter <= "000000000";
key_testing : process(key_0) --
begin
if (key_0 = '0') then
green_led <= '1';
duty_cycle_counter <= (duty_cycle_counter + step_5_dc);
else
green_led <= '0';
end if;
end process key_testing;
key_test_red_led : process(duty_cycle_counter)
begin
if (step_10_dc <= duty_cycle_counter) then
red_led <= '1';
end if;
end process key_test_red_led;
end Behavioral;
You're driving duty_cycle_counter continuously with 0 and trying to update it in the key_testing process. It looks like you wanted a start value (possible in most RAM-based FPGAs) or a reset, though in real life it will have some value so you could just leave out the initialization.

VHDL : how to read / write data of 16 bits in RAM with 8 bits per address

I have a VHDL code for reading and writing data of 8 bits to a RAM with 8 bits per address, but i need to make changes to the code in order to read/write data of 16 bits to the RAM with 8 bits per address.
What changes could be done?
The initial code i have is:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity RAM is
port(address: in std_logic_vector(0 to 15);
datain: in std_logic_vector(7 downto 0);
dataout: out std_logic_vector(7 downto 0);
WE, CS, OE: in std_logic);
end entity RAM;
architecture behavior6 of RAM is
type RAM_type is array (0 to 2**16) of std_logic_vector(7 downto 0);
signal RAM1: RAM_type;
begin
process (address, CS, WE, OE)
begin
dataout <= (others => 'Z'); --chip is not selected (this is the first row of the T.T)
if (CS = '0')
then
if WE= '0' then --we want to write
RAM1(to_integer(unsigned(address))) <= datain;
end if;
if WE= '1' and OE= '0'
then--we want to read
dataout <= RAM1(to_integer(unsigned(address)));
else
dataout <= (others => 'Z');
end if;
end if;
end process;
end behavior6;
Try this code
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity RAM is
port(address: in std_logic_vector(7 down to 0);
datain: in std_logic_vector(15 downto 0);
dataout: out std_logic_vector(15 downto 0);
WE, CS, OE: in std_logic);
end entity RAM;
architecture behavior6 of RAM is
type RAM_type is array (255 down to 0) of std_logic_vector(15 downto 0);
signal RAM1:memory:=(others=>"0000000000000000");
begin
process (address, CS, WE, OE)
variable a:integer range 0 to 255;
begin
a:=conv_integer(address);
if (CS = '0')
then
if WE= '0' then
RAM1(a)<=datain;
end if;
if WE= '1' and OE= '0'
then
dataout<=RAM1(a);
end if;
end if;
end process;
end behavior6;

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.

VHDL - Writing To Registers

I want to use four push buttons as inputs and three seven-segment LED displays as outputs. Two push buttons should step up and down through the sixteen RAM locations; the other two should increment and decrement the contents of the currently-displayed memory location. One seven segment display should show the current address (0–F), and two others should display the contents of that location in hexadecimal (00–FF). This is my code to attempt to do this (I haven't implemented the display yet):
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity raminfr is
port (
clk : in std_logic;
we : in std_logic;
do : out unsigned(7 downto 0)
);
end raminfr;
architecture rtl of raminfr is
type ram_type is array (0 to 15) of unsigned(7 downto 0);
signal RAM : ram_type;
signal read_a : unsigned(3 downto 0);
signal a : unsigned(3 downto 0);
signal di : unsigned(7 downto 0);
signal clock : std_logic;
signal key : std_logic_vector(3 downto 0);
begin
U1: entity work.lab1 port map (
clock =>clock,
key => key,
register_counter => a,
value_counter => di
);
process (clk)
begin
if rising_edge(clk) then
if we = '1' then
RAM(to_integer(a)) <= di;
end if;
read_a <= a;
end if;
end process;
do <= RAM(to_integer(read_a));
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity lab1 is
port(
clock : in std_logic;
key : in std_logic_vector(3 downto 0);
value_counter : buffer unsigned(7 downto 0) ;
register_counter : buffer unsigned(3 downto 0)
);
end lab1;
architecture up_and_down of lab1 is
signal value_in_ram : unsigned(7 downto 0);
signal clk : std_logic;
signal we : std_logic;
begin
U1: entity work.raminfr port map (
do=>value_in_ram,
clk=>clk,
we=>we
);
process(clock, value_counter, register_counter)
begin
if rising_edge(clock) then
if (key(3)='0' and key(2)='0' and key(1)='1' and key(0)='0') then
value_counter <= value_counter + "1";
elsif (key(3)='0' and key(2)='0' and key(1)='0' and key(0)='1') then
value_counter <= value_counter - "1";
elsif (key(3)='1' and key(2)='0' and key(1)='0' and key(0)='0') then
register_counter<= register_counter + "1";
value_counter <= value_in_ram;
elsif (key(3)='0' and key(2)='1' and key(1)='0' and key(0)='0') then
register_counter<= register_counter - "1";
value_counter <= value_in_ram;
end if;
end if;
end process;
end architecture up_and_down;
When I try to compile this, I get the following errors repeating over and over:
Error (12051): Project too complex: hierarchy path is too long
Error (12052): Entity "lab1" is instantiated by entity "raminfr"
Error (12052): Entity "raminfr" is instantiated by entity "lab1"
This is obviously due to the fact that I have port mapped each entity in the other, but I don't know any other way to accomplish what I want to accomplish. Can somebody suggest alternatives?
This is a guess since it's not too clear what you want to do. It seems that the problem is one of design : you have a good idea what the end result should do, but it's not clear how to decompose that into components which interact in the simplest way to accomplish the goal.
I am basing this guess on the fact that the active code in "raminfr" stores and loads data independent of the other stuff that has crept in.
So I am going to suggest that "raminfr" be cleaned up as just a memory component WITHOUT any of the other stuff. It can then be embedded in the "lab1" component which handles keys, and stores and displays values from the correct registers. It can also be reused anywhere else you need a memory.
So let's look at raminfr.
entity raminfr is
port (
clk : in std_logic;
we : in std_logic;
do : out unsigned(7 downto 0)
);
end raminfr;
It has a clock, a write enable input, and a data output. But curiously, no address or data inputs! Now, memory is such a standard "design pattern" that deviation from it is probably ill advised, so let's add them...
entity raminfr is
port (
clk : in std_logic;
we : in std_logic;
addr : in unsigned(3 downto 0);
di : in unsigned(7 downto 0);
do : out unsigned(7 downto 0)
);
end raminfr;
Some variants of the memory pattern have other features; read enables, output enables, separate read and write clocks, etc but this simple one will do here.
You can also use generics to customise its size, modifying its data and address bus widths to match. This makes it much more useful and saves a proliferation of similar but different modules...
Let's clean up the architecture to match.
architecture rtl of raminfr is
type ram_type is array (0 to 15) of unsigned(7 downto 0);
signal RAM : ram_type;
signal read_a : unsigned(3 downto 0);
begin
process (clk)
...
end process;
do <= RAM(to_integer(read_a));
end rtl;
Now we can instantiate it in the "lab1" module, connecting up its new ports
U1: entity work.raminfr port map (
addr => register_counter, -- was "a", typo
di => value_counter,
do => value_in_ram,
clk => clk,
we => we
);
and making any supporting changes to the rest of lab1.
This is not the only reasonable decomposition : you could also make "lab1" a simple component without its own storage and bring out other necessary signals as ports. Then you would need a third "top level" entity whose architecture interconnected lab1 and raminfr.

VHDL setting constant data in RAM

Recently i'm using VHDL to write a 16-but RAM. My code is:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.Numeric_Std.all;
entity RAM is
port(
PC_in: in std_logic_vector (5 downto 0);
EN_WR_in: in std_logic_vector (1 downto 0);
RAM_in : in std_logic_vector(15 downto 0);
RAM_out : out std_logic_vector(15 downto 0);
test : out integer
);
end RAM;
architecture Behavioral of RAM is
type ram_t is array (63 downto 0) of std_logic_vector(15 downto 0);
signal ram : ram_t;
begin
PROCESS (EN_WR_in)
BEGIN
if (EN_WR_in(1)='1') then
IF (EN_WR_in(0) = '1') THEN
ram(conv_integer(unsigned(PC_in))) <= RAM_in;
else
RAM_out <= ram(conv_integer(unsigned(PC_in)));
end if;
else
RAM_out <="ZZZZZZZZZZZZZZZZ";
end if;
END PROCESS;
ram(20) <= "0000100010010000";
end Behavioral;
The problem that i facing with is i need to set some constant data in the ram just like
ram(20) <= "0000100010010000";
But the constant data didn't exist during simulation. Is there any way to solve it?
Thanks.
You can initialize the ram when you declare it:
signal ram : ram_t := ( "0000100010010000", x"1234", ... );
or perhaps
signal ram : ram_t := ( 20 => "0000100010010000", others => (others=>'0') );

Resources