EEVblog Electronics Community Forum

Electronics => FPGA => Topic started by: rea5245 on December 02, 2022, 09:26:02 pm

Title: Help with Verilog vectors
Post by: rea5245 on December 02, 2022, 09:26:02 pm
I don't understand why a piece of Verilog code doesn't work, and I don't know how to fix it.

Here's the code. It's accessing a ROM:

Code: [Select]
module U16(input A12, input A7, input A6, input A5, input A4,
    input A3, input A2, input A1, input A0,
    inout I_O0, inout I_O1, inout I_O2, inout I_O3, inout I_O4, inout I_O5, inout I_O6, inout I_O7,
    input nCE, input A10, input nOE, input A11, input A9, input A8, input nWE);

   wire [12:0] A = {A12, A11, A10, A9, A8, A7, A6, A5, A4, A3, A2, A1, A0};
   wire [7:0] I_O = {I_O7, I_O6, I_O5, I_O4, I_O3, I_O2, I_O1, I_O0};

   rom romimpl(A, nCE, nOE, I_O);

endmodule

When this is run in Modelsim, the data lines (I_O<n>) are all HiZ.

If I change the invocation of romimpl to:

Code: [Select]
   rom romimpl(A, nCE, nOE, {I_O7, I_O6, I_O5, I_O4, I_O3, I_O2, I_O1, I_O0});

it works: the data lines have data on them.

So obviously, the way I'm collecting I_O<n> into a vector is wrong.

What's the right way to do it?

Thank you.
Title: Re: Help with Verilog vectors
Post by: Foxxz on December 02, 2022, 10:11:02 pm
You need to

Code: [Select]
   wire [12:0] A;
   wire [7:0] I_O;

   assign A = {A12, A11, A10, A9, A8, A7, A6, A5, A4, A3, A2, A1, A0};
   assign I_O = {I_O7, I_O6, I_O5, I_O4, I_O3, I_O2, I_O1, I_O0};
Title: Re: Help with Verilog vectors
Post by: rea5245 on December 02, 2022, 11:08:40 pm
Code: [Select]
   wire [12:0] A;
   wire [7:0] I_O;

   assign A = {A12, A11, A10, A9, A8, A7, A6, A5, A4, A3, A2, A1, A0};
   assign I_O = {I_O7, I_O6, I_O5, I_O4, I_O3, I_O2, I_O1, I_O0};

Thank you, but that did not fix it.

Another thing that puzzles me is that the A vector works OK. Could this have something to do with A being input and I_O being inout?
Title: Re: Help with Verilog vectors
Post by: BrianHG on December 02, 2022, 11:38:41 pm
For this to work, you need all the address inputs tied or set to something especially the nCE and nOE.
If you do not, Modelsim will most likely show you blue Hi-Z output waveform for the data.

If the data in the 'rom romimpl()' implementation contents is not set or cleared, any missing address inputs, then output waveform will most likely be Red unknown X, assuming you tied the nCE and nOE to GND.

Title: Re: Help with Verilog vectors
Post by: rea5245 on December 02, 2022, 11:48:43 pm
For this to work, you need all the address inputs tied or set to something especially the nCE and nOE.
If you do not, Modelsim will most likely show you blue Hi-Z output waveform for the data.

Yeah, but all I need to do, to change it from non-working to working is to change:
   rom romimpl(A, nCE, nOE, I_O);
to:
   rom romimpl(A, nCE, nOE, {I_O7, I_O6, I_O5, I_O4, I_O3, I_O2, I_O1, I_O0});

So the address lines, nCE, and nOE are OK. And if I put a breakpoint in the 'rom' module, I can verify that they're OK.
Title: Re: Help with Verilog vectors
Post by: BrianHG on December 03, 2022, 01:10:03 am
Ok, you are correct.
The wire xxx = {xa,xb,sc...} and assign  xxx = {xa,xb,sc...}, you have it backwards.
(My fault, I should have noticed...)

assign {I_O7, I_O6, I_O5, I_O4, I_O3, I_O2, I_O1, I_O0} = I_O;

Would have fed your IO port with output data.
Title: Re: Help with Verilog vectors
Post by: rea5245 on December 03, 2022, 01:30:56 am
assign {I_O7, I_O6, I_O5, I_O4, I_O3, I_O2, I_O1, I_O0} = I_O;

Would have fed your IO port with output data.

Yup, that did it! Thank you!

But what if this were RAM and I needed it to be bidirectional?
Title: Re: Help with Verilog vectors
Post by: BrianHG on December 03, 2022, 02:09:59 am
Usually in FPGAs, a ram module has a data in path and data out path.  It is designed this way so you may post writes while waiting the 1 or 2 clocks for the previous read to come back.

Code: [Select]
(showing 2 of 8 bits)
assign {I_O7,I_O6}   = (~nOE && ~nCE) ? mem_Q[7:6] : 2'bzz ;  // the mem_Q comes from the FPGA ram's read data.
assign mem_D[7:6]   = {I_O7, I_O6} ; // the mem_D goes to the data input port of the ram for writing.

Or, for your case, maybe try:
bidir  I_O[7:0] = {I_O7, I_O6, I_O5, I_O4, I_O3, I_O2, I_O1, I_O0};


IE: Making ram from scratch...
Code: [Select]
input clk,nOE,nCE,nWE;
input [15:0] A;
bidir [7:0] DQ;

reg [7:0] memory [0:65535] ;  // ram...
assign DQ = (~nOE && ~nCE && nWE) ? memory[A] : 8'bzzzzzzzz ; // Non clocked read....
always @(posedge clk) if (~nCE && ~nWE)  memory[A] <= DQ ; // omitting this line, and adding an 'initial' at the reg with a file or text array basically makes a rom.
endmodule
Note that clocking the read data usually makes the FPGA 2x faster.
Note that clock D-latching read and write address (you also need to latch the write data) makes the FPGA another 2x faster.
Note that non-clocking the write usually makes the FPGA 2x slower.
Title: Re: Help with Verilog vectors
Post by: rea5245 on December 03, 2022, 04:51:26 pm
Or, for your case, maybe try:
bidir  I_O[7:0] = {I_O7, I_O6, I_O5, I_O4, I_O3, I_O2, I_O1, I_O0};

bidir doesn't seem to be a Verilog keyword. And inout doesn't work there either.
Title: Re: Help with Verilog vectors
Post by: asmi on April 30, 2023, 09:55:51 pm
There are no bidirectional lines inside FPGA. If you need to work with bidirectional lines coming from outside of chip, you will need to use constructs like this one:
Code: [Select]
module blah(..., inout pin, ...)

reg pin_tristate;
reg pin_out;
assign pin = pin_tristate ? 1'bZ : pin_out;
// to set the pin to input mode, you tristate output (pin_tristate <= 1'b1), to set it into output mode, you clear tristate flag (pin_tristate <= 1'b0), and the value of pin_out register will be driven out of the pin
if you attempt to use such construct inside FPGA, it will be synthesized using multiplexes instead.

Alternatively, you can use vendor-provided IO primitives (like IOBUF for Xilinx devices) which essentially do the same, but can offer more options and/or additional functionality.