This question already has answers here:
What is the difference between reg and wire in a verilog module?
(3 answers)
Closed 2 years ago.
I have some code in VHDL I am trying to convert to Verilog.
The VHDL code works fine
library ieee;
use ieee.std_logic_1164.all;
entity find_errors is port(
a: bit_vector(0 to 3);
b: out std_logic_vector(3 downto 0);
c: in bit_vector(5 downto 0));
end find_errors;
architecture not_good of find_errors is
begin
my_label: process (a,c)
begin
if c = "111111" then
b <= To_StdLogicVector(a);
else
b <= "0101";
end if;
end process;
end not_good;
The Verilog code I have, gets errors "Illegal reference to net "bw"."
and
Register is illegal in left-hand side of continuous assignment
module find_errors(
input [3:0]a,
output [3:0]b,
input [5:0]c
);
wire [0:3]aw;
wire [3:0]bw;
reg [5:0]creg;
assign aw = a;
assign b = bw;
assign creg = c;
always #(a,c)
begin
if (creg == 4'b1111)
bw <= aw;
else
bw <= 4'b0101;
end
endmodule
It looks pretty close but there are a few things that are problems/errors that need to be fixed, see inline comments in fixed code:
module find_errors(
input wire [3:0] a, // Better to be explicit about the types even if
// its not strictly necessary
output reg [3:0] b, // As mentioned in the comments, the error youre
// seeing is because b is a net type by default; when
// describing logic in any always block, you need to
// use variable types, like reg or logic (for
// SystemVerilog); see the comment for a thread
// describing the difference
input wire [5:0] c);
// You dont really need any local signals as the logic is pretty simple
always #(*) begin // Always use either always #(*), assign or
// always_comb (if using SystemVerilog) for combinational logic
if (c == 6'b111111)
b = a; // For combinational logic, use blocking assignment ("=")
// instead of non-blocking assignment ("<="), NBA is used for
// registers/sequential logic
else
b = 4'b0101;
end
endmodule
aw and creg are unnecessary, and bw needs to be declared as reg.
module find_errors(
input [3:0] a,
output [3:0] b,
input [5:0] c
);
reg [3:0] bw;
assign b = bw;
always #(a,c)
begin
if (c == 4'b1111)
bw <= a;
else
bw <= 4'b0101;
end
endmodule
Since there is no sequential logic, you don't even need an always block:
module find_errors(
input [3:0] a,
output [3:0] b,
input [5:0] c
);
assign b = (c == 4'b1111) ? a : 4'b0101;
endmodule
Related
I am not sure, what exactly the error is. I think, my indexing in the for-loop is not Verilog-compatible, but I might be wrong.
Is it allowed to index like this (a[(4*i)+3:4*i]) in a for-loop just like in C/C++?
Here is a piece of my code, so the for-loop would make more sense
module testing(
input [399:0] a, b,
input cin,
output reg cout,
output reg [399:0] sum );
// bcd needs 4 bits + 1-bit carry --> 5 bits [4:0]
reg [4:0] temp_1;
always #(*) begin
for (int i = 0; i < 100; i++) begin
if (i == 0) begin // taking care of cin so the rest of the loop works smoothly
temp_1[4:0] = a[3:0] + b[3:0] + cin;
sum[3:0] = temp_1[3:0];
cout = temp_1[4];
end
else begin
temp_1[4:0] = a[(4*i)+3:4*i] + b[(4*i)+3:4*i] + cout;
sum[(4*i)+3:4*i] = temp_1[3:0];
cout = temp_1[4];
end
end
end
endmodule
This might seem obvious. I'm doing the exercises from:
HDLBits and got stuck on this one in particular for a long time (This solution isn't the one intended for the exercise).
Error messages Quartus:
Error (10734): Verilog HDL error at testing.v(46): i is not a constant File: ../testing.v Line: 46
Error (10734): Verilog HDL error at testing.v(47): i is not a constant File: ../testing.v Line: 47
But I tried the same way in indexing and got the same error
The error appears because Verilog does not allow variables at both indices of a part select (bus slice indexes).
The most dynamic thing that can be done involves the indexed part select.
Here is a related but not duplicate What is `+:` and `-:`? SO question.
Variations of this question are common on SO and other programmable logic design forums.
I took your example and used the -: operator rather than the : and changed the RHS of this to a constant. This version compiles.
module testing(
input [399:0] a, b,
input cin,
output reg cout,
output reg [399:0] sum );
// bcd needs 4 bits + 1-bit carry --> 5 bits [4:0]
reg [4:0] temp_1;
always #(*) begin
for (int i = 0; i < 100; i++) begin
if (i == 0) begin // taking care of cin so the rest of the loop works smoothly
temp_1[4:0] = a[3:0] + b[3:0] + cin;
sum[3:0] = temp_1[3:0];
cout = temp_1[4];
end
else begin
temp_1[4:0] = a[(4*i)+3-:4] + b[(4*i)+3-:4] + cout;
sum[(4*i)+3-:4] = temp_1[3:0];
cout = temp_1[4];
end
end
end
endmodule
The code will not behave as you wanted it to using the indexed part select.
You can use other operators that are more dynamic to create the behavior you need.
For example shifting, and masking.
Recommend you research what others have done, then ask again if it still is not clear.
I am trying to make a 4-bit adder and test it. I decided to use wait to determine when the adder circuit is done by checking when my sum and carry_out are >= 0. The inputs for the circuit are given as command line arguments. I am constructing my 4-bit adder using my full adder which I was able test successfully using this method.
full_adder.v
//Behavioral Verilog
module full_adder (input a, input b, input cin, output s, output cout);
assign s = a ^ b ^ cin;
assign cout = (a && b) || (a && cin) || (b && cin);
endmodule
4_bit_adder.v
module four_bit_adder(input [0:3] x, input [0:3] y, input carry_in, output [0:3] sum, output carry_out);
full_adder add1(x[0], y[0], sum[0], carry_in, carry1);
full_adder add2(x[1], y[1], sum[1], carry1, carry2);
full_adder add3(x[2], y[2], sum[2], carry2, carry3);
full_adder add4(x[3], y[3], sum[3], carry3, carry_out);
endmodule
4_bit_adder_tester.v
module four_bit_adder_test;
reg [0:3]x;
reg [0:3]y;
reg carry_in;
wire sum;
wire carry_out;
four_bit_adder adder(x, y, carry_in, sum, carry_out);
initial begin
$display("Here");
if (!$value$plusargs("x=%d", x)) begin
$display("ERROR: please specify +x=<value> to start.");
$finish;
end
if (!$value$plusargs("y=%d", y)) begin
$display("ERROR: please specify +y=<value> to start.");
$finish;
end
if (!$value$plusargs("carry_in=%d", carry_in)) begin
$display("ERROR: please specify +carry_in=<value> to start.");
$finish;
end
wait(sum >= 0 && carry_out>= 0) $display("sum=%d, carry_out=%d", sum, carry_out);
$finish;
end
endmodule
The problem is that carry_out remains at x so the sum and carry_out variables never get printed. I tried printing out the value of carry_out, and I think the logic in my circuits should work. Is this a valid way of testing my Verilog code?
That not a recommended way of testing because you get no output if the data is incorrect.
A better way is checking if the output matches what you expect
$display("Expected %b + %b + %b = %b", x,y,carry_in, {x+y+carry_in});
#1 // let output propagate
if ( {carry_out,sum} == x + y + carry_in )
$display("passed sum=%b, carry_out=%b", sum, carry_out);
else
$display("failed sum=%b, carry_out=%b", sum, carry_out);
end
This gives you a better picture of what is going wrong. You sill see that the output is z which means you have not connected thing up properly.
Also, get rid of all warning messages.
You need to pay close attention to your simulator log files because there should be warning messages which will point out the problem in your code. For example, on EDA Playground, I see this warning:
Warning-[PCWM-W] Port connection width mismatch
testbench.sv, 21
"four_bit_adder adder(x, y, carry_in, sum, carry_out);"
The following 1-bit expression is connected to 4-bit port "sum" of module
"four_bit_adder", instance "adder".
Expression: sum
Instantiated module defined at: "testbench.sv", 8
The warning goes away when you change:
wire sum;
to:
wire [0:3] sum;
You can use wait, but you should account for the situation when the expression is never true. In this case, you could add a testbench timeout which ends the simulation cleanly after a reasonable amount of time. For example, add a second initial block in four_bit_adder_test:
initial begin
#50 $display("Error: timeout");
$finish;
end
My college teacher asked for me to implement a Johnson Counter and it's test bench, with an width<=32 (he calls it an N parameter), and the implementation has to use generate/for structures. Although I had learned a little about Johnson Counter, I don't know how to use generate in this case, and I had some errors when I tried to run the test bench. Here is my implementation so far:
module johnsonCounter #(parameter N = 32)
(
input clk,
input rstn,
output reg [N-1:0] out
);
always # (posedge clk) begin
if (!rstn)
out <= 1;
else begin
out[N-1] <= ~out[0];
generate
for (int i = 0; i < N-1; i=i+1) begin
out[i] <= out[i+1];
end
endgenerate
end
end
endmodule
Here is the test bench:
module tb;
parameter N = 32;
reg clk;
reg rstn;
wire [N-1:0] out;
johnsonCounter u0 (.clk (clk),
.rstn (rstn),
.out (out));
always #10 clk = ~clk;
initial begin
{clk, rstn} <= 0;
$monitor ("T=%0t out=%b", $time, out);
repeat (2) #(posedge clk);
rstn <= 1;
repeat (15) #(posedge clk);
$finish;
end
initial begin
$dumpvars;
$dumpfile("dump.vcd");
end
endmodule
These are the errors:
ERROR VCP2000 "Syntax error. Unexpected token: generate[_GENERATE]. This is a Verilog keyword since IEEE Std 1364-2001 and cannot be used as an identifier. Use -v95 argument for compilation." "design.sv" 13 7
ERROR VCP2020 "begin...end pair(s) mismatch detected. 2 <end> tokens are missing." "design.sv" 17 7
ERROR VCP2020 "module/macromodule...endmodule pair(s) mismatch detected. 1 <endmodule> tokens are missing." "design.sv" 17 7
ERROR VCP2000 "Syntax error. Unexpected token: endgenerate[_ENDGENERATE]. This is a Verilog keyword since IEEE Std 1364-2001 and cannot be used as an identifier. Use -v95 argument for compilation." "design.sv" 17 7
Any help is welcome =)
It is illegal to use generate in that way.
For your code, just a for loop is needed (without generate):
always # (posedge clk) begin
if (!rstn)
out <= 1;
else begin
out[N-1] <= ~out[0];
for (int i = 0; i < N-1; i=i+1) begin
out[i] <= out[i+1];
end
end
end
For generate syntax, refer to the IEEE Std 1800-2017, section 27. Generate constructs.
I tried implementing it using the generate construct. I am also new at this, so if anybody sees any problem or error, or could provide any suggestion to improve performance, I would appreciate it.
Regarding your question, I always use generate to instantiate several modules, I think it makes my code cleaner and easier to understand. So what I did is to define a simple D flip-flop module, which I will use to instantiate it. If you want to use generate, you have to define an iterative variable with genvar. Also, you should use generate outside an always block (I don't know if there is a situation where you could use it inside the always block). Below, you can see the code.
module ff
(
input clk,
input rstn,
input d,
output reg q,
output reg qn
);
always #(posedge clk)
begin
if(!rstn)
begin
q <= 0;
qn <= 1;
end
else
begin
q <= d;
qn <= ~d;
end
end
endmodule
module johnsonCounter #(parameter N = 4)
(
input clk,
input rstn,
output [N-1:0] out,
output [N-1:0] nout
);
genvar i;
generate
for (i = 0; i < N-1; i=i+1) begin
ff flip (.clk(clk), .rstn(rstn), .d(out[i+1]), .q(out[i]), .qn(nout[i]));
end
endgenerate
ff lastFlip (.clk(clk), .rstn(clk), .d(nout[0]), .q(out[N-1]), .qn(nout[N-1]));
endmodule
Here you have the testbench, too. One thing I changed from your code is the dumpfile line. It should go before dumpvar.
module tb;
parameter N = 4;
reg clk;
reg rstn;
wire [N-1:0] out;
johnsonCounter u0 (.clk (clk),
.rstn (rstn),
.out (out));
always #10 clk = ~clk;
initial begin
{clk, rstn} <= 0;
$monitor ("T=%0t out=%b", $time, out);
repeat (2) #(posedge clk);
rstn <= 1;
repeat (15) #(posedge clk);
$finish;
end
initial begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmodule
This code was tested using EDA Playground and it worked fine but, as I said, I am not an expert, so if anybody finds any error or have any suggestion, it is welcome.
Here's my verilog code about add and shift multiplying
when I compile and Initialze and adding the inputs and outputs to get waveforms and simulating them, I dont see any results, everything is z... what is the problem?
module multi(a, b, ans);
input [3:0] a;
input [3:0] b;
output reg [15:0] ans;
reg [15:0] aa;
reg [15:0] bb;
reg [15:0] tmp=0;
reg flag = 1'b1;
always #( a, b)
begin
aa = a;
bb = b;
while ( flag == 1'b1 )
begin
if( bb[0] == 1'b1 )
tmp = tmp + aa;
aa = aa << 1;
bb = bb >> 1;
if ( bb==0 )
flag = 1'b0;
end
ans = tmp;
end
endmodule
There are a number of things that look strange with this code.
First is that you have no clock input, but are attempting to do everything with combinatorial logic.
Second is that setting flag to 1 in the reg statement will mean that your module is only capable of doing a single multiplication. By the way, it is more normal (especially for ASIC design) to use a reset signal than use this initialisation in a reg line.
Third is that a 4 bit number times a 4 bit number will result in an 8bit answer, not 16bit.
In any case, unless you are working at very high speeds you should be able to perform a multiply in a single cycle.
Here are a couple of ways of writing this code more naturally:
Combinatorial Style
module multi(a, b, ans);
input [3:0] a;
input [3:0] b;
output reg [7:0] ans;
always #(*)
begin
ans = a * b;
end
endmodule
Clocked style
module multi(clk, a, b, ans);
input [3:0] a;
input [3:0] b;
output reg [7:0] ans;
always #(posedge clk)
begin
ans <= a * b;
end
endmodule
Your input is 4 bits wide and your assigning to a 16 bit variable, the top 12 bits are unassigned ie x.
input [3:0] a;
reg [15:0] aa;
//...
aa = a;
To assign all bits of aa try some thing like:
aa = {12'b0, a};
//{} is bit concatenation
Or to sign extend a to 16 bits, repeat the MSB 12 times using {width{value}} replication:
aa = {{12{a[3]}}, a};
the question is simple, I heared that assign out = (a>b)?a:b is wrong. is it wrong? if it is, is there another way to find MAX?
It's right if and only if out is a wire. If it's a register, then you have to do something like this:
always #* begin
if (a>b)
out = a;
else
out = b;
end
Take into account that in Verilog, a variable of type reg can infer either a wire or a latch, or a true register. It depends on how you specify the behaviour of the module that uses that reg:
Combinational (out is implemented as a wire although it's a reg)
module max (input [7:0] a,
input [7:0] b,
output reg [7:0] out);
always #* begin
if (a>b)
out = a;
else
out = b;
end
endmodule
Combinational (out is implemented as a wire and it's defined as a wire)
module max (input [7:0] a,
input [7:0] b,
output [7:0] out);
assign out = (a>b)? a : b;
endmodule
Latch (out is a reg, and it's implemented as a latch which stores the last produced result if conditions don't make it change, i.e. if a==b, which btw, may not provide a correct output in that case)
module max (input [7:0] a,
input [7:0] b,
output reg [7:0] out);
always #* begin
if (a>b)
out = a;
else if (a<b)
out = b;
end
endmodule
Register (out is implemented as a true register, clock edge triggered)
module max (input clk,
input [7:0] a,
input [7:0] b,
output reg [7:0] out);
always #(posedge clk) begin
if (a>b)
out <= a;
else if (a<=b)
out <= b;
end
endmodule
What you have there looks correct to me. There isn't really any other way to do it.
this works with 3 input values
module max(
input [7:0] v1,
input [71:0] v2,
input [7:0] v3,
output [7:0] max
);
wire [7:0] v12;
wire [7:0] v23;
assign v12 = v1>=v2 ? v1 : v2;
assign v23 = v2>=v3 ? v2 : v3;
assign m = v12>=v23 ? v12 : v23;
endmodule
You can do this by using subtractor. Using a subtractor is less area cost expensive and faster - if fpga have sub/add components or arithmetic sub/add operation support and do not have comperator components.
https://polandthoughts.blogspot.com/2020/04/the-4-bit-signed-comparator.html
Check boolean function at the end. You check only 3 bits.
Sorry for my English.