Help with Verilog vectors - Page 1
Forum section: electronics / general

author: rea5245
author_rank: Frequent Contributor
timestamp: December 02, 2022, 09:26:02 pm
content: 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: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);endmoduleWhen this is run in Modelsim, the data lines (I_O<n>) are all HiZ.If I change the invocation of romimpl to:Code: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.

author: Foxxz
author_rank: Regular Contributor
timestamp: December 02, 2022, 10:11:02 pm
content: You need toCode: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};

author: rea5245
author_rank: Frequent Contributor
timestamp: December 02, 2022, 11:08:40 pm
content: Quote from: Foxxz on December 02, 2022, 10:11:02 pmThank 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?

author: BrianHG
author_rank: Super Contributor
timestamp: December 02, 2022, 11:38:41 pm
content: 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.

author: rea5245
author_rank: Frequent Contributor
timestamp: December 02, 2022, 11:48:43 pm
content: Quote from: BrianHG on December 02, 2022, 11:38:41 pmYeah, 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.

author: BrianHG
author_rank: Super Contributor
timestamp: December 03, 2022, 01:10:03 am
content: 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.

author: rea5245
author_rank: Frequent Contributor
timestamp: December 03, 2022, 01:30:56 am
content: Quote from: BrianHG on December 03, 2022, 01:10:03 amYup, that did it! Thank you!But what if this were RAM and I needed it to be bidirectional?

author: BrianHG
author_rank: Super Contributor
timestamp: December 03, 2022, 02:09:59 am
content: 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:(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: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 : 8'bzzzzzzzz ; // Non clocked read....always @(posedge clk) if (~nCE && ~nWE) memory <= DQ ; // omitting this line, and adding an 'initial' at the reg with a file or text array basically makes a rom.endmoduleNote 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.

author: rea5245
author_rank: Frequent Contributor
timestamp: December 03, 2022, 04:51:26 pm
content: Quote from: BrianHG on December 03, 2022, 02:09:59 ambidir doesn't seem to be a Verilog keyword. And inout doesn't work there either.

author: asmi
author_rank: Super Contributor
timestamp: April 30, 2023, 09:55:51 pm
content: 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: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 pinif 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.