Amal
June 29, 2015, 2:26pm
1
Is there a way to access a parameterized interface port’s size from within a module that uses this interface? The code below is close to what I want to do, just a representative.
interface my_if
#( parameter int unsigned P_WIDTH = 2 )
(
input wire clk,
input wire srst
);
logic [P_WIDTH-1:0] data;
modport master ( output data );
modport slave ( input data );
endinterface : my_if
If a module uses this interface
module my_slave
(
input wire clk,
input wire srst,
my_if.slave slv,
output logic [$bits(slv.data)-1:0] q
// A: ^^^^^^^^^^^^^^^
);
localparam C_WIDTH = $bits(slv.P_WIDTH);
// B: ^^^^^^^^^^^^^^^^^^
always_ff @( posedge clk ) begin
q <= slv.data;
end
module : my_slave
A: $bits(slv.data) results in a value of one (1) !
B: $bits(slv.P_WIDTH) causes: “Illegal reference to a parameter below an arrayed instance: slv.P_WIDTH” .
Can this be done in a generic way instead of passing the P_WIDTH to my_slave?
– Amal
In reply to Amal :
Your code worked for me. Contact your tool vendor for support.
Amal
July 2, 2015, 6:30pm
3
In reply to dave_59 :
Hi Dave,
I have tried this in a number of different vendor tools (Questa, Synplify and Vivado) and I have cases open with each vendor. They seem to say that accessing interface port parameters is not valid because it is like a hierarchical access to a parameter inside an interface. And off course I want this to be synthesizable.
In the following more elaborate example, are these valid (according to LRM) accesses to the P_WIDTH parameter and data of master port mst[0]? Hierarchical access to objects within a module is not valid. If interfaces are like modules, shouldn’t this same statement be true for interfaces? But personally I would think I should be able to access an interface port’s parameters/signals this way.
$bits(mst[0].data)
mst[0].P_WIDTH
//--------------------------------------------------------------------------------------------------
interface my_if
#( parameter int unsigned P_WIDTH = 2 )
(
input wire clk,
input wire srst
);
logic [P_WIDTH-1:0] data;
modport master ( output data );
modport slave ( input data );
initial begin
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
$display("my_if");
$display(" P_WIDTH : %0d - %m", P_WIDTH);
end
endinterface : my_if
//--------------------------------------------------------------------------------------------------
module my_slave
#(
parameter P_COUNT = 4
)
(
input wire clk,
input wire srst,
//
my_if.slave slv,
my_if.master mst[0:P_COUNT-1]
);
// Uncommenting this prints:
//# top.slv: $bits(mst[0].data) = 1
//# top.slv: $bits(mst[1].data) = 5
localparam C_WIDTH1 = $bits(mst[0].data);
// Uncommenting this printss:
//# top.slv: $bits(mst[0].data) = 5
//# top.slv: $bits(mst[1].data) = 1
localparam C_WIDTH2 = $bits(mst[1].data);
// The following causes error: "Illegal reference to a parameter below an arrayed instance: mst[0].P_WIDTH"
//localparam C_WIDTH3 = mst[0].P_WIDTH;
//localparam C_WIDTH4 = mst[1].P_WIDTH;
initial begin
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
$display("my_slave");
$display(" %m: $bits(slv.data) = %0d", $bits(slv.data));
$display(" %m: slv.P_WIDTH = %0d", slv.P_WIDTH);
$display(" %m: $bits(mst[0].data) = %0d", $bits(mst[0].data));
$display(" %m: $bits(mst[1].data) = %0d", $bits(mst[1].data));
$display(" %m: mst[0].P_WIDTH = %0d", mst[0].P_WIDTH);
$display(" %m: mst[1].P_WIDTH = %0d", mst[1].P_WIDTH);
//for( int unsigned i=0; i<P_COUNT; i++ ) begin
// $display(" %m: $bits(mst[%0d].data) = %0d", i, $bits(mst[i].data));
//end
//for( int unsigned i=0; i<P_COUNT; i++ ) begin
// $display(" %m: mst[%0d].P_WIDTH = %0d", i, mst[i].P_WIDTH);
//end
//$display(" %m: C_WIDTH3 = %0d", C_WIDTH3);
//$display(" %m: C_WIDTH4 = %0d", C_WIDTH4);
end
for( genvar i=0; i<P_COUNT; i++ ) begin
always_ff @( posedge clk ) begin
mst[i].data <= slv.data + i;
end
end
endmodule : my_slave
//--------------------------------------------------------------------------------------------------
module top
#( parameter int unsigned P_WIDTH = 5 )
(
input wire clk,
input wire srst,
input wire [P_WIDTH-1:0] din,
output logic [P_WIDTH-1:0] dout0,
output logic [P_WIDTH-1:0] dout1
);
localparam C_COUNT = 2;
my_if #( .P_WIDTH(P_WIDTH) ) slv_if ( .clk(clk), .srst(srst) );
my_if #( .P_WIDTH(P_WIDTH) ) mst_if[0:C_COUNT-1] ( .clk(clk), .srst(srst) );
assign slv_if.data = din;
my_slave #( .P_COUNT(C_COUNT) ) slv( .clk(clk), .srst(srst), .slv(slv_if), .mst(mst_if) );
assign dout0 = mst_if[0].data;
assign dout1 = mst_if[1].data;
endmodule : top
Regards,