Author Topic: How modeling static RAM in Verilog  (Read 3421 times)

0 Members and 1 Guest are viewing this topic.

Offline caiusTopic starter

  • Regular Contributor
  • *
  • Posts: 195
  • Country: it
    • Caius Arcade Repairs & Engineering
How modeling static RAM in Verilog
« on: October 31, 2024, 10:11:49 pm »
Hi all,
it came the time for me to model a static RAM in Verilog.I'm uncertain if using registers or block, the RAM must be static therefore asynchronous.I attach the schematics (one RAM must be 256X8, the other 128X8)
Thanks in advance for any help or advice.

P.S.

The models will run on MAX10 FPGA.
 

Offline woofy

  • Frequent Contributor
  • **
  • Posts: 372
  • Country: gb
    • Woofys Place
Re: How modeling static RAM in Verilog
« Reply #1 on: November 01, 2024, 11:52:44 am »
Hi all,
...  the RAM must be static therefore asynchronous. ...
static rams can be synchronous, and when inferring an fpga's built in ram blocks, usually are.

I've not used the max10, but the ice40 example below should be very similar.

Code: [Select]
module DataRam (din, write_en, waddr, raddr, clk, dout);
parameter addr_width = 10;
parameter data_width = 8;
input [addr_width-1:0] waddr, raddr;
input [data_width-1:0] din;
input write_en, clk;
output reg [data_width-1:0] dout;

reg [data_width-1:0] mem [(1<<addr_width)-1:0];

   initial begin
     $readmemh("dta_data", mem); // dta_data - the initialised 8-bit ram
   end

always @(posedge clk) // Write memory.
begin
if (write_en)
mem[waddr] <= din; // Using write address bus.
end

always @(posedge clk) // Read memory.
begin
dout <= mem[raddr]; // Using read address bus.
end

endmodule


Offline nctnico

  • Super Contributor
  • ***
  • Posts: 28258
  • Country: nl
    • NCT Developments
Re: How modeling static RAM in Verilog
« Reply #2 on: November 01, 2024, 03:10:04 pm »
Generally speaking: if you infer asynchronous RAM, the synthesizer will be forced to use flipflops and/or LUTS. With synchronous RAM, the synthesizer can choose what is most efficient (synchronous block ram or use LUTs / flipflops anyway).
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline caiusTopic starter

  • Regular Contributor
  • *
  • Posts: 195
  • Country: it
    • Caius Arcade Repairs & Engineering
Re: How modeling static RAM in Verilog
« Reply #3 on: November 01, 2024, 06:22:47 pm »
Thanks for answers.I found this module for a 2K X 8Bit RAM, maybe I can adapt it for my needs :

Code: [Select]
module ram
#(
  parameter addr_width=12,
  parameter data_width=8
)
(
  input clk,
  input [addr_width-1:0] addr,
  input [data_width-1:0] din,
  output [data_width-1:0] q,
  input rd_n,
  input wr_n,
  input ce_n
);

reg [data_width-1:0] data;
reg [data_width-1:0] mem[(1<<addr_width)-1:0];

assign q = ~ce_n ? data : 0;

always @(posedge clk) begin

  if (~rd_n) data <= mem[addr];
  if (~wr_n & ~ce_n) mem[addr] <= din;

end


endmodule
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8182
  • Country: ca
    • LinkedIn
Re: How modeling static RAM in Verilog
« Reply #4 on: November 01, 2024, 09:35:36 pm »
You didn't set an optional attribute for your:
Code: [Select]
reg [data_width-1:0] mem[(1<<addr_width)-1:0];

Read here: https://www.intel.com/content/www/us/en/programmable/quartushelp/17.0/hdl/vlog/vlog_file_dir_ram.htm

or a default init file:
Read here: https://www.intel.com/content/www/us/en/programmable/quartushelp/17.0/hdl/vlog/vlog_file_dir_ram_init.htm

or default power-up initialization value like:
Code: [Select]
reg [data_width-1:0] mem[(1<<addr_width)-1:0]  = '{default:'0} ;

or in-line coded assigned init values like here:
https://github.com/BrianHGinc/BHG_I2C_init_RS232_debugger/blob/8a607f0d0aebf0e0bc151308c545c21822d9936b/hdl/BHG_I2C_init_RS232_debugger.sv#L495
 

Offline caiusTopic starter

  • Regular Contributor
  • *
  • Posts: 195
  • Country: it
    • Caius Arcade Repairs & Engineering
Re: How modeling static RAM in Verilog
« Reply #5 on: November 02, 2024, 04:22:32 pm »
You didn't set an optional attribute for your:
Code: [Select]
reg [data_width-1:0] mem[(1<<addr_width)-1:0];

Read here: https://www.intel.com/content/www/us/en/programmable/quartushelp/17.0/hdl/vlog/vlog_file_dir_ram.htm

or a default init file:
Read here: https://www.intel.com/content/www/us/en/programmable/quartushelp/17.0/hdl/vlog/vlog_file_dir_ram_init.htm

or default power-up initialization value like:
Code: [Select]
reg [data_width-1:0] mem[(1<<addr_width)-1:0]  = '{default:'0} ;

or in-line coded assigned init values like here:
https://github.com/BrianHGinc/BHG_I2C_init_RS232_debugger/blob/8a607f0d0aebf0e0bc151308c545c21822d9936b/hdl/BHG_I2C_init_RS232_debugger.sv#L495

Is it important to fill the RAM with an initial contents?
I found this other model :

Code: [Select]
module SRAM_sync #(parameter DATA_WIDTH = 8, ADDR_WIDTH = 8)(
    input wire clk,
    input wire [ADDR_WIDTH-1:0] ADDR,
    input wire [DATA_WIDTH-1:0] DATA,
    (* direct_enable = 1 *) input wire CEn,
    input wire OEn,
    input wire WEn,
    output reg [DATA_WIDTH-1:0] Q
    );

    reg [DATA_WIDTH-1:0] mem[0:(2**ADDR_WIDTH)-1];
    reg [DATA_WIDTH-1:0] data_out;
   
    always @(posedge clk) begin
        if(!CEn) begin
            if(!OEn) begin
                Q <=  mem[ADDR];
            end
        end
        if(!CEn) begin
            if(!WEn) begin
                mem[ADDR] <= DATA;
            end
        end
    end

endmodule

« Last Edit: November 02, 2024, 07:12:44 pm by caius »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8182
  • Country: ca
    • LinkedIn
Re: How modeling static RAM in Verilog
« Reply #6 on: November 02, 2024, 06:38:20 pm »
Is it important to fill the RAM with an initial contents?
I found this other model :
Reasons for filling the ram or at least adding the = '{default:'0}...

When simulating your design, without anything, or even at least the ='{default:'0}, until you write to any memory address, all reads to non written addresses will return an 'X' or undefined instead of a 0.

Unlike when you simulate your design, by default, un-assigned memory in an FPGA will power-up default to all 0.

Note that filling your memory with initial power-up data usually will not consume any additional resources in your FPGA unless the memory is stored in logic cells and you are trying to do something unusually special.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8182
  • Country: ca
    • LinkedIn
Re: How modeling static RAM in Verilog
« Reply #7 on: November 02, 2024, 06:46:01 pm »
See my /*************************** for changing your memory into a proper tri-state output enable.

Thanks for answers.I found this module for a 2K X 8Bit RAM, maybe I can adapt it for my needs :

Code: [Select]
module ram
#(
  parameter addr_width=12,
  parameter data_width=8
)
(
  input clk,
  input [addr_width-1:0] addr,
  input [data_width-1:0] din,
                         inout [data_width-1:0] q,    /*********************************************
  input rd_n,
  input wr_n,
  input ce_n
);

reg [data_width-1:0] data;
reg [data_width-1:0] mem[(1<<addr_width)-1:0];

                       assign q = ~ce_n ? data : {data_width{1'bz}};     /****************************************

always @(posedge clk) begin

  if (~rd_n) data <= mem[addr];
  if (~wr_n & ~ce_n) mem[addr] <= din;

end


endmodule
 
The following users thanked this post: caius

Offline caiusTopic starter

  • Regular Contributor
  • *
  • Posts: 195
  • Country: it
    • Caius Arcade Repairs & Engineering
Re: How modeling static RAM in Verilog
« Reply #8 on: November 02, 2024, 10:03:59 pm »
See my /*************************** for changing your memory into a proper tri-state output enable.

Thanks for answers.I found this module for a 2K X 8Bit RAM, maybe I can adapt it for my needs :

Code: [Select]
module ram
#(
  parameter addr_width=12,
  parameter data_width=8
)
(
  input clk,
  input [addr_width-1:0] addr,
  input [data_width-1:0] din,
                         inout [data_width-1:0] q,    /*********************************************
  input rd_n,
  input wr_n,
  input ce_n
);

reg [data_width-1:0] data;
reg [data_width-1:0] mem[(1<<addr_width)-1:0];

                       assign q = ~ce_n ? data : {data_width{1'bz}};     /****************************************

always @(posedge clk) begin

  if (~rd_n) data <= mem[addr];
  if (~wr_n & ~ce_n) mem[addr] <= din;

end


endmodule

Thanks.
Since I'm using Quartus schematics I'm having some troubles in wiring the busses.How can I change the RAM code in order to split the bus into singe address and data pins?
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8182
  • Country: ca
    • LinkedIn
Re: How modeling static RAM in Verilog
« Reply #9 on: November 02, 2024, 10:53:46 pm »
See my /*************************** for changing your memory into a proper tri-state output enable.

Thanks for answers.I found this module for a 2K X 8Bit RAM, maybe I can adapt it for my needs :

Code: [Select]
module ram
#(
  parameter addr_width=12,
  parameter data_width=8
)
(
  input clk,
  input [addr_width-1:0] addr,
  input [data_width-1:0] din,
                         inout [data_width-1:0] q,    /*********************************************
  input rd_n,
  input wr_n,
  input ce_n
);

reg [data_width-1:0] data;
reg [data_width-1:0] mem[(1<<addr_width)-1:0];

                       assign q = ~ce_n ? data : {data_width{1'bz}};     /****************************************

always @(posedge clk) begin

  if (~rd_n) data <= mem[addr];
  if (~wr_n & ~ce_n) mem[addr] <= din;

end


endmodule

Thanks.
Since I'm using Quartus schematics I'm having some troubles in wiring the busses.How can I change the RAM code in order to split the bus into singe address and data pins?
Please show me what you mean.
You already have a separate data and address bus.
Are you using the block schematics?

(It is good practice to learn how to do everything in HDL, however I understand if you are trying to make a cheap fast 2-3 component/module design to emulate a TTL schematic.)

Also, it is goo practice on how to use a simulator.
 

Offline caiusTopic starter

  • Regular Contributor
  • *
  • Posts: 195
  • Country: it
    • Caius Arcade Repairs & Engineering
Re: How modeling static RAM in Verilog
« Reply #10 on: November 02, 2024, 11:48:58 pm »

Please show me what you mean.
You already have a separate data and address bus.
Are you using the block schematics?

(It is good practice to learn how to do everything in HDL, however I understand if you are trying to make a cheap fast 2-3 component/module design to emulate a TTL schematic.)

Also, it is good practice on how to use a simulator.

Yes, I'm using block schematics in Quartus trying to emulate a TTL schematics.
I would like to have the RAM symbol with individual pins (for example, address bus as A0, A1, A2, A3, A4 etc.Same for DATA input and output).Just like the attached symbol.

P.S.
Dumb question : I know data pins are bidirectional but why to have in Verilog RAM module a separate bus for data input and data output?It would possible to declare them as 'inout' and have only a set of pins like attached symbol?
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8182
  • Country: ca
    • LinkedIn
Re: How modeling static RAM in Verilog
« Reply #11 on: November 03, 2024, 12:02:23 am »

Please show me what you mean.
You already have a separate data and address bus.
Are you using the block schematics?

(It is good practice to learn how to do everything in HDL, however I understand if you are trying to make a cheap fast 2-3 component/module design to emulate a TTL schematic.)

Also, it is good practice on how to use a simulator.

Yes, I'm using block schematics in Quartus trying to emulate a TTL schematics.
I would like to have the RAM symbol with individual pins (for example, address bus as A0, A1, A2, A3, A4 etc.Same for DATA input and output).Just like the attached symbol.

P.S.
Dumb question : I know data pins are bidirectional but why to have in Verilog RAM module a separate bus for data input and data output?It would possible to declare them as 'inout' and have only a set of pins like attached symbol?

In quartus schematic, you just wire the address or data bus as ' data[7..0] ', then you can use wires where ever you like data[7], data[6], ect.

Yes, if I remember correctly as it has been like 15 years, quartus in the block diagrams use the double period instead of the colon.

The hard way would be to draw your own sub-schematic of the ram chip, wiring individual input pins and output pins to the .v code, then generate a block diagram symbol from that schematic perfectly matching your picture.

As for the separate in and out for the data, it is the way it operates in the FPGA and runs much faster (like 3x) than using a single tri-state IO bus for the data.  You can also now write data while simultaneously reading data with a separate data in and data out.

Yes, you can modify your .v code to use 1 tristate data bus for reading and writing if you want to perfectly simulate a static ram chip.
 

Offline caiusTopic starter

  • Regular Contributor
  • *
  • Posts: 195
  • Country: it
    • Caius Arcade Repairs & Engineering
Re: How modeling static RAM in Verilog
« Reply #12 on: November 04, 2024, 11:43:23 pm »
Thanks for reply.
I'm using this RAM model for a 128x8-bit :

 
Code: [Select]
module ram128
    #(
      parameter addr_width=7,
      parameter data_width=8
    )
    (
      input clk,
      input [addr_width-1:0] addr,
      input [data_width-1:0] din,
                             inout [data_width-1:0] q,     
      input rd_n,
      input wr_n,
      input ce_n
    );

    reg [data_width-1:0] data;
    reg [data_width-1:0] mem[(1<<addr_width)-1:0];

                           assign q = ~ce_n ? data : {data_width{1'bz}};   

    always @(posedge clk) begin

      if (~rd_n) data <= mem[addr];
      if (~wr_n & ~ce_n) mem[addr] <= din;

    end

And this for a 256x8-bit :

 
Code: [Select]
module ram_
    #(
      parameter addr_width=8,
      parameter data_width=8
    )
    (
      input clk,
      input [addr_width-1:0] addr,
      input [data_width-1:0] din,
                             inout [data_width-1:0] q,     
      input rd_n,
      input wr_n,
      input ce_n
    );

    reg [data_width-1:0] data;
    reg [data_width-1:0] mem[(1<<addr_width)-1:0];

                           assign q = ~ce_n ? data : {data_width{1'bz}};   

    always @(posedge clk) begin

      if (~rd_n) data <= mem[addr];
      if (~wr_n & ~ce_n) mem[addr] <= din;

    end


    endmodule


I implemented these modules in the whole block schematics under Quartus (translated from TTL schematics).When I try to do a compile I get the errors in the attached log.
I attach also a the snippet of TTL schematics that I'm trying to simulate in Quartus.Thanks in advance for any help or suggestion.
« Last Edit: November 05, 2024, 12:01:54 am by caius »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8182
  • Country: ca
    • LinkedIn
Re: How modeling static RAM in Verilog
« Reply #13 on: November 05, 2024, 12:54:14 am »
Show us your quartus schematic with wiring to the IO pins.
 

Offline caiusTopic starter

  • Regular Contributor
  • *
  • Posts: 195
  • Country: it
    • Caius Arcade Repairs & Engineering
Re: How modeling static RAM in Verilog
« Reply #14 on: November 05, 2024, 09:31:25 am »
Show us your quartus schematic with wiring to the IO pins.

Here attached the Quartus block schematics with MAX10 IO assignement (sorry it's a big messy one ) and original TTL schematics.
 

Online xvr

  • Frequent Contributor
  • **
  • Posts: 494
  • Country: ie
    • LinkedIn
Re: How modeling static RAM in Verilog
« Reply #15 on: November 05, 2024, 07:06:27 pm »
FPGA do not have tristate buffers internally. Quartus try to convert your RAM data bus from tristate to switches, but unsuccessfully. Did you really need tristate/bidirectional data bus on RAM module?

 
The following users thanked this post: Someone

Offline caiusTopic starter

  • Regular Contributor
  • *
  • Posts: 195
  • Country: it
    • Caius Arcade Repairs & Engineering
Re: How modeling static RAM in Verilog
« Reply #16 on: November 05, 2024, 09:17:22 pm »
FPGA do not have tristate buffers internally. Quartus try to convert your RAM data bus from tristate to switches, but unsuccessfully. Did you really need tristate/bidirectional data bus on RAM module?

I think I need bidirectional data bus on RAM modules since original design have it.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8182
  • Country: ca
    • LinkedIn
Re: How modeling static RAM in Verilog
« Reply #17 on: November 06, 2024, 02:13:36 am »
Quote
Error (13076): The node "74283:GRACIE|f74283:sub|76" has multiple drivers due to the conflicting nodes "ram_:RAMTL|q[0..7]" and "ram_:RAMBL|q[0..7]"


Take a look at your schematic.
Both ram chips read enables are wired together.

Ok, like said above, you cannot do tristate busses inside the FPGA.

Change your ram code from:

Code: [Select]
                             inout [data_width-1:0] q,     
...
                           assign q = ~ce_n ? data : {data_width{1'bz}};

to:

Code: [Select]
                             output [data_width-1:0] q,     
...
                           assign q = ~ce_n ? data : {data_width{1'b0}};

and use an 'OR' gate on the output busses to merge the 'Q' outputs to a single output.


Also, the schematic might not work right unless you design clock-less static memory modules instead of synchronous clocked memory modules.  That is unless you mode the clocked address and data buffers from the TTL components to inside your verilog ram modules.  The other choice is to use the PLL to 2x the speed of your source clock and run the ram at 2x clock frequency.

(Also, next time you try a project like this, maybe use multiple sub schematic pages like your source TTL schematic, and have a 'top' hierarchy schematic wiring those sup pages together and also wire to the selected FPGA IO pins.)
« Last Edit: November 06, 2024, 02:21:07 am by BrianHG »
 
The following users thanked this post: caius

Offline caiusTopic starter

  • Regular Contributor
  • *
  • Posts: 195
  • Country: it
    • Caius Arcade Repairs & Engineering
Re: How modeling static RAM in Verilog
« Reply #18 on: November 06, 2024, 10:32:37 am »
Thanks for reply.
I changed the RAM code as suggested and put an OR gate as attached screenshot but I get errors on Quartus compiling (log attached)
I forgot to say that I have a Verilog code (not made by me) of the original TTL schematics but it has still issue after I fixed some with the use of a PLL (thanks again BrianHG for the precious help!).
I covered this in another thread here :

https://www.eevblog.com/forum/fpga/help-on-translate-schematics-to-verilog/

I attach again the Verilog code, I think the issue is related to the simulated RAMs (the author used registers instead of blocks, maybe they are asynchronous and must synchronous instead)
« Last Edit: November 06, 2024, 11:19:03 am by caius »
 

Online xvr

  • Frequent Contributor
  • **
  • Posts: 494
  • Country: ie
    • LinkedIn
Re: How modeling static RAM in Verilog
« Reply #19 on: November 06, 2024, 11:05:50 am »
This Verilog code will not work. Direct implementation of discret logic into FPGA also will not work (almost everytime). That kind of design violate synchronous design principles. All synchronization signals generated inside FPGA logic will be very prone to glitches. In discrete logic design these glitches will be suppressed by limited speed of logic and by wire capacitance. This is not the case for FPGA - here all glitchess will affect triggers.
 

Offline caiusTopic starter

  • Regular Contributor
  • *
  • Posts: 195
  • Country: it
    • Caius Arcade Repairs & Engineering
Re: How modeling static RAM in Verilog
« Reply #20 on: November 06, 2024, 11:37:06 am »
This Verilog code will not work. Direct implementation of discret logic into FPGA also will not work (almost everytime). That kind of design violate synchronous design principles. All synchronization signals generated inside FPGA logic will be very prone to glitches. In discrete logic design these glitches will be suppressed by limited speed of logic and by wire capacitance. This is not the case for FPGA - here all glitchess will affect triggers.

Well, with some tweaking (implementing a PLL and a 4.7K resistor in series to main clock) I got the design mostly working.I remind you all the original TTL schematics are from a custom IC used on some arcade PCBs from '80, I desgined a replacement of this custom IC based on a MAX10 FPGA running the above Verilog code.I said 'mostly' because there are still issue on a specific arcade board, some garbage graphics on screen that I 'm unable to get rid of.For this reason I thought to translate the original TTL schematics to Quartus block schematics to see if this may lead to some improvement.
 

Online xvr

  • Frequent Contributor
  • **
  • Posts: 494
  • Country: ie
    • LinkedIn
Re: How modeling static RAM in Verilog
« Reply #21 on: November 06, 2024, 11:45:46 am »
'Garbage graphics ' is a result of asynchronous design. It can't be removed by some block changing. The only one way to get rid of them is to reimplement original schematic in synchronous manner
 

Offline caiusTopic starter

  • Regular Contributor
  • *
  • Posts: 195
  • Country: it
    • Caius Arcade Repairs & Engineering
Re: How modeling static RAM in Verilog
« Reply #22 on: November 06, 2024, 11:53:58 am »


(Also, next time you try a project like this, maybe use multiple sub schematic pages like your source TTL schematic, and have a 'top' hierarchy schematic wiring those sup pages together and also wire to the selected FPGA IO pins.)

Yes, I tried to split the whole schematics into sub pages but, after researching, it seems it's not possible under Quartus.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8182
  • Country: ca
    • LinkedIn
Re: How modeling static RAM in Verilog
« Reply #23 on: November 06, 2024, 06:36:37 pm »


(Also, next time you try a project like this, maybe use multiple sub schematic pages like your source TTL schematic, and have a 'top' hierarchy schematic wiring those sup pages together and also wire to the selected FPGA IO pins.)

Yes, I tried to split the whole schematics into sub pages but, after researching, it seems it's not possible under Quartus.
LOL, did you even try any of the tutorials?
Did you even try to Youtube search Quartus schematic entry tutorials?
 

Offline caiusTopic starter

  • Regular Contributor
  • *
  • Posts: 195
  • Country: it
    • Caius Arcade Repairs & Engineering
Re: How modeling static RAM in Verilog
« Reply #24 on: November 06, 2024, 07:10:07 pm »

LOL, did you even try any of the tutorials?
Did you even try to Youtube search Quartus schematic entry tutorials?


I read some posts on Intel forums and found no answers.
OK, I'm a dumb  ;D
Regarding this project, I will put it aside , I'm not able to debug it (plus, I have no oscilloscope at the moment for doing comparison between original signals and FPGA ones).Thanks you, guys, for the help, anyway!
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf