Assign inout to inout (SystemVerilog)

3.6k Views Asked by At

I need make I2C mux inside FPGA. SCL signal from master to slaves should be connected through mux and it's no problem. What about SDA signal? It should work in both directions. Directly connection without High-Z or clock synchronization. assign sda_slave0 = sda_master ;`

module i2c_mux
(
    inout       wire            sda_master,
    input       wire            scl_master,
    inout       wire            sda_slave0,
    output      bit             scl_slave0,
    inout       wire            sda_slave1,
    output      bit             scl_slave1
    inout       bit [1:0]       select
    
)

always_comb
begin
    unique case (select)
    2'b00 : { scl_slave1, scl_slave0 } = { 1, scl_master };
    2'b01 : { scl_slave1, scl_slave0 } = { scl_master, 1 };
    2'b10 : { scl_slave1, scl_slave0 } = { 1, 1 };
    2'b11 : { scl_slave1, scl_slave0 } = { 1, 1 };
end

assign sda_master = sda_slave0; // ?????????????????????
assign sda_slave0 = sda_master; // ?????????????????????


    
endmodule
1

There are 1 best solutions below

1
On

Since you are targeting FPGA, you need to check what is supported on your board. Internal bidirectional tents have limited or no support on FPGAs. They might have special macro modules.

Normally with inouts should have a deterministic driver assign io = drv_en ? data : 'z;. But it looks you want the connecting logic to determine the driving direction. This can be done in simulation; questionable for synthesis.

With SystemVerilog you can use alias (assuming your tool-set supports it)

alias sda_master = sda_slave0 = sda_slave1;

In Veriog and SystemVerilog you can use tran primitive (typically not synthesizable)

tran (sda_master,sda_slave0); 
tran (sda_master,sda_slave1); 

You can also create your own module with aliased ports. This is compatible with Verilog-95 and above. I'm not sure how synthesis friendly it is.

module conn3( .a(io), .b(io), .c(io) );
  inout io;
endmodule

module i2c_mux( /*your port list*/ );
// ... other code

  conn3 link_io(sda_master, sda_slave0, sda_slave1);
endmodule

If you need to conditionally connect, you can use the Verilog primitive tranif (typically not synthesizable)

tranif1 (sda_master,sda_slave0, select==2'b00); 
tranif1 (sda_master,sda_slave1, select==2'b01); 

Again, check what your FPGA supports as it will be the limiting factor.