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

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.

Related

Separating SystemVerilog nets before applying force

I want to force a signal down a hierarchy from my testbench. The modules are automatically created from schematics (changing design is not possible), and they are mostly based on wire type.
A code example can be found on EDA play ground.
//top level module
module dummy1(input A, output B);
dummy2 u_dummy2(A, B);
always #(A)
begin
assert (A == 1'b0) else $error("Force reached this level");
end
endmodule
module dummy2(input A, output B);
dummy3 u_dummy3(A, B);
endmodule
module dummy3(input A, output B);
assign B = A;
endmodule
If I force A in dummy3, it will change A in dummy2 and dummy1 which is something expected. I want to know if there is a way to separate A in dummy3 from A in dummy2 so that force is not applied to top level module.
module dummy_tb;
logic A, B;
dummy1 u_dummy1(A, B);
initial
begin
A = 0;
$display("step0: A=%b B=%b", u_dummy1.A,u_dummy1.B);
#1;
//force A1 to 1
force u_dummy1.u_dummy2.u_dummy3.A = 1'b1;
#1;
$display("step1: A=%b B=%b", u_dummy1.A,u_dummy1.B);
release u_dummy1.u_dummy2.u_dummy3.A;
#1;
$display("step2: A=%b B=%b", u_dummy1.A,u_dummy1.B);
//TODO: find something to separate A in u_dummy3 from A in u_dummy2, then force
end
endmodule
I can't think of a way to "separate" the nets without a change to the Verilog source code for the design modules, but you could achieve a similar effect by also forcing A in dummy2:
#1;
//force A1 to 1
force u_dummy1.u_dummy2.u_dummy3.A = 1'b1;
force u_dummy1.u_dummy2.A = 1'b0; // <-------- add this line
#1;
edaplayground
I think that this behavior results from a couple of quotes from the standard:
23.3.3 Port connection rules:
Each port connection shall be a continuous assignment of source to sink, where one connected item shall be
a signal source and the other shall be a signal sink. The assignment shall be a continuous assignment from
source to sink for input or output ports.
This makes dummy3.A the sink and dummy_tb.A the source.
10.6.2 The force and release procedural statements: A force procedural statement on a net shall override all drivers of the net—gate outputs, module outputs,
and continuous assignments—until a release procedural statement is executed on the net. When released,
the net shall immediately be assigned the value determined by the drivers of the net.
This makes dummy_tb.A a driver to the dummy3.A; So, basically verilog is forced to force all input ports on the way.
As a result, there is no way to do what you want without either forcing the port in the above level of hierarchy to a different value or to force outputs of continuous assignments in the low level module (force dummy3.B).

Connect different port width

Suppose my module has a 8-bit input and 8-bit output
module MyModule (input logic [7:0] in, output logic [7:0] out);
...
endmodule : MyModule
If I want to connect a 1-bit input in and leave the other bits as zero, the following works:
MyModule (.in({7'b0, a}), .out(b))
How can I do the same if I want a 1-bit output, ignoring the other bits? Something like this
MyModule (.in(a), .out({7'b0, b}))
vcs says its invalid, and connecting b directly gives a warning. I'd ideally like a solution that doesn't throw warnings.
Here's what I've thought of:
Use .out(b) and use b[0] for bit
Create unused logic variable unused and use .out({unused, b}) which does work
Use assign statment (I'd like to avoid this)
Any solution better than these?
You could use the streaming operator:
MyModule M (.in(a), .out({<<{b}}));
But I think your first idea is the most straightforward.
You might also use parameterized modules:
module MyModule #(IN_WDT = 8, OUT_WDT = 8)
(input logic[IN_WDT-1:0] in, output logic [OUT_WDT -1 : 0] out);
...
MyModule #(8,1) M1(a8, b1);
or
MyModule #(.OUT_WDT(1)) M1(.in(a8), .out(b1));

Multidriven nets: Synthesis ok, Simulation fails

I have a fundamental understanding problem with System Verilog. I am working on a processor design, where some bus systems should be shared between several processing units (System Verilog modules). With an arbiter only one module at a time should be active, driving the bus, while all other are high impedance.
I got rid of the multidriven nets warnings in Vivado during synthesis and there are not anymore any bus conflicts, but the simulator gives a warning, that the bus signals 'might' be multidriven. I made a tiny example code and I would expect to get for 'data' '11', when 'select' is '10'?
While simulation stops at all in Vivado, it works with Cadence simulator, but with wrong results - screenshot simulation
testbench.sv
`timescale 1ns / 1ps
module testbench_top();
logic [1:0] select;
logic [1:0] data;
top top_inst(.*);
initial
begin
select = 0;
#2 select = 1;
#2 select = 2;
#2 select = 0;;
end
initial
begin
$monitor("t=%3d s=%b,d=%b\n",$time,select,data);
end
endmodule
design.sv
`timescale 1ns / 1ps
module top
(
input logic [1:0] select,
output logic [1:0] data
);
driver_1 driver_1_inst(.*);
driver_2 driver_2_inst(.*);
endmodule
module driver_1
(
input logic [1:0] select,
output logic [1:0] data
);
always_comb
begin
if (select == 2'b10)
data = 2'b11;
else
data = 'z;
end
endmodule
module driver_2
(
input logic [1:0] select,
output logic [1:0] data
);
always_comb
begin
if (select == 2'b01)
data = 2'b01;
else
data = 'z;
end
endmodule
I'm assuming you expect the value of data signal the top module, which is driven by the two outputs of your driver modules, to be resolved (e.g. when one drive 'z, the other gets the bus.
This will happen if you declare the top.data signal as output wire logic [1:0] data.
Section 23.2.2.3 Rules for determining port kind, data type, and direction of the IEEE 1800-2012 standard states that
For output ports, the default port kind depends on how the data type
is specified: — If the data type is omitted or declared with the
implicit_data_type syntax, the port kind shall default to a net of
default net type. — If the data type is declared with the explicit
data_type syntax, the port kind shall default to variable.
In your case, the second clause applies, since you declared data as output logic[1:0], meaning that it was interpreted as a variable and not a net. Multiple values on variables aren't resolved (and in some tools are also illegal).

How do I sign extend in SystemVerilog?

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

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