Passing bus to another module via port mapping in SystemVerilog - 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. 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

Related

Passing bus array to another module via port mapping

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

Verilog : error Reference to scalar wire 'VALUE' is not a legal reg or variable lvalue

I'm stuck with this code. I don't understand why my VALUE cannot be inverted.
module PREDIV(
input wire QUARTZ,
output wire VALUE);
always # (posedge QUARTZ)
assign VALUE= ~VALUE;
endmodule
There are a few problems.
You should not use the assign keyword inside an always block.
When making a procedural assignment (those inside an always block), you should declare the signal as a reg type, not a wire. This is what your error message is referring to.
For sequential logic, you should use nonblocking assignments: <=.
Finally, a reg is initialized as unknown (X). You need a way to initialize VALUE, otherwise it will remain X. One way is to add a RESET signal.
module PREDIV(
input wire QUARTZ, input RESET,
output reg VALUE);
always # (posedge QUARTZ or posedge RESET)
if (RESET) begin
VALUE <= 0;
end else begin
VALUE <= ~VALUE;
end
endmodule
It looks like the code is using blocking assignment in the always block.
The always blocks should be using only non-blocking assignments.
The code should be something like:
always #(posedge QUARTS)
Value <= ~Value;

illegal referance to net data in my inout datatype

I am new to verilog and I am writing a code in verilog for creating a memory block capable to read and write data. it has the following code
I tried all things written in some of the answers of similar type of questions but still I am getting an error.
module memory( wr_n , rst_n ,data ,clk ,add , en);
input wire wr_n;
input wire rst_n;
input wire clk;
input wire en;
parameter size = 255;
parameter n = 7;
inout wire [n:0] data;
input wire [n:0] add;
reg [n:0] mem [size:0];
integer i;
always #( posedge clk , negedge rst_n)
begin
if(!rst_n)
begin
for( i=0; i<=size; i=i+1 )
begin
mem[i] <= 8'hff;
end
end
else
begin
if(en)
begin
if(!wr_n) //read
data <= mem[add];
else //write
mem[add] <= data;
end
else
data = 8'h z;
end
end
endmodule
here when I use continuous assignment before data I get an error like
"LHS in procedural assignment may not be a net:data"
even if I have declared it as wire.
and yeah in my test bench I have declared data as reg type because when I declare it as net it shows again the
"Illegal reference to net error".
I am not able to fix it since long time..please help me out.
The inout port 'data' is of type wire. So, it cannot be used on the left hand side of the <= expression in a procedural block (always block and initial block).
So we should use continuous assignment statements like
assign data = (wr_n == 0)? mem[add]:n{1'bz};
The same holds true when we are driving any values on the inout port form the test bench. The signal connecting to the inout port from the test bench must be of type wire. And hence it should also be written using continuous assignment statements.
assign testbench_inout_signal = (wr_n == 0)? value_to_be_written :n{1'bz};
There is a better way of using an inout port, it should be isolated from the logic to avoid conflicts while reading and writing, remember whenever you use inout ports make sure the points mentioned in the link are satisfied.
One such solution is declare a temporary variable for reading and writing and
by using continuous assignment statement assign values to bidirectional port.
Following snippet will give you some more clearance of how the error can be avoided
reg [n:0] temp; // declare a variable and try to read and write with this variable
if(!wr_n) //read
temp <= mem[add];
else //write
mem[add] <= temp;
assign data = (wr_n==0)? temp : {n{1'bz}};
Remove the else part having data = 8'h z; there cannot be two else for single if statement as per LRM.

exiting for loop inside generate statement

I am trying using infinite for loop inside generate statement. But the problem is I cannot stop it or exit it using some condition. I used "disable" and "break". Both don't work.
It shows an error :
unexpected token: 'disable'
Please help me solve this problem or suggest an alternative to it. Here is my Verilog code:
module top(a1,a3,wj,d4,d10,d2,dc,dtot);
input [11:0]a1,a3,wj;
input [3:0]d4;
input [9:0]d10;
input [1:0]d2;
input [25:0]dc;
output reg[25:0]dtot;
reg [25:0]dt,error;
reg [11:0]alpha1,alpha3;
genvar i;
generate
for (i=1;i>0;i=i+1-1)begin:test
assign a1[11:0]=alpha1[11:0];
assign a3[11:0]=alpha3[11:0];
calb_top t1(a1,a3,wj,d4,d10,d2,dc,dt,error,alpha1,alpha3);
if(error==26'b00000000000000000000000000)begin
disable test;
//break;
end
end
endgenerate
assign dtot=dt;
endmodule
Verilog generate block are used to describe physical hardware. As such, an inifinite loop in a generate block will require infinite resources.
Any for loop inside a generate statement must be of a fixed and finite size that can be determined during synthesis.
Remember that HDL is not executed sequentially, but describes connections between physical circuits. Since it appears that you only require one instance of the calb_top module, you don't require either the generate block or the for loop.
Edit:
Since you're intending to perform an iterative process, you have two options, as Greg pointed out in his comment below - you can either instantiate a fixed number of calb_top blocks (since an infinite number would require an infinite amount of space) or to re-use the same block some number of times.
Here are some samples. I've haven't sim'd or synthesized them, but they're logically correct.
N-Block solution
module top(a1,a3,wj,d4,d10,d2,dc,dtot,clock,done);
parameter NUM_BLOCKS = 10;
input [11:0]a1,a3,wj;
input [3:0]d4;
input [9:0]d10;
input [1:0]d2;
input [25:0]dc;
output [25:0]dtot;
wire [11:0] a1s [NUM_BLOCKS:0];
wire [11:0] a3s [NUM_BLOCKS:0];
wire [25:0] dt [NUM_BLOCKS-1:0];
wire [25:0] error [NUM_BLOCKS-1:0];
assign a1s[0]=a1;
assign a3s[0]=a3;
genvar i;
generate
for (i=0;i<NUM_BLOCKS;i=i+1)begin:test
calb_top t1(a1s[i],a3s[i],wj,d4,d10,d2,dc,dt[i],error[i],a1s[i+1],a3s[i+1]);
end
endgenerate
assign dtot=dt[NUM_BLOCKS-1];
endmodule
This links together a number of calb_top blocks equal to NUM_BLOCKS, then outputs the result of the final block to dtot. This doesn't do any checks on the error, so you may want to put in your own code to check error[NUM_BLOCKS-1] (the error of the final calb_top).
Single-Block solution:
module top(clock,start,a1,a3,wj,d4,d10,d2,dc,dtot);
input clock;
input start;
input [11:0]a1,a3,wj;
input [3:0]d4;
input [9:0]d10;
input [1:0]d2;
input [25:0]dc;
output reg[25:0]dtot;
wire [25:0]dt,error;
reg [11:0] a1in, a3in;
wire [11:0] alpha1,alpha3;
calb_top t1(a1in,a3in,wj,d4,d10,d2,dc,dt,error,alpha1,alpha3);
always #(posedge clock)
begin
if (start)
begin
a1in <= a1;
a3in <= a3;
end
else
begin
a1in <= alpha1;
a3in <= alpha3;
end
end
always #(posedge clock)
if (start)
dtot <= 0;
else if (error == 0)
dtot <= dt;
else
dtot <= dtot;
endmodule
Each clock cycle, we run one pass through calb_top. If start is 1, then a1 and a3 are used as inputs. Otherwise, the previous outputs alpha1 and alpha3 are used. When error is 0, then dtot is set. Note that I've added clock and start to the port list.

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