2
\$\begingroup\$

Verilog beginner here. Working with Lattice Diamond for a design using the MachXO2.

For context: I recently got this answer to a related question. See the second image in the answer.

I want to implement a dblbuffer module that internally has the two FIFOs as shown in that diagram (FIFO_DC module from their IPExpress; module name is fifo_dc), and externally just has input data / write clock, and output data /read clock (plus some additional auxiliary signals, not relevant to this post/question).

I can't seem to connect the output from the selector/multiplexer to the module's output:

module dblbuffer (data_in, wr_clk, out, rd_clk, save_current);

input wr_clk, rd_clk, save_current;
input [15:0] data_in;
output [15:0] out;

reg selected; // a buffered/synchronized/edge-detection version of save_current
              // (details related to it omitted here for simplicity)

always @(fifo0.Q, fifo1.Q, selected)
begin
    out[15:0] <= (selected ? fifo1.Q[15:0] : fifo0.Q[15:0]);
end

fifo_dc fifo0
(
    .Data(data_in), 
    .WrClock(wr_clk),
    .RdClock(rd_clk),
    // ···
    .Q(), // Should I leave Q unassigned, to be used as above?
    // ···
);

fifo_dc fifo1 ....

The synthesizer gives me procedural assignment to a non-register out is not permitted. VERI-1100.

So, I try adding:

reg[15:0] out_wires;
assign out_wires[15:0] = out[15:0];

And now it tells me concurrent assignment to a non-net out_wires is not permitted. VERI-1195. I thought it was related to the = vs. <=, but trying that with the <= gives me a plain syntax error (syntax error near <=. VERI-1137).

If I simply try reg[15:0] out_wires = out[15:0] it tells me that out is not a constant. VERI-1188.

I hope it's clear what I'm trying to do so that someone can point out the correct syntax (or the correct structure, if what I'm doing wrong goes beyond just syntax).

Thanks!

\$\endgroup\$
2
\$\begingroup\$

It would be simpler to just declare the output port as reg (instead of the default, which is wire):

output reg [15:0] out;

But you don't really need the always block anyway, so just write:

output [15:0] out;

assign out[15:0] = (selected ? fifo1.Q[15:0] : fifo0.Q[15:0]);
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Huh -- with output reg[15:0] out and the rest unchanged, I get the error dblbuffer.v(22): external reference fifo0.Q remains unresolved. VERI-1172 (line 22 is always @(fifo0.Q, fifo1.Q, selected). Actually with either of the two approaches (with the assign line it gives me the same error). Perhaps, that reflects some other error that was there, but the non-reg error was making the compiler/synthesizer stop before reaching this fifo0.Q unresolved error? \$\endgroup\$ – Cal-linux Sep 15 '19 at 21:01
  • 1
    \$\begingroup\$ Yes, that's a separate problem. \$\endgroup\$ – Dave Tweed Sep 15 '19 at 21:04
  • \$\begingroup\$ Sweet -- declaring wire[15:0] fifo0_Q, fifo1_Q, changing to (selected ? fifo1_Q ··· and tying the .Q of the module to the wires (as in: .Q(fifo0_Q)) seems to solve the issue. I guess one day I will understand why! :-) (and hopefully it is the right thing to do) \$\endgroup\$ – Cal-linux Sep 15 '19 at 21:20
  • \$\begingroup\$ @TomCarpenter -- we seem to have had a race condition! I figured out this change and wrote this comment before I saw your answer (but right after I posted it, I saw that your answer was already there! :-) We even chose the same names fifo0_Q and fifo1_Q .... I guess they're sort of an obvious choice) \$\endgroup\$ – Cal-linux Sep 15 '19 at 21:32
1
\$\begingroup\$

Use a wire to connect to the output of the FIFO. You can if you want for example use a 2D array of wires, then indexing with the selected signal to infer a mux.

output [15:0] out;

wire [15:0] fifo_Q [0:1];
assign out = fifo_Q[selected];

fifo_dc fifo0
    ...
    .Q(fifo_Q[0])
);
...

You could also use the ternary operator (as per @DaveTweed's suggestion) but with a pair of wires connected to the Q outputs:

wire [15:0] fifo0_Q;
wire [15:0] fifo1_Q;
assign out = selected ? fifo1_Q : fifo0_Q;

    ...
    .Q(fifo0_Q)
);
...
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ "indexing with the selected signal to infer a mux" -- aww, that is awesome!!! (I mean, I probably won't change the code, which already had the ternary operator to suggest a mux — although who am I kidding: like I'm going to resist the temptation :-) ) \$\endgroup\$ – Cal-linux Sep 15 '19 at 21:26
  • \$\begingroup\$ "wire [15:0] fifo_Q [0:1];" -- does it make a difference if I write [1:0] instead of [0:1]? I find it curious that you specificallly wrote it like that, but you left the [15:0] like that, with the opposite ordering. \$\endgroup\$ – Cal-linux Sep 15 '19 at 21:46
  • 1
    \$\begingroup\$ @Cal-linux The index ordering doesn't really matter, its just an odd convention left over from memory address being in ascending order, hence [0:1], but binary being written MSB first, hence [15:0]. It doesn't matter if you flip the ordering. \$\endgroup\$ – Tom Carpenter Sep 16 '19 at 7:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.