Author Topic: Help with Verilog vectors  (Read 1650 times)

0 Members and 1 Guest are viewing this topic.

Offline rea5245Topic starter

  • Frequent Contributor
  • **
  • Posts: 581
  • Country: us
Help with Verilog vectors
« 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.
 

Offline Foxxz

  • Regular Contributor
  • *
  • Posts: 122
  • Country: us
Re: Help with Verilog vectors
« Reply #1 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};
 

Offline rea5245Topic starter

  • Frequent Contributor
  • **
  • Posts: 581
  • Country: us
Re: Help with Verilog vectors
« Reply #2 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?
 

Offline BrianHG

  • Super Contributor
  • ***
  • Posts: 7725
  • Country: ca
Re: Help with Verilog vectors
« Reply #3 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.

« Last Edit: December 02, 2022, 11:41:37 pm by BrianHG »
 

Offline rea5245Topic starter

  • Frequent Contributor
  • **
  • Posts: 581
  • Country: us
Re: Help with Verilog vectors
« Reply #4 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.
 

Offline BrianHG

  • Super Contributor
  • ***
  • Posts: 7725
  • Country: ca
Re: Help with Verilog vectors
« Reply #5 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.
 

Offline rea5245Topic starter

  • Frequent Contributor
  • **
  • Posts: 581
  • Country: us
Re: Help with Verilog vectors
« Reply #6 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?
 

Offline BrianHG

  • Super Contributor
  • ***
  • Posts: 7725
  • Country: ca
Re: Help with Verilog vectors
« Reply #7 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.
« Last Edit: December 03, 2022, 05:39:34 am by BrianHG »
 

Offline rea5245Topic starter

  • Frequent Contributor
  • **
  • Posts: 581
  • Country: us
Re: Help with Verilog vectors
« Reply #8 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.
 

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2730
  • Country: ca
Re: Help with Verilog vectors
« Reply #9 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.
« Last Edit: April 30, 2023, 10:05:45 pm by asmi »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf