Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronic 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.

Register Log in

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

Cesar0182

Member level 4
Joined
Feb 18, 2019
Messages
73
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
728
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.
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
46,973
Helped
13,933
Reputation
28,114
Reaction score
12,573
Trophy points
1,393
Location
Bochum, Germany
Activity points
273,900
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?
 

Cesar0182

Member level 4
Joined
Feb 18, 2019
Messages
73
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
728
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.
 

TrickyDicky

Advanced Member level 5
Joined
Jun 7, 2010
Messages
7,001
Helped
2,056
Reputation
4,129
Reaction score
2,006
Trophy points
1,393
Activity points
38,425
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;

 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
46,973
Helped
13,933
Reputation
28,114
Reaction score
12,573
Trophy points
1,393
Location
Bochum, Germany
Activity points
273,900
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.
 

barry

Advanced Member level 5
Joined
Mar 31, 2005
Messages
4,858
Helped
1,068
Reputation
2,146
Reaction score
1,053
Trophy points
1,393
Location
California, USA
Activity points
26,510
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.
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
46,973
Helped
13,933
Reputation
28,114
Reaction score
12,573
Trophy points
1,393
Location
Bochum, Germany
Activity points
273,900
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.
 

barry

Advanced Member level 5
Joined
Mar 31, 2005
Messages
4,858
Helped
1,068
Reputation
2,146
Reaction score
1,053
Trophy points
1,393
Location
California, USA
Activity points
26,510
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.
 

TrickyDicky

Advanced Member level 5
Joined
Jun 7, 2010
Messages
7,001
Helped
2,056
Reputation
4,129
Reaction score
2,006
Trophy points
1,393
Activity points
38,425
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;

 

barry

Advanced Member level 5
Joined
Mar 31, 2005
Messages
4,858
Helped
1,068
Reputation
2,146
Reaction score
1,053
Trophy points
1,393
Location
California, USA
Activity points
26,510
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.
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
46,973
Helped
13,933
Reputation
28,114
Reaction score
12,573
Trophy points
1,393
Location
Bochum, Germany
Activity points
273,900
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.
 

ads-ee

Super Moderator
Staff member
Joined
Sep 10, 2013
Messages
7,562
Helped
1,768
Reputation
3,542
Reaction score
1,710
Trophy points
113
Location
USA
Activity points
55,755
(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.
 

barry

Advanced Member level 5
Joined
Mar 31, 2005
Messages
4,858
Helped
1,068
Reputation
2,146
Reaction score
1,053
Trophy points
1,393
Location
California, USA
Activity points
26,510
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.
 

ads-ee

Super Moderator
Staff member
Joined
Sep 10, 2013
Messages
7,562
Helped
1,768
Reputation
3,542
Reaction score
1,710
Trophy points
113
Location
USA
Activity points
55,755
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).
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
46,973
Helped
13,933
Reputation
28,114
Reaction score
12,573
Trophy points
1,393
Location
Bochum, Germany
Activity points
273,900
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.
 

Toggle Sidebar

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top