Author Topic: [Verilog] Test Bench Error - llegal output or inout port connection for port  (Read 8544 times)

0 Members and 1 Guest are viewing this topic.

Offline pigtwoTopic starter

  • Regular Contributor
  • *
  • Posts: 133
Hello again, I just started working with test benches and I ran into an error. 

I'm trying to test a memory controller I made but I'm having a problem with the inout port.  I'm basically just trying to see if it reads the data from the inout port correctly.

Here is the error I'm getting:
Code: [Select]
Illegal output or inout port connection for "port 'Mem_IO'"

Here is the test bench:
Code: [Select]
`timescale 1ns/10ps
module test_mem_cont;
 
  reg clock, rw, reset, execute;
  reg [10:0] addr_in;
  wire ready;
  reg [5:0] mem_io;
 
  Memory_Controller dut(
    .Clock_50MHZ(clock),
    .RW(rw),
    .Reset(reset),
    .Execute(execute),
    .Addr_In(addr_in),
    .Ready(ready),
    .Mem_IO(mem_io));

  initial clock = 0;
  always # 10 clock = ~clock;
 
  initial
    begin
   
    mem_io <= 10;
    reset <= 0;
   
    # 50
   
    reset <= 1;
   
    # 1000
   
    addr_in <= 5;
    rw <= 0;
   
    while(1)
      begin
      # 40
      if(ready)
        # 40
        execute <= 1;
        # 40
        execute <= 0;
      end
    $stop;
    end
endmodule

And here is the module I am testing:
Code: [Select]
module Memory_Controller(
input wire Clock_50MHZ, RW, Reset, Execute,
input wire[5:0] Data_In,
input wire[10:0] Addr_In,    // In the form [A12, A11, A8-A0]

inout wire [5:0] Mem_IO,

output wire[5:0] Data_Out,
output wire[10:0] Addr_Out,
output wire Data_Ready, CS, RAS, CAS, WE, BA0, BA1, A9, A10, CKE, Ready, DQMH, DQML, CLK
);
// This is a basic memory controller for the IS42S16160B memory chip.  Which has 256 Mb of memory in 16 bit words. 
//  RW: 1 means write, 0 means read

// Symbolic mode register defintion
localparam[14:0] mode_reg = 15'b00000100010000;

// Symbolic OP-Code definition.  The OP Code is in the form [!CS, !RAS, !CAS, !WE]
localparam[3:0]
read = 4'b0101,
write = 4'b0100,
nop = 4'b0111,
activate = 4'b0011,
refresh = 4'b0001,
load_mode_reg = 4'b0000,
precharge = 4'b0010;

// Symbolic state defintions
localparam[4:0]
Start = 5'h1,
Start_NOP = 5'h2,
Start_Precharge = 5'h3,
Start_Refresh = 5'h4,
Start_Refresh_Loop = 5'h5,
Load_Mode_Reg = 5'h6,
Load_Mode_Reg_NOP1 = 5'h7,
Load_Mode_Reg_NOP2 = 5'h8,
Idle = 5'h9,
Refresh = 5'hA,
Refresh_NOP1 = 5'hB,
Refresh_NOP2 = 5'hC,
Refresh_NOP3 = 5'hD,
Refresh_NOP4 = 5'hE,
Activate = 5'hF,
Activate_NOP = 5'h10,
Read = 5'h11,
Read_NOP1 = 5'h12,
Read_NOP2 = 5'h13,
Write = 5'h14,
Write_NOP1 = 5'h15,
Precharge = 5'h16,
Precharge_NOP = 5'h17;

// Internal defintions
reg[10:0] address, address_next;
reg[4:0] state, state_next;
reg[3:0] op_code, op_code_next;
reg[5:0] data_out, data_out_next, mem_io, mem_io_next;
reg[1:0] nop_count, nop_count_next;
reg[3:0] refresh_count, refresh_count_next;
reg[13:0] init_wait_count, init_wait_count_next;
reg ready, ready_next, data_ready, data_ready_next, ba0, ba0_next, ba1, ba1_next, a9, a9_next, a10, a10_next;

// FSMD register and data specifications
always @(posedge Clock_50MHZ)
begin
if(!Reset)
begin
state <= Start;
op_code <= nop;
nop_count <= 0;
refresh_count <= 0;
ready <= 0;
data_ready <= 0;
address <= 0;
ba0 <= 0;
ba1 <= 1;
a9 <= 0;
a10 <= 0;
mem_io <= 0;
data_out <= 0;
init_wait_count <= 0;
end
else
begin
state <= state_next;
op_code <= op_code_next;
nop_count <= nop_count_next;
refresh_count <= refresh_count_next;
ready <= ready_next;
data_ready <= data_ready_next;
address <= address_next;
ba0 <= ba0_next;
ba1 <= ba1_next;
a9 <= a9_next;
a10 <= a10_next;
mem_io <= mem_io_next;
data_out <= data_out_next;
init_wait_count <= init_wait_count_next;
end
end

// FSMD next state definitions
always @*
begin
// Define default values
state_next = state;
op_code_next = op_code;
nop_count_next = nop_count;
refresh_count_next = refresh_count;
ready_next = ready;
data_ready_next = data_ready;
address_next = address;
ba0_next = ba0;
ba1_next = ba1;
a9_next = a9;
a10_next = a10;
mem_io_next = mem_io;
data_out_next = data_out;
init_wait_count_next = init_wait_count;

case(state)
// Initialization sequence
Start:
begin
data_out_next = 0;
ready_next = 0;
op_code_next = nop;
data_ready_next = 0;
refresh_count_next = 0;
mem_io_next = 0;
ba0_next = 0; // These two may need to be different but I think they can be constant. 
ba1_next = 0; //    They are essentually MSB of the address.
init_wait_count_next = 0;
state_next = Start_NOP;
end

Start_NOP:
begin
op_code_next = nop;
init_wait_count_next = init_wait_count + 1;
// if(init_wait_count == 14'd10001)
state_next = Start_Precharge;
end

Start_Precharge:
begin
op_code_next = refresh;
nop_count_next = 0;
state_next = Start_Refresh;
end

Start_Refresh:
begin
op_code_next = nop;
if(nop_count == 2'd2) // Four nops are needed in total.  This will achive two and the other comes from the state
state_next = Start_Refresh_Loop; //    one of the state transisions later on.
else
begin
nop_count_next = nop_count + 2'd1;
state_next = Start_Refresh;
end
end

Start_Refresh_Loop:
begin
op_code_next = nop;
refresh_count_next = refresh_count + 4'd1;
if(refresh_count != 10)
state_next = Start_Precharge;
else
begin
op_code_next = load_mode_reg;
{ba1_next, ba0_next, address_next[10], address_next[9], a10_next, a9_next, address_next[8:0]} = mode_reg;
state_next = Load_Mode_Reg;
end
end

Load_Mode_Reg:
begin
op_code_next = nop;
state_next = Load_Mode_Reg_NOP1;
end

Load_Mode_Reg_NOP1:
begin
op_code_next = nop;
state_next = Load_Mode_Reg_NOP2;
end

Load_Mode_Reg_NOP2:
begin
op_code_next = nop;
refresh_count_next = 0;
a10_next = 0;
state_next = Idle;
end

// Idle
Idle:
begin
data_out_next = data_out;
ready_next = 1;
refresh_count_next = refresh_count + 4'd1;
op_code_next = nop;
if(refresh_count == 400)   //REMOVE////////// replace with frequency dependant value later
begin
op_code_next = refresh;
state_next = Refresh;
end
else if((refresh_count != 400)&&Execute)
begin
op_code_next = activate;
ready_next = 0;
data_ready_next = 0;
state_next = Activate;
end
else
begin
state_next = Idle;
end
end

// Refresh sequence
Refresh:
begin
op_code_next = nop;
state_next = Refresh_NOP1;
end

Refresh_NOP1:
begin
op_code_next = nop;
state_next = Refresh_NOP2;
end

Refresh_NOP2:
begin
op_code_next = nop;
state_next = Refresh_NOP3;
end

Refresh_NOP3:
begin
op_code_next = nop;
state_next = Refresh_NOP4;
end

Refresh_NOP4:
begin
op_code_next = nop;
state_next = Idle;
end

// Activate sequence
Activate:
begin
address_next = Addr_In;
op_code_next = nop;
state_next = Activate_NOP;
end

Activate_NOP:
begin
if(RW)     // Write
begin
op_code_next = write;
mem_io_next = Data_In;
state_next = Write;
end
else      // Read
begin
op_code_next = read;
state_next = Read;
end
end

// Write sequence
Write:
begin
op_code_next = nop;
state_next = Write_NOP1;
end

Write_NOP1:
begin
op_code_next = precharge;
state_next = Precharge;
end

// Read sequence
Read:
begin
op_code_next = nop;
state_next = Read_NOP1;
end

Read_NOP1:
begin
op_code_next = nop;
data_out_next = Mem_IO;    // ????? mem_io ?
state_next = Read_NOP2;
end

Read_NOP2:
begin
op_code_next = precharge;
data_ready_next = 1;
state_next = Precharge;
end

// Precharge sequence
Precharge:
begin
op_code_next = nop;
state_next = Precharge_NOP;
end

Precharge_NOP:
begin
op_code_next = nop;
state_next = Idle;
end

default:
state_next = Idle;
endcase
end

// Connections
assign CLK = Clock_50MHZ;
assign DQMH = 0;
assign DQML = 0;
assign Mem_IO = (RW) ? mem_io : 6'bz;
assign Data_Out = data_out;
assign CS = op_code[3];
assign RAS = op_code[2];
assign CAS = op_code[1];
assign WE = op_code[0];
assign CKE = 1;         // Clock enable.  Might need a non constant value for start up.
assign BA0 = ba0;
assign BA1 = ba1;
assign A9 = a9;
assign A10 = a10; // Selects which banks to activate.  Since I'm always using the same banks, IE BA0/BA1 constant, it shouldn't matter.
assign Addr_Out = address;
assign Data_Ready = data_ready;
assign Ready = ready;

endmodule

I'm not sure what is causing this.  It's probably something really obvious but I'm not noticing because this is pretty much my first attempt at a test bench.

Thank you!
 

Offline cyr

  • Frequent Contributor
  • **
  • Posts: 252
  • Country: se
Make mem_io a wire, you can't connect an output or a "inout" to a register.

To be able to simulate reads and writes, you can do something like this:

Code: [Select]

wire [5:0] mem_io;
reg [5:0] mem_out;
reg mem_oe;

...

assign mem_io = (mem_oe) ? mem_out : 6'hz;


Assign the data you expect to read to mem_out, and set mem_oe high when the RAM should be driving the bus.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf