Passing bus array to another module via port mapping - verilog

I have below code inside SV module where I instantiate another SV module and pass 5-bit bus to it to check for X and Z's as coded below:
input [4:0] analdo_trim;
cds_XZ_checker XZ_check_analdo_trim (.in(analdo_trim),.in_ok(analdo_trim_ok));
Here is module definition for cds_XZ_checker:
module cds_XZ_checker(in,in_ok);
input in;
output bit in_ok;
always_comb begin //Asynchronous assertion check block
asynch_XZ_check: assert (!($isunknown(in))) in_ok=1'b1;
else begin
$warning ("WARNING (%M) digital signal in=%b is undefined at time %t",in,$time);
in_ok=1'b0;
end//else
end
endmodule
The issue is when I read 5-bit analdo_trim in above module via in port, it only reads LSB of analdo_trim because it doesn't have bus width in declaration.
Module cds_XZ_checker is generic module which is instantiated inside several other modules. Hence, I can't declare 'in' as [4:0] as some other modules might pass bus with different bit width. Is there a way I can parameterize this so that it will work for any bit width?

You can use a parameter to accommodate different input bus widths:
module cds_XZ_checker #(parameter WIDTH=5) (in,in_ok);
input [WIDTH-1:0] in;
output bit in_ok;
always_comb begin //Asynchronous assertion check block
asynch_XZ_check: assert (!($isunknown(in))) in_ok=1'b1;
else begin
$warning ("WARNING (%M) digital signal in=%b is undefined at time %t",in,$time);
in_ok=1'b0;
end//else
end
endmodule
module tb;
logic a,b;
logic [4:0] c;
logic d;
cds_XZ_checker #(.WIDTH(1)) i0 (a, b);
cds_XZ_checker i1 (c, d);
endmodule
The tb module shows how you would parameterize each instance of the checker module. The default width is 5. If your checker input is 5-bit, then passing the parameter is optional.
Demo on edaplayground

Related

Passing bus to another module via port mapping in SystemVerilog

I have below code inside SV module, where I instantiate another SV module and pass 5-bit bus to it to check for X and Z's as coded below:
input [4:0] analdo_trim;
cds_XZ_checker XZ_check_analdo_trim (.in(analdo_trim),.in_ok(analdo_trim_ok));
Here is module definition for cds_XZ_checker:
module cds_XZ_checker(in,in_ok);
input in;
output bit in_ok;
always_comb begin //Asynchronous assertion check block
asynch_XZ_check: assert (!($isunknown(in))) in_ok=1'b1;
else begin
$warning ("WARNING (%M) digital signal in=%b is undefined at time %t",in,$time);
in_ok=1'b0;
end//else
end
endmodule
The issue is when I read 5-bit analdo_trim in above module via in port, it only reads LSB of analdo_trim. Any ideas why the whole 5-bit array is not being passed with above syntax?
You declared the module input to be 1-bit wide. You need to declare it as 5-bit wide. Change:
input in;
to:
input [4:0] in;
Now 5-bit bus to it to check for X and Z's it will be passed. Yours was a small mistake in the declaration
module cds_XZ_checker(in,in_ok);
input [4:0] in;
output bit in_ok;
always_comb begin //Asynchronous assertion check block
asynch_XZ_check: assert (!($isunknown(in))) in_ok=1'b1;
else begin
$warning ("WARNING (%M) digital signal in=%b is undefined at time %t",in,$time);
in_ok=1'b0;
end//else
end
endmodule

Verilog module instantiation reg input output

While implementing Verilog code in behavioral modeling we are using reg as output. But, when I have to use module instantiation and connect it using a wire, it's showing an error while implementation. Is there any other way where I can use module instantiation to connect outputs of different module instances to implement combinational logic as it's illegal to connect the reg output of the previous model to a wire? Note that I have to apply behavioral modeling hence no assignment statements are allowed. This is an example to connect two half adders to one full adder.
module half_adder(input wire a,b,output reg sum,output reg carry);
always#(a or b)
begin
sum = a^b ;
carry= a & b ;
end
endmodule
module full_adder(input wire a,b,c,output reg sum,output reg carry);
wire s1,c1,c2;
half_adder gate1(a,b,s1,c1);
half_adder gate2(s1,c,sum,c2);
always#(a or b or c)
begin
carry = c1|c2;
end
endmodule
Error (10663): Verilog HDL Port Connection error at full_adder.v(14):
output or inout port "sum" must be connected to a structural net
expression
In standard old verilog a reg cannot be connected to a reg using module connection or a continuous assignment. System verilog allows it. So, one of the solutions could be to switch to system verilog.
As for verilog, in half_adder port sum is declared as a reg. Instance gate2 connects variable of type reg to the port of type reg. This is illegal. This type of an assignment can only happen inside a procedural (i.e. always) block. Instance gate1 bypasses this issue by connecting port to the wire s1.
So, you can follow the similar path. Create another wire s2 as in the following example.
module full_adder(input wire a,b,c,output reg sum,output reg carry);
wire s1,c1, s2, c2;
half_adder gate1(a,b,s1,c1);
half_adder gate2(s1,c,s2,c2); // use s2 here
always#*
carry = c1|c2;
always #*
sum = s2; // now you can s2 assign to the 'sum' port
endmodule
Another way is to declare the 'sum' port as a wire. A register can be connected to a wire, using port connections or continuous assignment.
module full_adder(input wire a,b,c,
output sum, // declares it as a wire
output reg carry);
...
half_adder gate2(s1,c,sum,c2); // now it works this way.
And btw, do not use #(a,b,c). It is always error prone and is just wrong in your case. It should be #(c1,c2). But it is much better to use #*.
You should not declare sum as a reg in the full_adder module because it is not being assigned inside a procedural block (such as always). A reg is not a "net" type. Change:
module full_adder(input wire a,b,c,output reg sum,output reg carry);
to:
module full_adder(input wire a,b,c,output sum,output reg carry);
You also have an incorrect sensitivity list. Change:
always#(a or b or c)
to:
always #*
Now, the always block will trigger when the signals on the RHS of the assignments change.

Problem with creating structural modules using interfaces (SystemVerilog)

I'm new in SystemVerilog, and currently learn interfaces, and I ran into problem with structural modules.
So, for example, i have created interface
interface BusInterface
#(parameter N = 3) (input logic i_clk);
logic i_RESET;
logic i_in;
logic counterClock;
logic[(N - 1):0] o_count;
logic o_ERROR;
modport DetectorInterface
(input i_RESET,
input i_in,
output counterClock,
output o_ERROR);
modport CounterInterface
(input i_RESET,
output o_count);
modport FallingsCounterInterface
(input i_RESET,
input i_in,
output o_count,
output o_ERROR);
modport StimulatorInterface
(output i_RESET,
output i_in,
input o_count);
modport MonitorInterface
(input i_RESET,
input i_in,
input counterClock,
input o_count,
input o_ERROR);
modport CommonInterface
(input i_RESET);
endinterface
I also created 2 modules:
module FallingEdge_Detector
(BusInterface.DetectorInterface interfaceDetector);
int k;
typedef enum logic[1:0] {s_NewCountCycle, s_ReadyToCount, s_EndCountCycle} stateType;
stateType currentState, nextState;
// Register logic
always_ff #(posedge interfaceDetector.i_clk, posedge interfaceDetector.i_RESET)
begin
if (interfaceDetector.i_RESET) currentState <= s_NewCountCycle;
else if (interfaceDetector.i_clk) currentState <= nextState;
end
// Next State logic
always_comb
begin
case (currentState)
s_NewCountCycle:
begin
if (interfaceDetector.i_in) nextState <= s_ReadyToCount;
else nextState <= s_NewCountCycle;
end
s_ReadyToCount:
begin
if (interfaceDetector.i_in) nextState <= s_ReadyToCount;
else nextState <= s_EndCountCycle;
end
s_EndCountCycle:
begin
if (interfaceDetector.i_in) nextState <= s_ReadyToCount;
else nextState <= s_NewCountCycle;
end
endcase
end
// Output logic
assign interfaceDetector.counterClock = (currentState == s_EndCountCycle);
assign interfaceDetector.o_ERROR = (currentState != s_EndCountCycle) &
(interfaceDetector.counterClock == 1'b1);
endmodule
module Counter
#(parameter N = 3) (BusInterface.CounterInterface interfaceCounter);
int k;
// Register logic
always_ff #(posedge interfaceCounter.i_clk, posedge interfaceCounter.i_RESET)
begin
if (interfaceCounter.i_RESET) k <= 0;
else if (interfaceCounter.i_clk) k <= k + 1;
end
// Output logic
assign interfaceCounter.o_count = k[(N - 1):0];
endmodule
The problem is that I cannot create a top-level module:
module FallingsCounter
#(parameter N = 3) (BusInterface.FallingsCounterInterface interfaceFallingsCounter);
/*
(input logic i_clk, i_RESET,
input logic i_in,
output logic[(N - 1):0] o_count,
output logic o_ERROR);
*/
logic counterClock;
FallingEdge_Detector Detector
(interfaceFallingsCounter.i_clk, interfaceFallingsCounter.i_RESET,
interfaceFallingsCounter.i_in,
counterClock,
interfaceFallingsCounter.o_ERROR);
Counter Counter
(counterClock, interfaceFallingsCounter.i_RESET,
interfaceFallingsCounter.o_count);
endmodule
When I try to make this in that way, i get the next errors:
Error (10285): Verilog HDL Module Instantiation error at FallingsCounter.sv(28): instance "Detector" specifies 5 actual port connections but module "FallingEdge_Detector" only expects 1
Error (10978): SystemVerilog error at FallingsCounter.sv(25): unknown type and interface type are not equivalent - equivalent types must have same number of bits
Error (10698): SystemVerilog error at FallingsCounter.sv(25): can't connect expression with incompatible data type to formal "interfaceDetector"
Error (10181): Verilog HDL Module Instantiation error at FallingsCounter.sv(25): too many ports used in Module Instantiation
Error (10181): Verilog HDL Module Instantiation error at FallingsCounter.sv(26): too many ports used in Module Instantiation
Error (10181): Verilog HDL Module Instantiation error at FallingsCounter.sv(27): too many ports used in Module Instantiation
Error (10181): Verilog HDL Module Instantiation error at FallingsCounter.sv(28): too many ports used in Module Instantiation
So, I have the question: how to create the top level module using interface?
You can't use modports in your top-level module port declaration unless they are going to be connected to the same modport in the lower level modules.
Modports are like sub-types passed through an interface port. They define access rights to a bundle of signals, and you cannot change the modport type one it is passed into the module.
What you can do is pass the full interface (without modports) through the top-level module

Declare vector ports without specifying their size in Verilog

When declaring a module in Verilog (2001?), is it possible to tell that some ports are vectors without indicating their size? The goal here is to handle vector ports of any size, without having to specify the sizes through parameters.
I know I can write something like what follows in Verilog, but I'd like to know if there's a way to get rid of the extra WIDTH_DATA parameter:
module my_module
#(
parameter WIDTH_DATA = 48
)
(
input Clk, En,
input [WIDTH_DATA-1:0] Data_in,
output Ready,
output reg [WIDTH_DATA-1:0] Data_out
);
This is possible in VHDL, using a declaration like that:
entity my_module is
port (
Clk : in std_ulogic;
En : in std_ulogic;
Data_in : in std_ulogic_vector;
Ready : out std_ulogic;
Data_out : out std_ulogic_vector
);
end entity;
The module implementation can then know the size of Data_in at compile time using Data_in'length (same for Data_out).
This is not possible in Verilog.
You can do something close to what you want in SystemVerilog using the interface construct. You can parameterize an interface, and connect that interface (or set of interfaces) to my_module.
interface my_intf #(int WIDTH);
logic [WIDTH-1:0] data;
endinterface
module my_module(input clk, en,
my_intf in, out,
output ready);
// $bits(in.data) - gives you the WIDTH
// typedef type(out.data) out_type // local typedef
endmodule
module top;
my_intf #(8) I1;
my_intf #(16) I2;
bit clk, en, ready;
my_module M1 (.clk,.en, .in(I1), .out(I2), .ready);
endmodule

Verilog calling a multiplexer module in another module

I am trying to use Verilog to build a module which near the end calls a multiplexer (already designed and in the file). However, when I call the multiplexer and assign its inputs, I get an error saying:
Syntax error near "[".
The line it references is this:
.MUX_in[0](inv_ymux),
I'm trying to call the first bit of my 4 bit MUX_in (which is specified in my multiplexer module). Am I doing this correctly? how should I go about assigning it?
module multiplexer(MUX_in, S_in, MUX_out);
input [3:0] MUX_in;
input [1:0] S_in;
output MUX_out;
reg MUX_out;
always # (MUX_in or S_in)begin
case(S_in)
2'b00: MUX_out = MUX_in[0];
2'b01: MUX_out = MUX_in[1];
2'b10: MUX_out = MUX_in[2];
2'b11: MUX_out = MUX_in[3];
endcase
end
endmodule
Above is the module for the multiplexer.
One way to do it is to concatenate other signals in your port connections. The following connects inv_ymux to MUX_in[0]:
mux i0 (
.MUX_in ({3'b000, inv_ymux}),
// other port connections
);

Resources