RAM

To make it easier to configure RISC5 processors with different memory capacities, a parameterised RAM module was developed. It takes one parameter, Mem16384blocks, denominating the number of 16k x 32 blocks to allocate. The syntesising algorithm allocates first as many as possible 32k blocks, then adds one 16k block if needed.

module RAMG #(parameter Mem16384blocks = 3) (  
  input clki, clkb, // internal clock and bus clock = clki/2
  input wr, be,
  input [$clog2(Mem16384blocks*65536)-1:0] adr,
  input [31:0] wdata, 
  output reg [31:0] rdata
);

  localparam Num16k = Mem16384blocks % 2;
  localparam Num32k = Mem16384blocks / 2;

  /* ... */

  genvar j;
  generate
    for (j = 0; j < Num32k; j = j + 1) begin: b32k
      RAMG_base32 #(.cells(32768)) r32 (.clk(clki), .we(we[j]), .a(adr[16:2]), .di(wdata), .do(rdd[j]));
    end
    if (Num16k == 1) begin: b16k
      RAMG_base32 #(.cells(16384)) r16 (.clk(clki), .we(we[Num32k]), .a(adr[15:2]), .di(wdata), .do(rdd[Num32k]);
    end
  endgenerate
endmodule

In the top file, the RAM is instantiated thusly, to instantiate 512k of RAM (8 * 16k * 4 bytes):

localparam Mem16384blocks = 8;
localparam AdrBusWidth = $clog2(Mem16384blocks*'h10000);
RAMG #(.Mem16384blocks(Mem16384blocks)) ram (.clki(clk2x), .clkb(clkcpu), .wr(wr), .be(ben),
  .adr(adr[AdrBusWidth-1:0]), .wdata(outbus), .rdata(inbus0));

The PROM instantiation needs to be adjusted to select the boot loader with the correct memory configuration.