Verilog calling a multiplexer module in another module - verilog

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
);

Related

How to connect a modport interface to a module that wasn't originally declared using the modport

I have a module that I wrote originally like so:
module design_name #(
parameter AWIDTH = 32,
parameter DWIDTH = 32,
...
) (
input wire clk,
input wire rst,
input wire [AWIDTH-1:0] write_addr,
...
);
// logic, etc.
endmodule
I now, of course, want to test this block in a test bench. I want to use an interface so I have created an interface like so:
interface design_name_if #(
parameter AWIDTH = 32,
...
) (
input clk
);
logic rst;
logic [AWIDTH-1:0] write_addr;
...
modport des (
input rst,
input write_addr,
...
);
endinterface
I guess my question starts now; how do I use this interface in my test bench? I currently have:
module tb;
reg clk;
design_name_if intf (clk);
design_name dut (
.clk (intf.clk),
.rst (intf.ndm.rst),
.write_addr (intf.ndm.write_addr),
...
// I don't think the above is correct
initial begin
clk = 0; // or intf.clk = 0; ?
rst = 0;
forever #1 clk = ~clk;
#10
rst = 1;
end
endmodule
I've also tried some other simple logic, like just trying to assert certain signals and other things, but I can't even get the clk to start, nor can I ever get rst to assert when running the simulation. If it matters, the interface is declared above the tb in the same file. The module I'm testing is, probably obviously, in a different file. I can get the test bench to work without an interface by declaring all the signals as reg and wire within the test bench normally but I wanted to use an interface with tasks, functions, etc. Any help appreciated, thank you!
You were very close. Just get rid of the modport in the reference—a modport is not a scope, it is a set of access rights for a port connection or virtual interface reference.
design_name dut (
.clk (intf.clk),
.rst (intf.rst),
.write_addr (intf.write_addr),
...
There are several problems:
From a structural point of view, an interface is just a bunch of wires. The wire intf.clk is different than the wire clk. The posted code drives clk using a forever loop, but the testbench connects intf.clk to the dut which is not driven so the dut will not see any clocks (the wire that drives the dut clk input pin has no driver). This pattern is present on the signal/wire/variable rst also.
In the testbench the statment
forever #1 clk = ~clk;
statement in the middle of the initial block. This will prevent all other statements in the same initial block from executing. For example it will never execute the #10 or rst = 1 statements. The solution is to drive the clock (whatever clock you choose to use the interface or local declaration) using a different initial block or an always block.
There is no $finish to stop the test at the end of the initial stimulus block. This testbench will run the simulator in an infinite loop. The initial block needs the template:
initial
begin
<statements>
$finish;
end
so that the test does not get the simulator stuck in a loop.

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 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.

Verilog Structural description of an Edge-triggered T flip-flop with an synchronous reset (R)

I am trying to wire a Verilog Structural description of an Edge-triggered T flip-flop with an synchronous reset (R). Here is the circuit for this element:
Now assume that I have already written the behavioral description for each block in this schematic , so here is my structural description for this circuit by instantiation of each of this blocks in the circuit:
module edge_trig_flipflop_structure (
input x,y,clk,
output q,
wire a,b,c,d
);
inv u1(c,q);
mux_2x1 u2 (q,c,x,a);
inv u3(d,y);
and_2_1 u4(b,a,d);
d_flipflop u5(b,clk,q);
endmodule
Is this a good efficient code for this circuit? In other words, do I really need the two extra wires used for the inverters which are the wires c and d Or, is there another efficient way to write this code?
Edit : Here is the code for each component to know the order of ports in the declaration of each component
module mux_2x1 (
input a,
input b,
input sel,
output reg c
);
always # (*) begin
case ( sel)
1'b0: c=a;
1'b1: c=b;
default : $dispaly ("error");
endcase
end
endmodule
module d_flipflop ( input d,clk , output reg q);
always # (posedge clk ) begin
q=d;
end
endmodule
module inv(output reg b, input a);
always # (a) begin
b=~a;
end
endmodule
module and_2_1 ( output reg c,input a,b);
always #(a or b) begin
if (a==1'b1 & b==1'b1)
c= 1'b1;
else
c=1'b0;
end
endmodule
By default, Verilog does not require you to declare all signals. If signals appear in port connections, they will implicitly be 1-bit wire types.
However, it is good practice to declare all signals explicitly with wire, as you have done.
You could also change the default behavior and require explicitly declared signals using this compiler directive:
`default_nettype none
Since you are also concerned about connections, it is a good practice to make connections by name instead of connections by position. It is more verbose, but it will help avoid simple connection errors. For example:
inv u1 (.b(c), .a(q));
I got compile errors on your module header. You probably meant to code it this way:
module edge_trig_flipflop_structure (
input x,y,clk,
output q
);
wire a,b,c,d;

Why does 4-bit mux test bench code give x?

I can't put my finger on why is it not working. I ran a simulation on edaplayground, and I get an "x" in the output every time the select changes to 0. I properly get "1" when sel is "1" though.
The code:
module mux8_2(input [3:0]a,[3:0]b,sel,output [3:0]out);
assign out=(sel)?a:b;
endmodule
and the testbench:
module mux8_2_tb;
reg [3:0]A;
reg [3:0]B;
reg SEL;
wire [3:0]OUT;
mux8_2 UUT(A,B,SEL,OUT);
initial
begin
$dumpfile("dump.vcd");
$dumpvars(1);
A=4'b1; B=4'b0; SEL=1'b1;
#1 SEL=1'b0;
#1 SEL=1'b1;
#1 SEL=1'b0;
#1 SEL=1'b1;
#1 SEL=1'b0;
#1 SEL=1'b1;
#1;
end
endmodule
I can't reproduce your results; the OUT signal is always known for me.
But, I do get a compile warning:
The following 1-bit expression is connected to 4-bit port "sel" of module
"mux8_2", instance "UUT"
This can be fixed:
module mux8_2(input [3:0]a,[3:0]b, input sel,output [3:0]out);
In your code sel inherited the width from the previous signal ([3:0]b). Your code is equivalent to:
module mux8_2(input [3:0]a,[3:0]b,[3:0]sel,output [3:0]out);
Adding another input keyword before sel forces it to use the default width of 1 bit.

Resources