jamesbowman / swapforth

Swapforth is a cross-platform ANS Forth
BSD 3-Clause "New" or "Revised" License
275 stars 56 forks source link

How do I interface this fifo #46

Closed bmentink closed 6 years ago

bmentink commented 7 years ago

Hi Guys,

I am trying to interface a fifo, the instantiation is this:

fifo ff( .clk(clk), .rst(~reset), .buf_in(buf_in), .buf_out(buf_out), 
         .wr_en(wr_en), .rd_en(rd_en), .buf_empty(buf_empty), 
         .buf_full(buf_full), .fifo_counter(fifo_counter) );

I am trying to load buf_in on the Verilog side, and unload buf_out on the Forth side.

On the Verilog side at the top level I am doing:

always @(posedge clk) begin
    wr_en <= 1'b0;
    if (!buf_full & drum_output[1]) begin
      buf_in <= drum_output[1];
      wr_en <= 1'b1;
    end
  end

And to read the fifo on the Forth side added:

wire rd_en = io_rd_ & io_addr_[9];

and

assign io_din =
    """""""
    (io_addr_[ 9] ? {buf_out}                                      : 16'd0) |
   """""
    (io_addr_[12] ? {8'd0, uart0_data}                                  : 16'd0) |
    (io_addr_[13] ? {11'd0, random, 1'b0, PIOS_01, uart0_valid, !uart0_busy} : 16'd0);

So that fifo can be read on address $200, but I get no output on the Forth side, any clues?

bmentink commented 7 years ago

An update: It seems the data is not going into the FIFO as buf_empty is always true. Can anyone see what I am doing wrong when writing to the buffer ..

Thanks

RGD2 commented 7 years ago

I can't see anything obviously wrong with what you've shown.

Here are some possible leads to check out:

Does the bit that is to trigger the write actually ever go true? Is the fifo module trustworthy? Has it been otherwise tested? (Not just simulated - although it should already have passed a test bench. iverilog (Icarus verilog) is good for simulating little designs like that. Verilator could be used too, but it's way overkill for just a test bench. You can get away without simulating a testbench for the fifo if you're able to test each part by isolation and substitution. Counters are good easy synthetic data sources for fifo's, and you can replace the FIFO itself with just a couple of registers (google: clock domain crossing ) to test everything around the fifo. )

Is a clock domain being crossed? (Does the fifo have both a read and a write clock in its interface definition? Are the signals feeding in coming from logic running on a different clock?)

-- Remy

On Thursday, 10 November 2016, bmentink notifications@github.com wrote:

An update: It seems the data is not going into the FIFO as _bufempty is always true. Can anyone see what I am doing wrong when writing to the buffer ..

Thanks

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/jamesbowman/swapforth/issues/46#issuecomment-259606988, or mute the thread https://github.com/notifications/unsubscribe-auth/AO8-GJ-LFeqW7fAoCBDtL1ySyD7X2fcDks5q8rBBgaJpZM4KsDK0 .

-- Remy

bmentink commented 7 years ago

Hi Remy,

Thanks for the suggestions. I have already had it pass simulation. It came with test-bench code which worked fine in Icarus .... I usually use EDA Playground to simulate & test my modules.

See here--> https://www.edaplayground.com/x/4M9d

I tried feeding in the data on every clock tick (just as a test to remove the test for the data available flag) it still does nothing ..

The FIFO only has a single clock source used for read & write as per the interface .. I don't think any clock domain has been crossed, the same clock is used throughout ..

I just don't know why the data is not going into the FIFO ... the data_empty flag stays set, and no data is read .... and reading other data instead of buf_out is ok ..

bmentink commented 7 years ago

@RGD2

Hi Remy, I have found my issues, and of course of my own making.

There was several mistakes:

  1. I had to define my interface to the FIFO as "reg" I had them as "wire"
  2. The test of the drum_output[] would not work, I guess because it is a wire, so not registered.
  3. The wr_en had to be toggled every alternate clock cycle, I had tried to toggle on only one edge. So the working code was:

    always @(posedge clk) begin
     buf_in <= drum_output[1];
     wr_en <= ~wr_en;
    end

    This will of course be modified to loop around all my outputs and feed them to the FIFO.

The key to resolving this, was your suggestions of testing the code around the FIFO, which I did by removing the FIFO and replacing with a simple assign of buf_out to buf_in, when I got that working, my FIFO just worked ..

The whole chain of: ADC->RCFilter->FIFO->Forth .. now works

Thanks for the help.

RGD2 commented 7 years ago

You're welcome. Most of my problems are usually my own mistakes also. Isolate and test with exclusions is one of the more powerful fault finding techniques, because it usually doesn't care about complexity of the system, it just is chopping a system up until you're certain about where the fault really is.

It can backfire sometimes though.

Be careful about wire vs reg in verilog: Anything assigned within an "always" block has to be a reg. (Ie, in procedural code).

But that alone doesn't make it a register: you can write "always @*" blocks which model combinational logic. Everything set by them will need to be of type reg, but they'll all be asynchronous.

What makes it a register is being assigned in a synchronous way.

The wire type can be assigned at initialisation, or in an "assign" statement of its own. But not in an always block.

That "set every clock" thing I didn't notice either: but it's an implementation detail hidden in that particular fifo module. Many FIFO modules I'm used to would be quite happy to accept fresh data every clock: the wr_en line is usually just a level-sensitive enable, so it seems sensible to do burst writes.

Anyway: Glad I could be of help. :)

-- Remy

On Saturday, 12 November 2016, bmentink notifications@github.com wrote:

@RGD2 https://github.com/RGD2

Hi Remy, I have found my issues, and of course of my own making.

There was several mistakes:

  1. I had to define my interface to the FIFO as "reg" I had them as "wire"
  2. The test of the drum_output[] would not work, I guess because it is a wire, so not registered. 3.

    The wr_en had to be toggled every alternate clock cycle, I had tried to toggle on only one edge. So the working code was:

    always @(posedge clk) begin buf_in <= drum_output[1]; wr_en <= ~wr_en; end

    This will of course be modified to loop around all my outputs and feed them to the FIFO.

The key to resolving this, was your suggestions of testing the code around the FIFO, which I did by removing the FIFO and replacing with a simple assign of buf_out to buf_in, when I got that working, my FIFO just worked ..

Thanks for the help.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/jamesbowman/swapforth/issues/46#issuecomment-260072339, or mute the thread https://github.com/notifications/unsubscribe-auth/AO8-GO2d3DXMyUFEaLA70sNJmf_JWd-Aks5q9O7QgaJpZM4KsDK0 .

-- Remy

jamesbowman commented 6 years ago

Closing. A Verilog-related forum might have been a better place for this question.