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') );
Related
I have a Problem. I have an array of std_logic_vector and I input a value unsinged(3 downto 0) and I want to use value as the Index of the array.
So far so good but I should get a std_logic_vector out of the array and put in the Output segments (which is also a std_logic_vector with the same size) but I get the error:
> can't match type conversion with type array type "std_logic_vector"
here is my Code:
> library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity getarrayvalue is
port(
value : in unsigned(3 downto 0);
clk : in std_logic;
segments : out std_logic_vector(6 downto 0)
);
end entity;
architecture v1 of getarrayvalue is
type rom_type is array(0 to 9) of std_logic_vector(6 downto 0);
signal rom: rom_type :=("1111110","0110000","1101101","1111001","0110011","1011011","1011111","1110000","1111111","1111011");
signal val_i: integer;
val_i <= to_integer(value);
process(clk)
begin
if rising_edge(clk) then
segments <= rom_type(val_i);
end if;
end process;
end architecture;
Does anyone know how to fix this problem ? Thanks!
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;
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)
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;
For my project I need to reduce a noise of an ADC output and implemented a simple moving average filter in VHDL.
Although it works in simulation (see the picture):
it has some strange behavior if I display it on the chipscope when the system is running in FPGA (see the picture):
The VHDL code I use for the moving average is as follows:
library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.all;
use ieee.numeric_std.all;
entity moving_avg is
generic(
SAMPLES_COUNT : integer := 32
);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
sample_i : in std_logic_vector(11 downto 0);
avg_o : out std_logic_vector(11 downto 0)
);
end;
architecture rtl of moving_avg is
type sample_buff_t is array (1 to SAMPLES_COUNT) of std_logic_vector(11 downto 0);
signal sample_buffer : sample_buff_t;
signal sum : std_logic_vector(31 downto 0);
constant wid_shift : integer := integer(ceil(log2(real(SAMPLES_COUNT))));
signal avg_interm_s : std_logic_vector(31 downto 0);
begin
process (clk_i, rst_n_i) begin
if rst_n_i='1' then
sample_buffer <= (others => sample_i);
sum <= std_logic_vector(unsigned(resize(unsigned(sample_i), sum'length)) sll wid_shift) ;
elsif rising_edge(clk_i) then
sample_buffer <= sample_i & sample_buffer(1 to SAMPLES_COUNT-1);
sum <= std_logic_vector(unsigned(sum) + unsigned(sample_i) - unsigned(sample_buffer(SAMPLES_COUNT)));
end if;
end process;
avg_interm_s <= std_logic_vector((unsigned(sum) srl wid_shift));
avg_o <= avg_interm_s(11 downto 0);
end;
I use Xilinx Vivado tool 2015.2 running on Ubuntu 14.04 x64.
Could you please help me to identify the problem, such
that results in simulation correspond to results after synthesis?