Simulating BRAM with lattice/aldec tools - Page 1
Forum section: electronics / general

author: Dmeads
author_rank: Regular Contributor
timestamp: January 21, 2020, 09:40:42 pm
content: Hi all,I am working with 4kb (256 deep x 16 wide) BRAMs in lattice FPGAs.I used the instantiation provided by the memroy usage guide, and then created a wrapper around it.https://www.latticesemi.com/-/media/LatticeSemi/Documents/ApplicationNotes/MO/MemoryUsageGuideforiCE40Devices.ashx?document_id=47775The synthesis tools in lattice icecube2 says the BRAM is synthesized correctly, and there are no errors.I followed the timing diagram religiously (page 4 of memory usage guide). I have included my testbench and my verilog code.The problem is my simulation is wrong. reading from the BRAM always produces 0x0000, no matter what i write to that same address.The simulator is ALDEC lattice edition.Is there a separate step I am missing so the simulator knows I am trying to simulate a specific lattice BRAM?device is lattice ice40HX1K.code below:Code:`timescale 1ns / 1psmodule BRAM_256x16(input [15:0] WDATA_c,input [15:0] MASK_c,input [7:0] WADDR_c,input WE_c,input WCLKE_c,input WCLK_c,output [15:0] RDATA_c,input [7:0] RADDR_c,input RE_c,input RCLKE_c,input RCLK_c);SB_RAM256x16 ram256x16_inst (.RDATA(RDATA_c[15:0]),.RADDR(RADDR_c[7:0]),.RCLK(RCLK_c),.RCLKE(RCLKE_c),.RE(RE_c),.WADDR(WADDR_c[7:0]),.WCLK(WCLK_c),.WCLKE(WCLKE_c),.WDATA(WDATA_c[15:0]),.WE(WE_c),.MASK(MASK_c[15:0]));defparam ram256x16_inst.INIT_0 =256'h0000000000000000000000000000000000000000000000000000000000000000;defparam ram256x16_inst.INIT_1 =256'h0000000000000000000000000000000000000000000000000000000000000000;defparam ram256x16_inst.INIT_2 =256'h0000000000000000000000000000000000000000000000000000000000000000;defparam ram256x16_inst.INIT_3 =256'h0000000000000000000000000000000000000000000000000000000000000000;defparam ram256x16_inst.INIT_4 =256'h0000000000000000000000000000000000000000000000000000000000000000;defparam ram256x16_inst.INIT_5 =256'h0000000000000000000000000000000000000000000000000000000000000000;defparam ram256x16_inst.INIT_6 =256'h0000000000000000000000000000000000000000000000000000000000000000;defparam ram256x16_inst.INIT_7 =256'h0000000000000000000000000000000000000000000000000000000000000000;defparam ram256x16_inst.INIT_8 =256'h0000000000000000000000000000000000000000000000000000000000000000;defparam ram256x16_inst.INIT_9 =256'h0000000000000000000000000000000000000000000000000000000000000000;defparam ram256x16_inst.INIT_A =256'h0000000000000000000000000000000000000000000000000000000000000000;defparam ram256x16_inst.INIT_B =256'h0000000000000000000000000000000000000000000000000000000000000000;defparam ram256x16_inst.INIT_C =256'h0000000000000000000000000000000000000000000000000000000000000000;defparam ram256x16_inst.INIT_D =256'h0000000000000000000000000000000000000000000000000000000000000000;defparam ram256x16_inst.INIT_E =256'h0000000000000000000000000000000000000000000000000000000000000000;defparam ram256x16_inst.INIT_F =256'h0000000000000000000000000000000000000000000000000000000000000000;endmoduletestbench:Code:`timescale 1ns / 1psmodule tb;reg [15:0] WDATA_c;reg [15:0] MASK_c;reg [7:0] WADDR_c;reg WE_c;reg WCLKE_c;reg WCLK_c;wire [15:0] RDATA_c;reg [7:0] RADDR_c;reg RE_c;reg RCLKE_c;reg RCLK_c;BRAM_256x16 uut(WDATA_c,MASK_c,WADDR_c,WE_c,WCLKE_c,WCLK_c,RDATA_c,RADDR_c,RE_c,RCLKE_c,RCLK_c);always #500 WCLK_c = ~WCLK_c;always #500 RCLK_c = ~RCLK_c;initialbeginWCLK_c = 1;RCLK_c = 0;RE_c = 0;RCLKE_c = 0;WE_c = 0;WCLKE_c = 0;#750WE_c = 1;WCLKE_c = 1;WADDR_c = 8'h0F;WDATA_c = 16'h00FF;#1000WADDR_c = 8'h2A;WDATA_c = 16'hAAAA;#500WE_c = 0;WCLKE_c = 0;#1000RE_c = 1;RCLKE_c = 1;RADDR_c = 8'h0F;#1000RADDR_c = 8'h2A;#500RE_c = 0;RCLKE_c = 0;#2000$finish;endendmodulepicture of simulation attatched.any help would be appreciated.Thanks.

author: Dmeads
author_rank: Regular Contributor
timestamp: January 21, 2020, 09:42:07 pm
content: RDATA _c is the output I am concerned about, this outputs the data at the specified read address RADDR

author: BrianHG
author_rank: Super Contributor
timestamp: January 21, 2020, 09:53:12 pm
content: Your write data mask is undefined. I don't know about Lattice, but in Intel's Quartus, you need to set the 'write data mask enable' as it is used to set writing smaller bytes or individual bits, such as used in graphics pixel writes, or byte writes, when you have a memory which is wider in bits, like 32 bit or 64 bit, than a single byte. This is important unless every-time your processor want to write a single byte, it will need to read a 64 bit word, modify the 1 byte contents, then write the new modified 64 bit word. This would slow thing down considerably.My 8 bit GPU in the other thread by nockieboy has 16bit FPGA memory and does use the enable mask set to 2 banks of 8 bit wide so that the Z80 interface can write single bytes without worrying about erasing the opposite 8 bits in each 16 bit word of ram.Holding the write mask low would mean no write into those bits. Holding all the mask bits low would mean no write takes place at all even though a write_enable was sent.

author: Dmeads
author_rank: Regular Contributor
timestamp: January 21, 2020, 10:46:23 pm
content: ah interesting and good point. Thanks. Will see if it works and get back to you

author: Dmeads
author_rank: Regular Contributor
timestamp: January 22, 2020, 01:00:31 am
content: Yep the mask fixed it. Thanks so much!!