0
\$\begingroup\$

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 ..
\$\endgroup\$
1
  • 1
    \$\begingroup\$ In VHDL you'd either put this in a FOR loop in a process, or use a Generate statement. \$\endgroup\$ Feb 28, 2020 at 22:22

1 Answer 1

1
\$\begingroup\$

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]

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.