[Verilog] Test Bench Error - llegal output or inout port connection for port  - Page 1
Forum section: electronics / general

author: pigtwo
author_rank: Regular Contributor
timestamp: July 05, 2014, 03:33:36 am
content: 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:Illegal output or inout port connection for "port 'Mem_IO'"Here is the test bench:Code:`timescale 1ns/10psmodule 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;initialbeginmem_io <= 10;reset <= 0;# 50reset <= 1;# 1000addr_in <= 5;rw <= 0;while(1)begin# 40if(ready)# 40execute <= 1;# 40execute <= 0;end$stop;endendmoduleAnd here is the module I am testing:Code: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 defintionlocalparam[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 defintionslocalparam[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 defintionsreg[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 specificationsalways @(posedge Clock_50MHZ)beginif(!Reset)beginstate <= 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;endelsebeginstate <= 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;endend// FSMD next state definitionsalways @*begin// Define default valuesstate_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 sequenceStart:begindata_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;endStart_NOP:beginop_code_next = nop;init_wait_count_next = init_wait_count + 1;//if(init_wait_count == 14'd10001)state_next = Start_Precharge;endStart_Precharge:beginop_code_next = refresh;nop_count_next = 0;state_next = Start_Refresh;endStart_Refresh:beginop_code_next = nop;if(nop_count == 2'd2)// Four nops are needed in total. This will achive two and the other comes from the statestate_next = Start_Refresh_Loop; // one of the state transisions later on.elsebeginnop_count_next = nop_count + 2'd1;state_next = Start_Refresh;endendStart_Refresh_Loop:beginop_code_next = nop;refresh_count_next = refresh_count + 4'd1;if(refresh_count != 10)state_next = Start_Precharge;elsebeginop_code_next = load_mode_reg;{ba1_next, ba0_next, address_next, address_next, a10_next, a9_next, address_next[8:0]} = mode_reg;state_next = Load_Mode_Reg;endendLoad_Mode_Reg:beginop_code_next = nop;state_next = Load_Mode_Reg_NOP1;endLoad_Mode_Reg_NOP1:beginop_code_next = nop;state_next = Load_Mode_Reg_NOP2;endLoad_Mode_Reg_NOP2:beginop_code_next = nop;refresh_count_next = 0;a10_next = 0;state_next = Idle;end// IdleIdle:begindata_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 laterbeginop_code_next = refresh;state_next = Refresh;endelse if((refresh_count != 400)&&Execute)beginop_code_next = activate;ready_next = 0;data_ready_next = 0;state_next = Activate;endelsebeginstate_next = Idle;endend// Refresh sequenceRefresh:beginop_code_next = nop;state_next = Refresh_NOP1;endRefresh_NOP1:beginop_code_next = nop;state_next = Refresh_NOP2;endRefresh_NOP2:beginop_code_next = nop;state_next = Refresh_NOP3;endRefresh_NOP3:beginop_code_next = nop;state_next = Refresh_NOP4;endRefresh_NOP4:beginop_code_next = nop;state_next = Idle;end// Activate sequenceActivate:beginaddress_next = Addr_In;op_code_next = nop;state_next = Activate_NOP;endActivate_NOP:beginif(RW) // Writebeginop_code_next = write;mem_io_next = Data_In;state_next = Write;endelse // Readbeginop_code_next = read;state_next = Read;endend// Write sequenceWrite:beginop_code_next = nop;state_next = Write_NOP1;endWrite_NOP1:beginop_code_next = precharge;state_next = Precharge;end// Read sequenceRead:beginop_code_next = nop;state_next = Read_NOP1;endRead_NOP1:beginop_code_next = nop;data_out_next = Mem_IO; // ????? mem_io ?state_next = Read_NOP2;endRead_NOP2:beginop_code_next = precharge;data_ready_next = 1;state_next = Precharge;end// Precharge sequencePrecharge:beginop_code_next = nop;state_next = Precharge_NOP;endPrecharge_NOP:beginop_code_next = nop;state_next = Idle;enddefault:state_next = Idle;endcaseend// Connectionsassign 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;assign RAS = op_code;assign CAS = op_code;assign WE = op_code;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;endmoduleI'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!

author: cyr
author_rank: Frequent Contributor
timestamp: July 05, 2014, 08:52:24 am
content: 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: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.