# Verilog: Conditionally setting single bits to high-Z in vector

I have written a single-pin GPIO module for my project, and it is working fine. A simplified version looks like this:

module gpio_port(
input clk,
input reset,
...
inout gpio_pin
);

reg write_data;
reg pin_direction;  // 1: Write, 0: Read

// This line is problematic.
assign gpio_pin = pin_direction == 1'b1 ? write_data : 1'bZ;

always @(posedge clk or negedge reset) begin
// ...
write_data <= ...
end


I now want to extend this concept to a full 16-bit GPIO-port. So when I tried extending it, I came across a problem: In the version with only a single pin, the direction bit is used to determine whether the write bit should be put onto the inout wire, or if it should be driven high-Z. But I can't figure out, in the 16-bit wide example, how to selectively set the single bits in the inout pin vector to high-Z or the the bit in the write register.

module gpio_port(
input clk,
input reset,
...
inout [15:0] gpio_pin
);

reg [15:0] write_data;
reg [15:0] pin_direction;   // 1: Write, 0: Read

// This line is problematic.
assign gpio_pin = ???


My problem is that I am pretty new to Verilog, so I don't even know what to google for here, so I am sorry if this question is super trivial. I understand that I could just use a single direction flag, but I would like the pins to be individually definable as either input or output.

What I have tried:

I am currently using the following solution, which is super hacky:

assign gpio_pins[0] = (pin_direction[0] == 1'b1) ? write_data[0] : 1'bZ;
assign gpio_pins[1] = (pin_direction[1] == 1'b1) ? write_data[1] : 1'bZ;
assign gpio_pins[2] = (pin_direction[2] == 1'b1) ? write_data[2] : 1'bZ;
// ... and on and on ..

• In VHDL you'd either put this in a FOR loop in a process, or use a Generate statement. Feb 28, 2020 at 22:22

Two things you can do. Verilog has a structure generate-for loop construct in contrast to a procedural-for loop.

for(genvar pin;pin<N;pin++) begin : pins
assign gpio_pins[pin] = (pin_direction[pin] == 1'b1) ? write_data[pin] : 1'bZ;
end


Another thing you can do is

assign gpio_pins = write_data;


and make an assignment write_data[index] = 1'bz; when you want to read gpio_pins[index]