Search code examples
veriloghdl

Using 'assign' for binding module ports


I'm new to Verilog and still learning it, but the first think I get about that language is that it's all about ports interconnections. So, I naively wrote the following code

module mult4(input  wire [3:0] x, y,
             output wire [7:0] z)
    sum8 sh, sl, ss;
    assign sl.x = (y[0] ? x : 0),
           sl.y = (y[1] ? x : 0) << 1,
           sh.x = (y[2] ? x : 0) << 2,
           sh.x = (y[3] ? x : 0) << 3,
           ss.x = sl.z,
           ss.y = sh.z,
           sl.cin = 0,
           sh.cin = 0,
           ss.cin = 0,
           z = ss.z;
endmodule

and it wasn't going to work at all. Here sum8 is a mere 8-bit adder with a the following signature:

module sum8(input  wire       cin,   // carry-in bit
            input  wire [7:0] x, y,  // operands
            output wire       cout,  // carry-out bit
            output wire [7:0] z);    // result

Of course, I can rewrite this code to make it compile, but I would like to know another thing. Is there a way to achieve a similar look-and-feel in Verilog, or the only place where I can define port's mapping is inside the parentheses after the module name? If so, are there reasons for that? Do other HDLs have a feature like I want?


Solution

  • The closest thing would be the interface construct in SystemVerilog. It would look something like this:

    interface adder8_itf;
      wire             cin;   // carry-in bit
      wire [7:0] x, y;  // operands
      wire             cout;  // carry-out bit
      wire [7:0] z;     // result
    endinterface 
    module mult4(input  wire [3:0] x, y,
                 output wire [7:0] z);
        adder8_itf sh(), sl(), ss();
        sum8 i1(sh), i2(sl), i3(ss);
        assign sl.x = (y[0] ? x : 0),
               sl.y = (y[1] ? x : 0) << 1,
               sh.x = (y[2] ? x : 0) << 2,
               sh.x = (y[3] ? x : 0) << 3,
               ss.x = sl.z,
               ss.y = sh.z,
               sl.cin = 0,
               sh.cin = 0,
               ss.cin = 0,
               z = ss.z;
    endmodule
    module sum8 (adder8_itf itf);
       assign {itf.cout,itf.z} = itf.x +itf.y;
    endmodule
    

    Though, this is probably more work just so you can organize your port assignments a different way.