I have a situation which I believe is very common. I have a module with an SV Interface. The interface is a typical AXI interface.
Depending on one of the module’s parameters I want to instantiate an IP (an AXI clock converter) which has two of those interfaces, one Slave port and one Master port. In that case the Interface port of the module is connected to the the slave port of the clock converter and the Master side is connected to a newly create interface (create inside my module itself).
However, when the HDL parameters indicate so I don’t wanna instantiate the clock converter, instead what I would like to do is connect the port interface to my internal interface, since no CDC is required, I want the internal interface to be a direct assignment of the input interface…
I tried with a simple assign but of course I got an error. Is there a clean way of doing this (hopefully a one-liner)? or do I have to go signal by signal to do this?
Well… this is a pitty… seems like it would be a very usefull thing to do…
Just another quick question, are interfaces capable of having their internal signals initialized upon instantiation?? Inside my interface I have a bunch of logics, if I give them an initial valud then I can not assign them in clocked blocks, if I don’t then… well… I don’t have init values then.
If I give them init values and then I want to assign them with an “assign” I can’t… I have to use an “always_comb”, If I don’t and then I want to have one I am forced to use an auxiliary register with an init value and assign that register to the interface signal with an assign… The ideal thing would be to be able to choose upon instantiation… is there any way of doing this?
SV LRM: “an interface can also contain processes (i.e., initial or always procedures) and continuous assignments, which are useful for system-level modeling and testbench applications.”
Please be clear about the signal in your interface is declared as “variable” or “net”.
A net can be written by one or more continuous assignments, by primitive outputs, or through module ports. The resultant value of multiple drivers is determined by the resolution function of the net type. A net cannot be procedurally assigned.
Variables can be written by one or more procedural statements, including procedural continuous assignments. The last write determines the value. Alternatively, variables can be written by one continuous assignment or one port.
You can have a continuous assignment to a variable. But when you do so,you can only have one continuous assignment and no other procedural assignments at the same time.
Based on this thread, my guess is no.
Based on that if there is an interface port that needs to be retimed, all fields need to be broken out one at time like this:
always_ff @(posedge clk)
begin
first_sig_q <= my_inteface_port.first_sig;
second_sig_q <= my_interface_port.second_sig;
// ....
end
Does that make sense that the signals have to be broken out to be retimed, or am I missing some easy way to retime all the signals in an interface?
A packed struct can be retimed, maybe this indicates a case where a packed struct port would be preferred over an interface.
Yes you can make procedural or continuous assignments from the signals inside one interface to another using hierarchical references. You would have to know the flow of data to know which direction to make the assignments.
If you were to use structures you would have to isolate the structures by direction. i.e. one structure for inputs and another for outputs.
We already have constructs in SystemVerilog that can handle these kinds of of requirements. They are called classes. Just by passing a handle, we can connect bundles of variables together. We know they can be synthesized as SystemC has shown us, but we’re still waiting for support in SystemVerilog. We’ve been waiting for synthesis and place&route tools to handle arrays of wires for 30 years.
class A;
bit [3:0] x,y;
endclass
module top;
bit clk;
A w1,w2;
classconnect cc(.clk,.in(w1),.out(w2));
initial repeat(100) #5 clk=!clk;
always @(negedge clk) begin
w1 = new;
assert (randomize(w1.x,w1.y));
$display("%in %p out %p",w1,w2);
end
endmodule
module classconnect(input bit clk, A in, output A out);
always@(posedge clk)
out <= in;
endmodule