How do I sign extend in SystemVerilog? - system-verilog

Below is the code I have for my module:
module sext(input in[3:0], output out[7:0]);
always_comb
begin
if(in[3]==1'b0)
assign out = {4'b0000,in};
else
assign out = {4'b1111,in};
end
endmodule
For some reason this is not working. Instead of sign extending it is zero extending. Any ideas to why this might be the case?

I'm going to assume you meant (input [3:0] in, output [7:0] out). If that is true, then all you needed to write is
module sext(input signed [3:0] in, output signed [7:0] out);
assign out = in;
endmodule
You could also write
module sext(input [3:0] in, output [7:0] out);
assign out = 8'(signed'(in));
endmodule
And perhaps you don't even need to write this as a separate module.

Few things you need to take care is,
you haven't declared a data type for in and out, so by default they are wire and wire can't be used at LHS inside procedural block. Refer Section 6.5 Nets and variables (SV LRM 1800-2012). So either use a continuous assignment or declare it as a variable (i.e. reg/logic etc.).
The assignment of unpacked array is illegal in your example, so either use packed array or follow the instructions given in Section 10.10 Unpacked array concatenation (SV LRM 1800-2012)

It is not illegal syntax but assign used inside an always block probably does not do what you think it does. Use assign for wires and do not use it inside initial or always.
You have defined your port ranges after the name, this results in 4 and 8 1-bit arrays rather than a 4 and 8 bit value.
You have used {} for concatination, but they can also be used for replication ie {4{1'b1}}.
module sext(
input [3:0] in,
output reg [7:0] out ); //ranged defined before name
//No assign in always
//concatenation with replication
always_comb begin
out = { {4{in[3]}}, in};
end
endmodule
Or :
module sext(
input [3:0] in,
output [7:0] out ); //out left as wire
assign out = { {4{in[3]}}, in};
endmodule

I have seen your code.
There are some mistake in your code that you have to take care whiling writing the code.
You have use unpacked array so your targeted elements and actual elements are not match.
ERROR : Number of elements in target expression does not match the number of
elements in source expression.
This error can solve by using packed array.So, your targeted elements and actual elements are matched.
Here is link from where you will get better understanding regarding packed and unpacked array.
LINK : [http://www.testbench.in/SV_09_ARRAYS.html][1]
2.Another thing that you have to take care is you are storing some value in out signal(variable) like assign out = {4'b0000,in};
So you have to use reg data type to sore the value.
ERROR : Non reg type is not valid on the left hand side of this assignment
When you use reg data type then you can store value in out data type.
So, your problem is solved.
Here I also provide code which will run fine.
module sext(input [3:0]in, output reg [7:0]out);
always_comb
begin
if(in[3]==1'b0)
assign out = {4'b0000,in};
else
assign out = {4'b1111,in};
end
endmodule

Related

I can't compile a .sv file (SystemVerilog)

I'm learning SystemVerilog for the university. I installed the extensions in Visual Studio Code for syntax highlighting: SystemVerilog, Verilog-HDL/SystemVerilog/Bluespec SystemVerilog (Names of extensions).
I installed the compiler Icarus Verilog and inserted the address in the environment variables (PATH).
So I copied this code:
module adder
(s, b, c_in, sum, c_out);
input logic [7:0] a;
input logic [7:0] b;
input logic c_in;
output logic [7:0] sum;
output logic c_out;
logic [8:0] result;
assign result = a + b + c_in;
assign sum = result [7:0];
assign c_out = result[8];
endmodule: adder
And tried to run it, but it gave me this error:
Module end labels require SystemVerilog.
I even tried to compile from the cmd with the same result.
A thing that I noticed is that when I do the same thing with a .v file (Verilog), it works.
I get a compile error in your port list. Change:
(s, b, c_in, sum, c_out);
to:
(a, b, c_in, sum, c_out);
You didn't declare a in the list, and you use a in the code. s is not in the code.
After that change, your code is legal SystemVerilog syntax, and it compiles without errors on multiple simulators on edaplayground.
I did get different compile errors from yours with Icarus Verilog 0.10.0 on edaplayground. Perhaps you are compiling with a different version. Keep in mind that iverilog does not support all SV features yet.
If the module label is still causing problems for you, you can simply remove it because it is optional. Change:
endmodule: adder
to:
endmodule
Regarding the file extensions (.v and .sv), some compilers will automatically enable SV features when you use .sv; perhaps some even require .sv. Since your code uses an SV keyword (logic), you must have SV features enabled to compile.
Here is a version of your code that does not rely on SV features:
module adder
(a, b, c_in, sum, c_out);
input [7:0] a;
input [7:0] b;
input c_in;
output [7:0] sum;
output c_out;
wire [8:0] result;
assign result = a + b + c_in;
assign sum = result [7:0];
assign c_out = result[8];
endmodule
Using logic in the port declarations is optional, and you can declare result as a wire.

How to use a parameter to add or remove a signal from a system verilog interface and modport

Here is a snippet of some interface code that has some parameterized sizes to it. The fourth parameter, HAS_BURST is something I have experimented with, but it has only resulted in compilation errors.
Effectively I am looking for a way to ADD/REMOVE a signal from a interface based on parameter. Is there a way to have a generic interface with removable signals?
interface axi_if
#(parameter ID_WIDTH = 4,
ADDR_WIDTH = 40,
DATA_WIDTH = 64,
HAS_BURST = 0)
();
logic aw_ready;
logic aw_valid;
logic [ID_WIDTH-1:0] aw_bits_id;
logic [ADDR_WIDTH-1:0] aw_bits_addr;
logic [7:0] aw_bits_len;
logic [2:0] aw_bits_size;
generate
if (HAS_BURST)
logic [1:0] aw_bits_burst;
endgenerate
logic [2:0] aw_bits_size;
modport slave (
output aw_ready,
input aw_valid,
input aw_bits_id,
input aw_bits_addr,
input aw_bits_len,
generate
if (HAS_BURST)
input aw_bits_burst,
endgenerate
input aw_bits_size
);
modport master (
input aw_ready,
output aw_valid,
output aw_bits_id,
output aw_bits_addr,
output aw_bits_len,
generate
if (HAS_BURST)
output aw_bits_burst,
endgenerate
output aw_bits_size
);
endinterface
`endif
No, there isn't. Ports aren't valid in generate blocks. Parameters can be used to asjust the width of a port but not remove it entirely. You could use an `ifdef to compile it conditionally but that's an all-or-none solution. There can't be some instances with the signal and others without it.
Having the signal unconditionally present is fine in many situations and it's the easiest way to handle this problem. Tie any unused inputs to logic 0 and unused outputs can remain unconnected.
If neither of these options work there's no other way than to define two different interfaces. Doing this by hand quickly becomes unmaintainable. If there are two variations now you can be sure a third one will be needed soon, then a fourth, a fifth... Many chip design companies have SystemVerilog code generators which create customized modules for each instance.

verilog_mode autoreginput behavior when using assignment

I wonder if the following case is possible.
I have :
module a(
input [2:0] a_i
);
endmodule
module b ();
/*AUTOREGINPUTS*/
a u_a(/*AUTOINST*/)
endmodule
It expands to:
module b ();
/*AUTOREGINPUTS*/
reg [2:0] a_i;
a u_a(/*AUTOINST*/
.a_i(a_i))
endmodule
But if I modify adding the line assign a_i = '0;, then it does not expands AUTOREGINPUTS anymore. Is there a way to expand it even if I'm doing an assignment ?
The short answer is because when running verilog-auto to fill in /*AUTOREGINPUT*/ will exclude any signal that is already declared and by adding assign a_i = '0;, you are declaring a_i.
In Verilog, explicit variable declarations are not required and will take on the default nettype if left undeclared under certain circumstances. So, if I had the following:
module x;
assign myVar = '0;
endmodule
myVar will be implicitly declared to be a net with the default nettype (which by default is wire). You can read more in the System-Verilog LRM (IEEE1800-2009 Section 6.10). One recommendation to avoid typos generating implicitly declared variables is to change the default nettype with the `default_nettype macro to none (ie `default_nettype none on the top of every file); doing this forces all variables to be explicitly declared or the compiler/synthesizer will throw an error.
verilog-mode mode in emacs is aware of implicit declaration and, as such, will not autogenerate anything declared. Thus, when you add the assign statement, you are declaring a_i and so the autogenerator will not "redefine" a_i.
To avoid this, I can only recommend running the generator before you assign any of the variables to be autogenerated. Im not sure if it handles `default_nettype none correctly, but I would assume not.
Also note, it should be /*AUTOREGINPUT*/, not /*AUTOREGINPUTS*/, no 's' at the end.

What is difference between pass by ref and pass by val in systemverilog?

what is difference between pass by ref and pass by val in systemverilog?
I just want to know what is difference between pass by ref and pass by val in systemverilog?
I can't find any example.also expecially, what is this? Does anyone know what is this and explain?
interface xxx
...
event yyy;
event ggg;
modport io_bus ( ref yyy,
ref ggg,
....
);
endinterface
What is the purpose "ref yyy" in the modport ?
The two code blocks below summarize the difference.
value = 1;
IncreaseByOne(ref value); //pass by reference
//value will be set to 2
value = 1;
IncreaseByOne(value); //pass by value
//value will still be 1
Passing by reference means that the method which gets the parameter is able to change the variable such that the original variable is also changed. Passing by value means that a copy of the value is passed, and any change to that copy does not reflect back on the original variable.
Pass by value
In SystemVerilog, Pass by value is the default mechanism for passing arguments to subroutines. This argument passing mechanism works by copying each argument into the subroutine area. If the subroutine is automatic, then the subroutine retains a local copy of the arguments in its stack.
Pass by reference
Arguments passed by reference are not copied into the subroutine area, rather, a reference to the original argument is passed to the subroutine.
The subroutine can then access the argument data via the reference. No casting shall be permitted.
Also note, It shall be illegal to use argument passing by reference for subroutines with a lifetime of static.
Only the following shall be legal to pass by reference:
— A variable,
— A class property,
— A member of an unpacked structure, or
— An element of an unpacked array.
Nets and selects into nets shall not be passed by reference
For your question
What is the purpose "ref yyy" in the modport ?
There are some performance improvement when you use reference to an event when different events gets triggered multiple times, but it is a good practice to use only when considerable performance optimizations are required/necessary. One recommended example to use pass by reference can be found in the link
Here I've shown one way of how modport with ref event is used.
interface intf(input clk);
event out_event;
logic clk;
modport dut(input clk,ref out_event);
always #(out_event)
$display ($time,"ns"," out_event triggered");
endinterface
module dut( intf.dut d);
reg [2:0] count;
initial
count = 0;
always # (posedge d.clk)begin
count = count + 1'b1;
if ( count == 'd2)
-> d.out_event;
end
endmodule
module top (input clk);
intf int_f(.clk(clk));
dut u0(.d(int_f.dut));
endmodule
The above working example can be found in the link EDA-Playground
For more details about Pass by value refer Section 13.5.1 of SystemVerilog LRM IEEE 1800-2012 and for Pass by reference refer Section 13.5.2

Synchronous Counter

I'm trying to create a 32-bit synchronous counter using J-K flip-flops. I have a functional module for individual J-K flip-flops...
jkff(J, K, CLK, Q) where the first three are wire inputs and the last is a reg output.
I then have another functional module for the counter...
thirty_two(J, K, CLK, OUT[31:0]) where the first three are inputs and the last is output
In the thirty_two module, I instantiate many jkff modules, but I seem to be restricted to using wires as my output. Thus, OUT[31:0] is a wire instead of the desired reg I want.
Any suggestions?
A common mistake when starting out with verilog is thinking that wire & reg types have to match across hierarchy, they do not. A modules inputs are always wires and outputs can be regs or wires. Connectivity between modules are wires. The difference between usage of the two is purely down to how values are assigned or driven.
For example module thirty_two can use reg type to drive its output:
module thirty_two(
output reg [31:0] OUT
);
always #* begin
OUT = 32'bx;
end
endmodule
When instantiating thirty_two, outputs must drive wires. This make sense as the level that instantiates it can not directly change a sub modules output.
module top_level();
wire [31:0] thirty_two_out;
thirty_two thirty_two_i0 (
.OUT( thirty_two_out )
);
endmodule