Will 'typedef logic' generate a register when using it instead of a 'wire', in SystemVerilog? - verilog

Having the following SystemVerilog code:
module my_module(
input wire [31:0] my_net
);
...
endmodule
...
...
wire [31:0] my_net;
assign my_net = ...;
my_module m(my_net);
What are the consequences (at synthesis time) of change the my_net declaration by:
typedef logic [31:0] my_net_t; // This is actually no longer a net, but a variable.
module my_module(
input my_net_t my_net
);
...
endmodule
my_module m(my_net);
...
...
wire [31:0] my_net;
assign my_net = ...;
my_module m(my_net);
I mean, logic is a variable, not a net, therefore, will the synthesizer generate a register for my_net?

Incorrect. logic is a data type that can be applied to a variable or net.
input wire [31:0] my_net
input my_net_t my_net
are implicitly the same as
input wire logic [31:0] my_net
input wire my_net_t my_net
When internal to a module
logic v;
wire w;
are implicitly
var logic v;
wire logic W;
But regardless of my_net being a variable or net, a continuous assignment to my_net does not create a register.

No.
Continuous assignment using
assign my_net = RHS;
does not infer registers.

Related

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.

"Target of concurrent assignment or output port connection should be a net type"

I'm running into the following errors when trying to synthesize my code to run on my Anvyl board:
ERROR:HDLCompiler:329 - "C:/Users/Chase/Desktop/Code
Templates/final_bcd_counter.v" Line 25: Target <digit_1> of concurrent assignment or output port connection should be a net type.
ERROR:HDLCompiler:329 - "C:/Users/Chase/Desktop/Code
Templates/final_bcd_counter.v" Line 26: Target <digit_2> of concurrent assignment or output port connection should be a net type.
I was provided with a Lab_board.v file to drive the board which is as follows:
`timescale 1ns / 1ps
module lab_board(LED, SW, CLK);
output [7:0] LED;
input [7:0] SW;
input CLK;
bcd_count_7 counter(
.max_count(SW[6:0]),
.CLK(CLK),
.run(SW[7]),
.digit_l(LED[3:0]),
.digit_2(LED[7:4])
);
endmodule
The code that the errors are throw in is my final_bcd_counter.v file which is the main driver of the program that passes all the needed values to the board. It is as follows:
// This is the top module for the programmable BCD counter.
// It implements a programmable 7-bit counter and a binary-
// to-bcd converter that can output two digits.
module bcd_count_7(max_count, CLK, run, digit_1, digit_2);
input [6:0] max_count;
input CLK, run;
output reg [3:0] digit_1;
output reg [3:0] digit_2;
//Wires and registers for interconnect if needed
wire [6:0] countin_out;
// Programmable 7-bit counter module
prog_count_7 counter(.max_count(max_count),
.run(run),
.CLK(CLK),
.count_out(countin_out));
// Binary-to-BCD Converter for converting count_out to BCD
binary_bcd_2 bcd_converter(.bin_in(countin_out),
.digit_1(digit_1),
.digit_2(digit_2));
endmodule
I've tried changing the type of digit_1 and digit_2 with no avail. Could the solution be creating wires that connect to the lab board instead of passing output registers, if so, what would that look like?
Any help is appreciated. I can provide the code of the other modules in the program if needed.
Thanks!
You've declared digit_1/2 as a variable and it needs to be a net in Verilog I'm assuming those are output ports from your binary_bcd_2 module. SystemVerilog does not have this restriction.
Simply remove the reg keyword from the port declaration. I've added wire for clarity, but that is what is implicit
module bcd_count_7(
input wire [6:0] max_count,
input wire CLK, run,
output wire [3:0] digit_1,
output wire [3:0] digit_2
);

Leaving some bits in the port vector disconnected. Verilog module instantiation

Lets say I have a Verilog module with bit vector ports. How do I
instantiate it with some bits left unconnected?
I tried something like this but it didn't work:
module sub (in,out)
input [3:0] in;
output [3:0] out;
endmodule
module top;
wire [1:0] a1;
wire [1:0] c1;
sub Sub1(
.in[2:1](a1[1:0]),
.out[2:1](c1[1:0])
);
endomdule
It would be much easier to just declare signals of the correct size and use a continuous assignment
module top;
wire [1:0] a1;
wire [1:0] c1;
wire [3:0] pin;
wire [3:0] pout;
assign pin[2:1] = a1;
assign c1 = pout[2:1];
sub Sub1(
.in(pin),
.out(pout)
);
endomdule
In general, it is not a good idea to leave input ports floating. You could use a concatenation in the assignment, or directly in the port connection.
sub Sub1(
.in({1'b0,a1,1'b0}),
.out({pout[3],c1,pout[0]})
);
SystemVerilog has a net aliasing construct that makes thing even simpler
module top;
wire [3:0] pin;
wire [3:0] pout;
alias pin[2:1] = a1;
alias pout[2:1] = c1;
sub Sub1(
.in(pin),
.out(pout)
);
endomdule
Found LRM reference on why you cannot connect parts of ports.
LRM 1800-2012 Section 23.3.2.2 Connecting module instance ports by name:
The port_name shall be the name specified in the module declaration. The port name cannot be a bit-select, a part-select, or a concatenation of ports.
you cannot connect/disconnect parts of a port. You can do it with the whole port though. so, in your case you nedd to split your port in several parts, something like the following:
module sub (in1, in2, out1, out2);
input [2:1] in1;
input [1:0] in2;
output [2:1] out1;
output [1:0] out2;
endmodule
module top;
wire [1:0] a1;
wire [1:0] c1;
sub Sub1(
.in1(a1[1:0]),
.in2(),
.out1(c1[1:0]),
.out2()
);
endmodule
My code connect 4-bits to module's 8-bit outputs, upper/lower even middle part.
It does work, but what the hell is the 's'(or anything)?
It works in both Quartus Prime 18.0pro and Lattice Diamond 3.10(Symplify Pro).
module dff8
(
input clk,
input [7:0] a,
output reg [7:0] b
);
always # (posedge clk) begin
b <= a;
end
endmodule
module top
(
input clk,
input [7:0] x,
output [3:0] y,
output [3:0] z
);
dff8 u0 (.clk(clk), .a(x), .b({y,s,s,s,s}));
dff8 u1 (.clk(clk), .a(x), .b({s,s,s,s,z}));
endmodule

localparam after wire declaration

For a very strange reason (scripts we use) I need to be able to declare a localparam AFTER I declare wires and regs in a module:
module blah (clk, rst, in, out);
input clk;
input rst;
input [2:0] in;
output [3:0] out;
wire res;
localparam NUMBER=5;
...
is this legal verilog code? I would also appreciate a link to the relevant seciton in the documentation. Thanks!
This is valid Verilog (2001). Verilog 2001 saw the introduction of localparam, for all versions it is still syntactically valid to use parameter in this context. localparam indicates that it can not be overridden.
Usage can be seen in section 23.10 Overriding module parameters of SystemVerilog IEEE Std 1800-2012.
From IEEE 1800-2012:
For example:
module generic_fifo
#(MSB=3, LSB=0) // parameter port list parameters
(input wire [MSB:LSB] in,
input wire clk, read, write, reset,
output logic [MSB:LSB] out,
output logic full, empty );
parameter DEPTH=4; // module item parameter
localparam FIFO_MSB = DEPTH*MSB;
localparam FIFO_LSB = LSB;
// These constants are local, and cannot be overridden.
// They can be affected by altering the value parameters above
logic [FIFO_MSB:FIFO_LSB] fifo;
logic [LOG2(DEPTH):0] depth;
always #(posedge clk or posedge reset) begin
casez ({read,write,reset})
// implementation of fifo
endcase
end
endmodule
Exactly. As per the Verilog IEEE Std 1364-2001, you can use localparam in your Verilog code. It can be declared after wire declaration, no problem for that.

Why are output nets also required to be redeclared as either 'wire' or 'reg'?

Why do we have to take the same variable name of an output and also wire for getting the value? eg:
module TEST(INP1,INP2,CIN,COUT,SUM);
input [31:0] INP1;
input [31:0] INP2;
output [31:0] SUM;
input CIN;
output COUT;
wire [31:0] SUM;// Again redefined
wire COUT; // Again Redefined
assign {COUT,SUM} = INP1 + INP2 + CIN ;
Example for getting the Carry-out and the Sum of two numbers and Carry-In taken as the input.
Verilog 1995 did require the port direction to be listed after. Output wire types were implicit and regs could be declared inline with direction.
module TEST(A,B,C,D);
input [31:0] A;
input [31:0] B;
output [31:0] C;
output D;
reg D;
could be written as:
module TEST(A,B,C,D);
input [31:0] A;
input [31:0] B;
output [31:0] C;
output reg D; //Only declared twice
Since Verilog 2001 the extra definition is no longer required and they can be declared inline (ANSI-Style).
module TEST(
input [31:0] A,
input [31:0] B,
output [31:0] C,
output reg D // Declared Once
);
From SystemVerilog (2009) we have the logic type, you no longer have to switch between reg and wire types. The only requirement is that if you need to tri-state use wire or tri.
module TEST(
input [31:0] A,
input [31:0] B,
output logic [31:0] C,
output logic D
);
My understanding of the original requirement for having reg and wire types was for simulation speed or ease of simulator design. The value of a wire is evaluated every simulation delta cycle while a reg is only evaluated when triggered by the sensitivity list.
It is not necessary to declare an output also as a wire. Furthermore, you can avoid duplicating the port list by using ANSI-stlye port declarations:
module TEST (
input [31:0] INP1,
input [31:0] INP2,
output [31:0] SUM,
input CIN,
output COUT
);
assign {COUT,SUM} = INP1 + INP2 + CIN ;
endmodule
In your example, you do not need to declare outputs as reg. But, if you need to for another circuit, you can declare the type on the same line, such as:
output reg [31:0] Q;
Because just declaring a net as output doesn't describe if it is a reg type or a wire type.
An output can either be driven by a wire or reg, you have to tell it what type the driver is going to be.

Resources