Search code examples
vhdlverilog

vhdl equivalent for initial block in verilog


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


Solution

  • 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.