Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spurious write to BRAM after configuration on iCE40 #101

Closed
zeldin opened this issue Nov 14, 2015 · 7 comments
Closed

Spurious write to BRAM after configuration on iCE40 #101

zeldin opened this issue Nov 14, 2015 · 7 comments

Comments

@zeldin
Copy link
Contributor

zeldin commented Nov 14, 2015

The following code

module bram(
        input clk,
        output LED0,
        output LED1,
        output LED2,
        output LED3,
        output LED4,
        output LED5,
        output LED6,
        output LED7
        );

   wire        ramclk;
   assign ramclk = clk;

   reg [3:0]       cnt;
   reg [7:0]       leds;

   reg [7:0]       ram[511:0];

   assign {LED7, LED6, LED5, LED4, LED3, LED2, LED1, LED0} = leds;

   initial begin
      ram[0] <= 8'hAA;
   end

   always @(posedge clk) begin
      cnt <= cnt + 1;
   end

   always @(posedge ramclk) begin
      case (cnt)
    4: ram[7] <= 8'h55;
    6: leds <= ram[0];
      endcase
   end


endmodule // bram

should always (after 6 cycles at least :) read out the value 10101010
to the LEDs, since ram[0] is never modified by the code. However,
sometimes (about half the time) all zeros are read out instead. It appears
that a spurious write of data 0 to address 0 is sometimes happening
between configuration and the execution of the state machine. (I have
confirmed in more complicated verilog that address 0 and only address 0
gets modified this way.)

If I remove the assignment to ram[7], then the problem goes away.

Is it a hardware bug in iCE40 that you can't both have init data in
BRAMs and use the write function, or is yosys (or arachne-pnr) doing
something wrong here?

Yosys 0.5+389 (git sha1 faa3da5, gcc 4.8.5 -mcpu=power4 -mtune=power4 -maltivec -mabi=altivec -fno-strict-aliasing -O2 -fPIC -Os)

@zeldin
Copy link
Contributor Author

zeldin commented Nov 14, 2015

Attached generated files
bram.blif.txt
bram.txt

@Obijuan
Copy link

Obijuan commented Nov 23, 2015

I have already noticed a similar problem, but I wasn't able to determine the cause. It was a kind of random bug. I will make more tests using the information you have provided

@cseed
Copy link
Contributor

cseed commented Nov 23, 2015

I wonder if @laanwj's pull request fixes this. It cleared up a heisen-bug @cliffordwolf was running into. I'm at a work conference until Wed. I won't be able to look at any of this before then.

@Obijuan
Copy link

Obijuan commented Nov 24, 2015

I can confirm that this bug is still in Yosys 0.5+397
I am implementing a very simple educational microprocessor in verilog. I was having a lot of problems: the same program sometimes worked ok, but sometines not. It was a kind of random. Now I am avoiding the 0 address (assuming it is always 0) and everything seems to work fine

@zeldin
Copy link
Contributor Author

zeldin commented Nov 24, 2015

That's basically my case as well. I'm using the AVR core from opencores, and have added a module to upload code to the program memory (which is BRAM) runtime over a serial port. When using the upload function the code always works, but if putting the same code into initdata, the first instruction frequently becomes a NOP (I can use the upload function to also download the current PM contents in order to verify this, which is the "more complicated verilog" I was talking about earlier).

@Obijuan
Copy link

Obijuan commented Nov 24, 2015

Wow! That project is so cool!!! :-)

@cliffordwolf
Copy link
Collaborator

Looking into lattice synthesis results (1), I realized that the lattice tools use the RCLKE/WCLKE ports instead of RE/WE ports when inferring block memory. Theoretically this should not make a difference, but it seems to make a difference in this case.

When I instantiate the block-ram manually and use the RE/WE ports, then I can even reproduce the problem with the lattice tools. So this does not seem to be a place&route bug in our flow, but a general problem with iCE40 BRAMS when using the RE/WE ports.

I have now changed the bram mapper code for ice40 to use the RCLKE/WCLKE ports instead instead of RE/WE: 8ff229a This seems to fix the issue.

Btw: I have a large-ish SoC design with a similar setup (booting from BRAM that is writeable), but I never observed this bug in that design.. Interesting.

(1) You can't use your design for that: The Lattice tool completely ignore the initial section in your code and simply set all outputs to zero, no logic or memory is inferred.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants