How to add RAM to a TinyFPGA BX design managed by Atom?


#1

Adding a PLL works, like the initial project.
I can change its frequency through the parameters.
So I presume the PLL core files are somewhere in the TinyFPGA BX related
tools installations or in the provided blink_project files.

Adding a RAM SB_RAM1024x4 doing cut&paste from “Memory Usage Guide
for iCE40 Devices” document, after the necessary connection nets editing,
the build fails with the message:
ERROR: Module \SB_RAM1024x4' referenced in module\top’ in cell `\ram1024x4_inst’ is not
part of the design.

So … how to do?
Then I’ve installed IceCUBE2, built a Verilog module with the above SB_RAM1024x4 instance only
and performed a Synplify Pro Synthesis apparently without errors.
What of the generated files should I copy in the TinyFPGA BX folder?
Or, what is the method to add some RAM primitive in a TinyFPGA BX project using at end Atom
to build & upload?

Thanks a lot
Fabio


#2

I’ve been using the open source tools like yosys with Makefiles instead of the Atom IDE, and my limited experience has been that yosys can infer memory. In the variant of Clifford Wolf’s picosoc at https://github.com/tinyfpga/TinyFPGA-BX/blob/master/examples/picosoc/picosoc.v the memory was inferred from:

module picosoc_mem #(
	parameter integer WORDS = 256
) (
	input clk,
	input [3:0] wen,
	input [21:0] addr,
	input [31:0] wdata,
	output reg [31:0] rdata
);
	reg [31:0] mem [0:WORDS-1];

	always @(posedge clk) begin
		rdata <= mem[addr];
		if (wen[0]) mem[addr][ 7: 0] <= wdata[ 7: 0];
		if (wen[1]) mem[addr][15: 8] <= wdata[15: 8];
		if (wen[2]) mem[addr][23:16] <= wdata[23:16];
		if (wen[3]) mem[addr][31:24] <= wdata[31:24];
	end
endmodule

I have not tried the technology-specific mapping, using SB_SPRAM256KA and the like. Maybe try looking at Clifford Wolf’s repo: https://github.com/cliffordwolf/picorv32 ? Hope this helps.


#3

Thanks kc1.
Atom too can infer such a RAM, but I need to use several sysMEM EBR (dual port) and a lot of FF in the
logic blocks for my circuit so I cannot use teh FFs as RAM.
How to use/force the use of the EBR SB_RAM1024x4?
How to instantiate it?
Why the PLL can be instantiated and the SB_RAM1024x4 does not?


#4

Yosys infers SB_RAM40_4K, from what I see in the .blif file for projects where I’m using RAM. I’m guessing that if you tried to use a specific type of memory like SB_RAM1024x4, there would need to be support in the place & route tool (arachne-pnr or next-pnr). I checked the GitHub repos, and I didn’t find any matches for that specific item. Arachne-pnr has some code that refers SB_RAM40_4K though.


#5

Ehi, replacing SB_RAM1024x4 with SB_RAM40_4K it builds with no errors but now I don’t
know how the port names and ranges I’ve specified for SB_RAM1024x4 can match
for SB_RAM40_4K.
Do you know something about?


#6

… but it gives warnings when I run the simulator and the log window remains visible:

top.v:157: warning: Port 1 (RDATA) of SB_RAM40_4K expects 16 bits, got 3.
top.v:157: : Padding 13 high bits of the port.
top.v:157: warning: Port 5 (RADDR) of SB_RAM40_4K expects 11 bits, got 10.
top.v:157: : Padding 1 high bits of the port.
top.v:157: warning: Port 9 (WADDR) of SB_RAM40_4K expects 11 bits, got 10.
top.v:157: : Padding 1 high bits of the port.
top.v:157: warning: Port 11 (WDATA) of SB_RAM40_4K expects 16 bits, got 4.
top.v:157: : Padding 12 high bits of the port.

So it confirms it is the SB_RAM40_4K 256x16.

How to specify the memory clocks polarity?


#7

Sorry, it is
11-bit addr 16-bit data --> 2K x 16 … not the single EBR block as described in the Lattice manual.

Strange, I’ll do a testbench to simulate one.


#8

This is a simple test circuit with a single memory instance.
It seems to work, the MASK[15:0] input too as specified in the Lattice Memory guide.
I will implement an automatic test routine during the simulation.

`timescale 1ns/1ps
module tb ();
initial begin
$dumpfile(“top_tb.vcd”);
$dumpvars(0, t);
end

reg [2:0] rgb_value;
wire [9:0] x, y;

reg clk;
wire led, usbpu;

initial begin
	clk = 1'b0;
end

always begin
  #31 clk = !clk;
end

initial begin
//  repeat(16000000) @(posedge clk);
    repeat(2060) @(posedge clk);

    $finish;
end

top t (.CLK(clk));

endmodule // tb

`timescale 1ns/1ps
// look in pins.pcf for all the pin names on the TinyFPGA BX board
module top (
input CLK, // 16MHz clock
output LED, // User/boot LED next to power LED
output USBPU, // USB pull-up resistor

output PIN_1

);
wire PLL_CLKOUT;

// drive USB pull-up resistor to '0' to disable USB
assign USBPU = 0;
assign PIN_1 = CLK;

////////
// make a simple blink circuit
////////

// keep track of time and location in blink_pattern
reg [25:0] blink_counter;

// pattern that will be flashed over the LED over time
wire [31:0] blink_pattern = 32'b101010001110111011100010101;

wire [15:0] data;

wire [15:0] dWDATA;

buf #30 b (dRCLK, CLK);
buf #20 b1 (dWCLK, CLK);

SB_RAM40_4K ram_inst (
.RDATA(data[15:0]), // output read data bus [15:0]
.RADDR(blink_counter[10:0]), // read address bus [10:0]
.RCLK(dRCLK), // read clock (pixel clock)
.RCLKE(1’b1), // read clock enale, immagino sempre = 1
.RE(1’b1), // read enable, immagino sempre = 1
.WADDR(blink_counter[10:0]), // write address bus [10:0]
.WCLK(dWCLK), // write clock
.WCLKE(1’b1), // write clock enable
.WDATA(blink_counter[10:0]), // write data bus [15:0]
.WE(1’b1), // write enable
.MASK(16’h2)
);

// =====================================================================================================

initial blink_counter <= 0;

// increment the blink_counter every clock
always @(posedge CLK) begin
    blink_counter <= blink_counter + 1;
end

// light up the LED according to the pattern
assign LED = blink_pattern[blink_counter[25:21]];

endmodule


#9

Glad to hear it is working. Also, I noticed in the Lattice SBTICETechnologyLibrary201708.pdf that you can configure the SB_RAM40_4K to be 1024x4 with some extra defparam statements. Hopefully that would also work with yosys.


#10

Thanks for the hint.
The complete link is

The strange is that SB_RAM40_4K I’ve instatiated without defparam is a 2K x 16 block
and not a 256x16 as stated on Lattice document.
It seems I cannot have 1024x4 but minimum 8192x4.
It seems … at least here works like a 2Kx16 block, as instatiated (bus widths) and in the simulation.
Someone can confirm what I’m experiencing?