# Birectional I/O pin in verilog

I'm wanting eventually to interface some memory to my fpga. This will require pins on the fpga that can both read data and write output to the ram.

I'm far away from doing any of that yet, but as a learning exercise wanted make a simple module in verilog that when a direction signal is '1' output a signal to a pin, and when it is '0' reads a value from that pin.

But I can't get anything to compile. I'm not completely inexperienced with verilog but feel I'm missing something fundamental here rather than just having a simple typo in my example.

This code doesn't compile, I'm looking for either how to make it work, or even just a pointer to what I'm fundamentally missing to make bidirectional signals work. If it matters I'm using xilinx tools and plan to synthesize this to an xc3s50 or similar.

// This doesn't compile...
module test(
input  clock,           // The standard clock
input  direction,  // Direction of io, 1 = set output, 0 = read input
input  data_in,        // Data to send out when direction is 1
output data_out,       // Result of input pin when direction is 0
inout  io_port     // The i/o port to send data through
);

always @(posedge clock)
begin

// If direction is 1 then set
if (direction == 1)
begin
io_port <= data_out;
end

if (direction == 0)
begin
data_in <= io_port;
end
end

endmodule


edit The errors I get are -

ERROR:HDLCompilers:247 - "test.v" line 16 Reference to scalar wire 'io_port' is not a legal reg or variable lvalue
ERROR:HDLCompilers:106 - "test.v" line 16 Illegal left hand side of nonblocking assignment
ERROR:HDLCompilers:247 - "test.v" line 21 Reference to scalar wire 'data_in' is not a legal reg or variable lvalue
ERROR:HDLCompilers:106 - "test.v" line 21 Illegal left hand side of nonblocking assignment


Inouts are actually "wire" so you can't use any procedural/sequential assignments (where the left hand side must be a reg). Generally speaking:

• input : internally must always be of type net, externally the inputs can be connected to a variable of type reg or net.
• output : internally can be of type net or reg, externally the outputs must be connected to a variable of type net.
• inout : internally or externally must always be type net, can only be connected to a variable net type.

A common approach is to have an "enable" signal for the output of your inout, and to drive to high impedance if the output is not enabled. In your case direction is playing that role.

module test(
input  clock,      // The standard clock
input  direction,  // Direction of io, 1 = set output, 0 = read input
input  data_in,    // Data to send out when direction is 1
output data_out,   // Result of input pin when direction is 0
inout  io_port     // The i/o port to send data through
);

reg a, b;

assign io_port  = direction ? a : 1'bz;
assign data_out = b;

always @ (posedge clk)
begin
b <= io_port;
a <= data_in;
end

end

endmodule


The hardware corresponding to the above code would look something like this:

• Ah I see. Thank you.I completely forgot about z states. Although this will always set data_in to be the data I'm sending won't it and not the value of the pin? – John Burton Jun 3 '12 at 18:15
• @JohnBurton I changed the verilog to be a little more like I think what you were going for. – vicatcu Jun 3 '12 at 18:19
• The updated code (and picture) will pass io_port to data_out when direction is low and will pass data_in to io_port (and data_out one cycle later) when direction is high. – vicatcu Jun 3 '12 at 18:38
• what software are u using to produce that synthesis output? – sybreon Jun 4 '12 at 0:49
• @sybreon heh, I just used Eagle schematic capture to hack a drawing together. – vicatcu Jun 4 '12 at 1:43