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 read_data;
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
// ...
read_data <= gpio_pin;
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] read_data;
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 ..