Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

What is the vhdl equivalent of "initial begin" to initialize a ROM.

Status
Not open for further replies.

Cesar0182

Member level 5
Joined
Feb 18, 2019
Messages
85
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
825
Greetings ... tell you that a couple of days ago I am trying to translate a verilog file to vhdl and I found the next block that initializes a ROM.

Code:
// Make sure the memory is implemented as distributed
   (* rom_style = "distributed" *)
   reg [38:0]  rom [63:0];  // 39 bit word 64 words deep

   initial begin
      // rom entries contain (in order) the address, a bitmask, and a bitset
      //***********************************************************************
      // State 1 Initialization
      //***********************************************************************

      // Store the power bits
      rom[0] = {7'h28, 16'h0000, 16'hFFFF};

      // Store CLKOUT0 divide and phase
      rom[1]  = (S1_CLKOUT0_FRAC_EN == 0) ?
						{7'h09, 16'h8000, S1_CLKOUT0[31:16]}:
						{7'h09, 16'h8000, S1_CLKOUT0_FRAC_CALC[31:16]};
      rom[2]  = (S1_CLKOUT0_FRAC_EN == 0) ?
						{7'h08, 16'h1000, S1_CLKOUT0[15:0]}:
						{7'h08, 16'h1000, S1_CLKOUT0_FRAC_CALC[15:0]};

      // Store CLKOUT1 divide and phase
      rom[3]  = {7'h0A, 16'h1000, S1_CLKOUT1[15:0]};
      rom[4]  = {7'h0B, 16'hFC00, S1_CLKOUT1[31:16]};

      // Store CLKOUT2 divide and phase
      rom[5]  = {7'h0C, 16'h1000, S1_CLKOUT2[15:0]};
      rom[6]  = {7'h0D, 16'hFC00, S1_CLKOUT2[31:16]};

      // Store CLKOUT3 divide and phase
      rom[7]  = {7'h0E, 16'h1000, S1_CLKOUT3[15:0]};
      rom[8]  = {7'h0F, 16'hFC00, S1_CLKOUT3[31:16]};

      // Store CLKOUT4 divide and phase
      rom[9]  = {7'h10, 16'h1000, S1_CLKOUT4[15:0]};
      rom[10]  = {7'h11, 16'hFC00, S1_CLKOUT4[31:16]};

      // Store CLKOUT5 divide and phase
      rom[11] = {7'h06, 16'h1000, S1_CLKOUT5[15:0]};
      rom[12] = (S1_CLKOUT0_FRAC_EN == 0) ?
                {7'h07, 16'hC000, S1_CLKOUT5[31:16]}:
                {7'h07, 16'hC000, S1_CLKOUT5[31:30], S1_CLKOUT0_FRAC_CALC[35:32],S1_CLKOUT5[25:16]};

      // Store CLKOUT6 divide and phase
      rom[13] = {7'h12, 16'h1000, S1_CLKOUT6[15:0]};
      rom[14] = (S1_CLKFBOUT_FRAC_EN == 0) ?
                {7'h13, 16'hC000, S1_CLKOUT6[31:16]}:
                {7'h13, 16'hC000, S1_CLKOUT6[31:30], S1_CLKFBOUT_FRAC_CALC[35:32],S1_CLKOUT6[25:16]};

      // Store the input divider
      rom[15] = {7'h16, 16'hC000, {2'h0, S1_DIVCLK[23:22], S1_DIVCLK[11:0]} };

      // Store the feedback divide and phase
      rom[16] = (S1_CLKFBOUT_FRAC_EN == 0) ?
                {7'h14, 16'h1000, S1_CLKFBOUT[15:0]}:
                {7'h14, 16'h1000, S1_CLKFBOUT_FRAC_CALC[15:0]};
      rom[17] = (S1_CLKFBOUT_FRAC_EN == 0) ?
                {7'h15, 16'h8000, S1_CLKFBOUT[31:16]}:
                {7'h15, 16'h8000, S1_CLKFBOUT_FRAC_CALC[31:16]};

      // Store the lock settings
      rom[18] = {7'h18, 16'hFC00, {6'h00, S1_LOCK[29:20]} };
      rom[19] = {7'h19, 16'h8000, {1'b0 , S1_LOCK[34:30], S1_LOCK[9:0]} };
      rom[20] = {7'h1A, 16'h8000, {1'b0 , S1_LOCK[39:35], S1_LOCK[19:10]} };

      // Store the filter settings
      rom[21] = {7'h4E, 16'h66FF,
                S1_DIGITAL_FILT[9], 2'h0, S1_DIGITAL_FILT[8:7], 2'h0,
                S1_DIGITAL_FILT[6], 8'h00 };
      rom[22] = {7'h4F, 16'h666F,
                S1_DIGITAL_FILT[5], 2'h0, S1_DIGITAL_FILT[4:3], 2'h0,
                S1_DIGITAL_FILT[2:1], 2'h0, S1_DIGITAL_FILT[0], 4'h0 };

      //***********************************************************************
      // State 2 Initialization
      //***********************************************************************

      // Store the power bits
      rom[23] = {7'h28, 16'h0000, 16'hFFFF};

      // Store CLKOUT0 divide and phase
      rom[24] = (S2_CLKOUT0_FRAC_EN == 0) ?
                {7'h09, 16'h8000, S2_CLKOUT0[31:16]}:
                {7'h09, 16'h8000, S2_CLKOUT0_FRAC_CALC[31:16]};
      rom[25] = (S2_CLKOUT0_FRAC_EN == 0) ?
                {7'h08, 16'h1000, S2_CLKOUT0[15:0]}:
                {7'h08, 16'h1000, S2_CLKOUT0_FRAC_CALC[15:0]};

      // Store CLKOUT1 divide and phase
      rom[26] = {7'h0A, 16'h1000, S2_CLKOUT1[15:0]};
      rom[27] = {7'h0B, 16'hFC00, S2_CLKOUT1[31:16]};

      // Store CLKOUT2 divide and phase
      rom[28] = {7'h0C, 16'h1000, S2_CLKOUT2[15:0]};
      rom[29] = {7'h0D, 16'hFC00, S2_CLKOUT2[31:16]};

      // Store CLKOUT3 divide and phase
      rom[30] = {7'h0E, 16'h1000, S2_CLKOUT3[15:0]};
      rom[31] = {7'h0F, 16'hFC00, S2_CLKOUT3[31:16]};

      // Store CLKOUT4 divide and phase
      rom[32] = {7'h10, 16'h1000, S2_CLKOUT4[15:0]};
      rom[33] = {7'h11, 16'hFC00, S2_CLKOUT4[31:16]};

      // Store CLKOUT5 divide and phase
      rom[34] = {7'h06, 16'h1000, S2_CLKOUT5[15:0]};
      rom[35] = (S2_CLKOUT0_FRAC_EN == 0) ?
                {7'h07, 16'hC000, S2_CLKOUT5[31:16]}:
                {7'h07, 16'hC000, S2_CLKOUT5[31:30], S2_CLKOUT0_FRAC_CALC[35:32],S2_CLKOUT5[25:16]};

      // Store CLKOUT6 divide and phase
      rom[36] = {7'h12, 16'h1000, S2_CLKOUT6[15:0]};
      rom[37] = (S2_CLKFBOUT_FRAC_EN == 0) ?
                {7'h13, 16'hC000, S2_CLKOUT6[31:16]}:
                {7'h13, 16'hC000, S2_CLKOUT6[31:30], S2_CLKFBOUT_FRAC_CALC[35:32],S2_CLKOUT6[25:16]};

      // Store the input divider
      rom[38] = {7'h16, 16'hC000, {2'h0, S2_DIVCLK[23:22], S2_DIVCLK[11:0]} };

      // Store the feedback divide and phase
      rom[39] = (S2_CLKFBOUT_FRAC_EN == 0) ?
                {7'h14, 16'h1000, S2_CLKFBOUT[15:0]}:
                {7'h14, 16'h1000, S2_CLKFBOUT_FRAC_CALC[15:0]};
      rom[40] = (S2_CLKFBOUT_FRAC_EN == 0) ?
                {7'h15, 16'h8000, S2_CLKFBOUT[31:16]}:
                {7'h15, 16'h8000, S2_CLKFBOUT_FRAC_CALC[31:16]};

      // Store the lock settings
      rom[41] = {7'h18, 16'hFC00, {6'h00, S2_LOCK[29:20]} };
      rom[42] = {7'h19, 16'h8000, {1'b0 , S2_LOCK[34:30], S2_LOCK[9:0]} };
      rom[43] = {7'h1A, 16'h8000, {1'b0 , S2_LOCK[39:35], S2_LOCK[19:10]} };

      // Store the filter settings
      rom[44] = {7'h4E, 16'h66FF,
                S2_DIGITAL_FILT[9], 2'h0, S2_DIGITAL_FILT[8:7], 2'h0,
                S2_DIGITAL_FILT[6], 8'h00 };
      rom[45] = {7'h4F, 16'h666F,
                S2_DIGITAL_FILT[5], 2'h0, S2_DIGITAL_FILT[4:3], 2'h0,
                S2_DIGITAL_FILT[2:1], 2'h0, S2_DIGITAL_FILT[0], 4'h0 };

      // Initialize the rest of the ROM
      rom[46] = {7'h28,32'h0000_0000};
      for(ii = 47; ii < 64; ii = ii +1) begin
         rom[ii] = 0;
      end
   end

I have been suggested to use a process as shown below, but this is not working for me.

Code:
type array_64x39 is array (63 downto 0) of std_logic_vector(38 DOWNTO 0);
attribute rom_style : string;
SIGNAL rom          : array_64x39 register;  
attribute rom_style of rom : signal is "distributed";

process
begin
    -- Store the power bits
  rom(0)            <= "0101000" & x"0000" & x"FFFF";
  
  -- Store CLKOUT0 divide and phase
  S1_CLKOUT0_FRAC_A <= ("0001001" & x"8000" & S1_CLKOUT0(31 downto 16)) when S1_CLKOUT0_FRAC_EN = 0 else ("0001001" & x"8000" & S1_CLKOUT0_FRAC_CALC(31 downto 16));
  rom(1)            <= S1_CLKOUT0_FRAC_A;
  
  S1_CLKOUT0_FRAC_B <= ("0001000" & x"1000" & S1_CLKOUT0(15 downto 0)) when(S1_CLKOUT0_FRAC_EN = 0) else ("0001000" & x"1000" & S1_CLKOUT0_FRAC_CALC(15 downto 0));
  rom(2)            <= S1_CLKOUT0_FRAC_B;
  
  -- Store CLKOUT1 divide and phase
  rom(3)            <= "0001010" & x"1000" & S1_CLKOUT1(15 downto 0);
  rom(4)            <= "0001011" & x"FC00" & S1_CLKOUT1(31 downto 16);
  
  -- Store CLKOUT2 divide and phase
  rom(5)            <= "0001100" & x"1000" & S1_CLKOUT2(15 downto 0);
  rom(6)            <= "0001101" & x"FC00" & S1_CLKOUT2(31 downto 16);
  
  -- Store CLKOUT3 divide and phase
  rom(7)            <= "0001110" & x"1000" & S1_CLKOUT3(15 downto 0);
  rom(8)            <= "0001111" & x"FC00" & S1_CLKOUT3(31 downto 16);
  
  -- Store CLKOUT4 divide and phase
  rom(9)            <= "0010000" & x"1000" & S1_CLKOUT4(15 downto 0);
  rom(10)           <= "0010001" & x"FC00" & S1_CLKOUT4(31 downto 16);
  
  -- Store CLKOUT5 divide and phase
  rom(11)           <= "0000110" & x"1000" & S1_CLKOUT5(15 downto 0);
  S1_CLKOUT0_FRAC_C <= ("0000111" & x"C000" & S1_CLKOUT5(31 downto 16)) when (S1_CLKOUT0_FRAC_EN = 0) else ("0000111" & x"C000" & S1_CLKOUT5(31 downto 30) & S1_CLKOUT0_FRAC_CALC(35 downto 32) & S1_CLKOUT5(25 downto 16));
  rom(12)           <= S1_CLKOUT0_FRAC_C;
  
  -- Store CLKOUT6 divide and phase
  rom(13)           <= "0010010" & x"1000" & S1_CLKOUT6(15 downto 0);
  S1_CLKOUT0_FRAC_D <= ("0010011" & x"C000" & S1_CLKOUT6(31 downto 16)) when (S1_CLKFBOUT_FRAC_EN = 0) else ("0010011" & x"C000" & S1_CLKOUT6(31 downto 30) & S1_CLKFBOUT_FRAC_CALC(35 downto 32) & S1_CLKOUT6(25 downto 16));
  rom(14)           <=  S1_CLKOUT0_FRAC_D;
  
  -- Store the input divider
  rom(15)           <= "0010110" & x"C000" & ("00" & S1_DIVCLK(23 downto 22) & S1_DIVCLK(11 downto 0));
  
  -- Store the feedback divide and phase
  S1_CLKOUT0_FRAC_E <= ("0010100" & x"1000" & S1_CLKFBOUT(15 downto 0)) when (S1_CLKFBOUT_FRAC_EN = 0) else ("0010100" & x"1000" & S1_CLKFBOUT_FRAC_CALC(15 downto 0));
  rom(16)           <= S1_CLKOUT0_FRAC_E ;
  
  S1_CLKOUT0_FRAC_F <= ("0010011" & x"8000" & S1_CLKFBOUT(31 downto 16)) when (S1_CLKFBOUT_FRAC_EN = 0) else ("0010011" & x"8000" & S1_CLKFBOUT_FRAC_CALC(31 downto 16));  
  rom(17)           <=  S1_CLKOUT0_FRAC_F;
  
  -- Store the lock settings
  rom(18)           <= "0011000" & x"FC00" & ("000000" & S1_LOCK(29 downto 20));
  rom(19)           <= "0011001" & x"8000" & ('0'  & S1_LOCK(34 downto 30) & S1_LOCK(9 downto 0));
  rom(20)           <= "0011010" & x"8000" & ('0'  & S1_LOCK(39 downto 35) & S1_LOCK(19 downto 10));
  
  -- Store the filter settings
  rom(21)           <= "1001110" & x"66FF" & S1_DIGITAL_FILT(9) & "00" & S1_DIGITAL_FILT(8 downto 7) & "00" & S1_DIGITAL_FILT(6) & x"00";
  rom(22)           <= "1001111" & x"666F" & S1_DIGITAL_FILT(5) & "00" & S1_DIGITAL_FILT(4 downto 3) & "00" & S1_DIGITAL_FILT(2 downto 1) & "00" & S1_DIGITAL_FILT(0) & x"0" ;
  
  --***********************************************************************
  --State 2 Initialization
         --***********************************************************************
  -- Store the power bits
  rom(23)           <= "0101000" & x"0000" & x"FFFF";
  
  -- Store CLKOUT0 divide and phase
  S1_CLKOUT0_FRAC_G <=  ("0001001" & x"8000" & S2_CLKOUT0(31 downto 16))+8
   when (S2_CLKOUT0_FRAC_EN = 0) else ("0001001" & x"8000" & S2_CLKOUT0_FRAC_CALC(31 downto 16));
  rom(24)           <= S1_CLKOUT0_FRAC_G;
  
  S1_CLKOUT0_FRAC_H <= ("0001000" & x"1000" & S2_CLKOUT0(15 downto 0)) when (S2_CLKOUT0_FRAC_EN = 0) else ("0001000" & x"1000" & S2_CLKOUT0_FRAC_CALC(15 downto 0));
  rom(25)           <= S1_CLKOUT0_FRAC_H;
  
  -- Store CLKOUT1 divide and phase
  rom(26)           <= "0001010" & x"1000" & S2_CLKOUT1(15 downto 0);
  rom(27)           <= "0001011" & x"FC00" & S2_CLKOUT1(31 downto 16);
  
  -- Store CLKOUT2 divide and phase
  rom(28)           <= "0001100" & x"1000" & S2_CLKOUT2(15 downto 0);
  rom(29)           <= "0001101" & x"FC00" & S2_CLKOUT2(31 downto 16);
  
  -- Store CLKOUT3 divide and phase
  rom(30)           <= "0001110" & x"1000" & S2_CLKOUT3(15 downto 0);
  rom(31)           <= "0001111" & x"FC00" & S2_CLKOUT3(31 downto 16);
  
  -- Store CLKOUT4 divide and phase
  rom(32)           <= "0010000" & x"1000" & S2_CLKOUT4(15 downto 0);
  rom(33)           <= "0010001" & x"FC00" & S2_CLKOUT4(31 downto 16);
  
  -- Store CLKOUT5 divide and phase
  rom(34)           <= "0000110" & x"1000" & S2_CLKOUT5(15 downto 0);
  
  S1_CLKOUT0_FRAC_I <= ("0000111" & x"C000" & S2_CLKOUT5(31 downto 16)) when (S2_CLKOUT0_FRAC_EN = 0) else (x"0007" & x"C000" & S2_CLKOUT5(31 downto 30) & S2_CLKOUT0_FRAC_CALC(35 downto 32) & S2_CLKOUT5(25 downto 16));
  rom(35)           <= S1_CLKOUT0_FRAC_I;
  
  -- Store CLKOUT6 divide and phase
  rom(36)           <= "0010010" & x"1000" & S2_CLKOUT6(15 downto 0);
  
  S1_CLKOUT0_FRAC_J <= "0010011" & x"C000" & S2_CLKOUT6(31 downto 16) when (S2_CLKFBOUT_FRAC_EN = 0) else "0010011" & x"C000" & S2_CLKOUT6(31 downto 30) & S2_CLKFBOUT_FRAC_CALC(35 downto 32) & S2_CLKOUT6(25 downto 16);
  rom(37)           <= S1_CLKOUT0_FRAC_J;
  
  -- Store the input divider
  rom(38)           <= "0010110" & x"C000" & ("00" & S2_DIVCLK(23 downto 22) & S2_DIVCLK(11 downto 0));
  
  -- Store the feedback divide and phase
  S1_CLKOUT0_FRAC_K <= "0010100" & x"1000" & S2_CLKFBOUT(15 downto 0) when (S2_CLKFBOUT_FRAC_EN = 0) else "0010100" & x"1000" & S2_CLKFBOUT_FRAC_CALC(15 downto 0);
  rom(39)           <= S1_CLKOUT0_FRAC_K;
  
  S1_CLKOUT0_FRAC_L <= "0010101" & x"8000" & S2_CLKFBOUT(31 downto 16) when (S2_CLKFBOUT_FRAC_EN = 0) else "0010101" & x"8000" & S2_CLKFBOUT_FRAC_CALC(31 downto 16);                
  rom(40)           <= S1_CLKOUT0_FRAC_L;
  
  -- Store the lock settings
  rom(41)           <= "0011000" & x"FC00" & ("000000" & S2_LOCK(29 downto 20));
  rom(42)           <= "0011001" & x"8000" & ('0' & S2_LOCK(34 downto 30) & S2_LOCK(9 downto 0));
  rom(43)           <= "0011010" & x"8000" & ('0' & S2_LOCK(39 downto 35) & S2_LOCK(19 downto 10));
  
  -- Store the filter settings
  rom(44)           <= "1001110" & x"66FF" & S2_DIGITAL_FILT(9) & "00"  & S2_DIGITAL_FILT(8 downto 7)  & "00"  & S2_DIGITAL_FILT(6)  & x"00" ;
  rom(45)           <= "1001111" & x"666F"  & S2_DIGITAL_FILT(5)  & "00"  & S2_DIGITAL_FILT(4 downto 3)  & "00"  & S2_DIGITAL_FILT(2 downto 1)  & "00"  & S2_DIGITAL_FILT(0) & x"0";
  
  -- Initialize the rest of the ROM
  rom(46)           <= "0101000" & x"00000000";
  
    fill : for ii in 47 to 63 loop
      rom(ii) <= "000000000000000000000000000000000000000";
    end  loop fill;
end process;

Can someone help me with this problem please.
 

A process isn't the equivalent of an initial block, you should have an initializer for the signal array representing the rom. It may use a function generating the data.

I'm not sure about the variable elements in your initial block. Are they parameters?
 

Thanks for answering FvM, tell you that S1_CLKOUT0_FRAC_EN or S1_CLKOUT0 if they are parameters and S1_CLKOUT0_FRAC_A and others are signals that I had to create since I could not make a direct assignment to the rom.
A question to your suggestion, how can I call this function to initialize the rom.
 

you can call a function during initiialisation:


Code VHDL - [expand]
1
2
3
4
5
6
7
function some_init_func return integer is
begin
  return 10;
end function;
 
constant SOME_CONSTANT : integer := some_init_func;
signal int_sig : integer := some_init_func;

 

you can call a function during initiialisation
Typically, the initialisation function has an array result and sets the whole ROM at once. Inside the function, a for loop or case construct delivers the individual constant values.

Alternatively, a ROM can be initialized in a generate loop, like below


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- uses parameters OLEN, ILEN, RLEN
CONSTANT ROMSIZE : INTEGER  := 2**RLEN;
CONSTANT ROMMAX : INTEGER  := 2**OLEN;
CONSTANT ROMMAX : INTEGER  := 2**OLEN-ILEN;
TYPE ATANTAB IS ARRAY(0 TO ROMSIZE-1) OF UNSIGNED (OLEN-1 DOWNTO 0);
TYPE ATANTAB2 IS ARRAY(0 TO ROMSIZE-1) OF UNSIGNED (OLEN-RLEN DOWNTO 0);
SIGNAL ATANROM : ATANTAB;
SIGNAL ATANROM2 : ATANTAB2;
 
BEGIN
GENROM:
FOR idx in 0 TO ROMSIZE-1 GENERATE
  CONSTANT x: REAL := ARCTAN(real(idx)/real(ROMSIZE))/MATH_PI_OVER_4;
  CONSTANT xn: UNSIGNED (OLEN-1 DOWNTO 0) := CONV_UNSIGNED(INTEGER(x*real(ROMMAX)),OLEN);
  CONSTANT x2: REAL := ARCTAN(real(idx+1)/real(ROMSIZE))/MATH_PI_OVER_4 - x;
  CONSTANT xn2: UNSIGNED (OLEN-RLEN DOWNTO 0) := CONV_UNSIGNED(INTEGER(x2*real(ROMMAX2)),OLEN-RLEN+1);
BEGIN
  ATANROM(idx) <= UNSIGNED(xn); 
  ATANROM2(idx) <= UNSIGNED(xn2);   
END GENERATE;



S1_CLKOUT0_FRAC_A and others are signals that I had to create since I could not make a direct assignment to the rom.
All ROM values must be known at compile time. They can depend on calculated constants, but not signals.
 

If it's a ROM, can't you just define it as an IP block that gets loaded during configuration? For example, with the Xilinx tools you would have a memory defined that uses a .coe file that contains the ROM values that gets read during compilation; there's no need to "initialize" the ROM in your code. That looks to me like writing to a RAM.
 

There are many possible reasons why you may want to describe the ROM content in HDL, e.g. use the language features to calculate a lookup table as in my previous snippet. Or using module parameters to modify the content, as Cesar0182 apparently wants. But also many possible reasons to generate the table with other tools and import it to the project. It really depends on the application.
 

Maybe just a minor point (depending on speed and utilization), but when it's implemented in the code, you now have to generate all the associated routing to handle writing. A ROM, by definition, does not have a write port, but what you've REALLY got is a RAM that's only written once, but it's still a RAM and it's going to require all the necessary overhead.
 

Maybe just a minor point (depending on speed and utilization), but when it's implemented in the code, you now have to generate all the associated routing to handle writing. A ROM, by definition, does not have a write port, but what you've REALLY got is a RAM that's only written once, but it's still a RAM and it's going to require all the necessary overhead.

I dont quite know what you mean? A ROM in an FPGA is just a BRAM/M9k whatever thats pre-loaded with data with the write-port not connected. This can be infered from HDL as a constant with synchronous access:


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
constant SOME_ROM : slv_array_t := init_rom;
 
....
 
process(clk)
begin
  if rising_edge(clk)
    rom_op <= SOME_ROM(addr);
    -- no write logic in sight
  end if;
end process;

 

I dont quite know what you mean? A ROM in an FPGA is just a BRAM/M9k whatever thats pre-loaded with data with the write-port not connected. This can be infered from HDL as a constant with synchronous access:


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
constant SOME_ROM : slv_array_t := init_rom;
 
....
 
process(clk)
begin
  if rising_edge(clk)
    rom_op <= SOME_ROM(addr);
    -- no write logic in sight
  end if;
end process;


I don't understand what you've got there. What is "rom_op" ? What is addr? Isn't that logic? How do you get data into a RAM without writing it? (To be honest, I don't actually know the mechanism of how "ROM" gets loaded from a bitfile.)

If you have to write to that BRAM, you're going to need some logic, and you're going to need some routing connected to your logic. And it's going to have to meet timing.
 

It's surely possible to design a RAM that is loaded by the FPGA fabric at run time. However the ROM initialisation examples discussed in this thread don't involve write logic. Instead they infer a RAM preloaded from the configuration bitstream.
 

(To be honest, I don't actually know the mechanism of how "ROM" gets loaded from a bitfile.)

For both Xilinx and Altera the bitstreams include all the bit locations of the block RAMs in the devices. Specifically that is how Xilinx updates a bitfile with the software program for an embedded Microblaze design.
 

It's surely possible to design a RAM that is loaded by the FPGA fabric at run time. However the ROM initialisation examples discussed in this thread don't involve write logic. Instead they infer a RAM preloaded from the configuration bitstream.

I don’t see how the example in #9 can load the ROM from the bit file; it uses a clock.
 

I don’t see how the example in #9 can load the ROM from the bit file; it uses a clock.

That is how you would use access the ROM, as both Xilinx and Altera have to have a clock to their block RAMs. That code lacks any code for an init_rom function to initialize the ROM, which is in the example provided by FvM in #5 (though not implemented as a function).
 

I don’t see how the example in #9 can load the ROM from the bit file; it uses a clock.
The code only defines the ROM content. It's translated to a *.hex file by the FPGA synthesis tool and linked to the bit file. Hardware to load the bitfile into the RAM is already present in the FPGA, read the hardware manuals.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top