I am trying to convert some Verilog code to VHDL. I have difficulties to translate initial block in Verilog to VHDL properly.
As far as I know, the initial block corresponds to the process statement without a sensitivity list but we have to add a "wait" statement before the "end process".I tried it but it did not work. I tried some other methods too (using exit clause, conditional clause ( wait until), "for- generate" without process, etc) but none was successful.
Here is the Verilog code I want to convert, and it works properly
module MyRAM #(parameter DATA_WIDTH=24, parameter ADDR_WIDTH=10)
(
input [(DATA_WIDTH-1):0] data,
input [(ADDR_WIDTH-1):0] read_addr, write_addr,
input we, clk,
output reg [(DATA_WIDTH-1):0] q
);
// Declare the RAM variable
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
initial
begin : INIT
integer i;
for(i = 1; i < ((2**ADDR_WIDTH)-1); i = i+1) begin
if (i == 132) ram[i] = 24'h550000;
else if (i == 133) ram[i] = 24'h005500;
else if (i == 134) ram[i] = 24'h000055;
else ram[i] = 24'h000000;
end
//*/
end
always @ (negedge clk)
begin
// Write
if (we)
ram[write_addr] <= data;
q <= ram[read_addr];
end
endmodule
and this is the VHDL code I have written so far:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity MyRAM is
generic
(DATA_WIDTH: integer;
ADDR_WIDTH: integer);
port
(
data :in std_logic_vector ((DATA_WIDTH-1) downto 0);
read_addr :in std_logic_vector((ADDR_WIDTH-1) downto 0);
write_addr :in std_logic_vector(( DATA_WIDTH-1) downto 0);
we :in std_logic;
clk :in std_logic;
q :out std_logic_vector( 23 downto 0)
);
end MyRAM;
architecture behavioral of MyRAM is
constant case1:std_logic_vector(23 downto 0):=
(16=>'1',18=>'1',20=>'1',22=>'1',others=>'0');
constant case2:std_logic_vector(23 downto 0):=
(8=>'1',10=>'1',12=>'1',14=>'1',others=>'0');
constant case3:std_logic_vector(23 downto 0):=
(0=>'1',2=>'1',4=>'1',6=>'1',others=>'0');
type ram is array ( 0 to (2**ADDR_WIDTH-1)) of
std_logic_vector((DATA_WIDTH-1) downto 0);
shared variable origram:ram;
signal s_q: std_logic_vector(23 downto 0);
begin
process
begin
for ii in 1 to (2**ADDR_WIDTH-1) loop
if (ii = 132) then
origram(ii) := case1;
elsif (ii = 133) then
origram(ii) := case2;
elsif (ii = 134) then
origram(ii) := case3;
else
origram(ii) :=(others=>'0');
end if;
end loop;
wait;
end process;
process (clk)
begin
if falling_edge(clk) then
if (we ='1') then
origram(to_integer(unsigned(write_addr))) := data;
s_q <= origram(to_integer(unsigned(read_addr)));
end if;
end if;
end process;
q<=s_q;
end behavioral;
And this is the error message: Error (10533): VHDL Wait Statement error at MyRAM.vhd(88): Wait Statement must contain condition clause with UNTIL keyword
I do not have much experience in these languages, so I would appreciate any kind of help
The answer is both yes and no. While yes, you can do pretty much what you can do in an initial block in a process, in your situation the answer is you are actually initialising a signal. For this you need to use a function, and set the initial value:
type ram is array ( 0 to (2**ADDR_WIDTH-1)) of std_logic_vector((DATA_WIDTH-1) downto 0);
function init_ram return ram is
variable r : ram;
begin
-- set the contents of the ram
end function init_ram;
shared variable origram:ram := init_ram;
Processes with wait at the end are only for simulation (which would mimic an initial block in verilog used for testbench stimulus)
Note: from VHDL 2002, using a shared variable like this is illegal as it should be a protected type (which is not synthesisable currently). The only reason you might want a shared variable (rather than a signal) to infer a ram is to get write-before-read behaviour in a RAM. It is very annoying most of the Xilinx Inference examples use a shared variable. Switching your code to VHDL2008 will throw the error mentioned above.