Can Verilog variables be given local scope to an always block? - scope

I sometimes find it useful to use blocking assignments for "local variables" inside clocked always blocks. This can help cut down on repeated code.
To avoid accidentally using the same variable in a different always block (which can be non-deterministic for simulation), I'd like to give it local scope. Is there a nice synthesizable way of doing this?
Something like:
module sum3(
input clk,
input [7:0] in1,
input [7:0] in2,
input [7:0] in3,
output reg [7:0] result,
output reg [7:0] result_p1);
begin :sum
reg [7:0] sum_temp; // local variable
always #(posedge clk) begin
sum_temp = in1 + in2 + in3;
result <= sum_temp;
result_p1 <= sum_temp + 1;
end
end
endmodule
(ModelSim seems to be okay with this, but Synplify doesn't seem to like it.)

I'm not sure of the semantics in plain Verilog, but according to the SystemVerilog LRM section 6.21:
Variable declarations shall precede any statements within a procedural block.
Therefore the following is legal syntax in SystemVerilog:
module sum3(
input clk,
input [7:0] in1,
input [7:0] in2,
input [7:0] in3,
output reg [7:0] result,
output reg [7:0] result_p1);
always #(posedge clk) begin : sum
reg [7:0] sum_temp; // local variable (scope limited to process)
sum_temp = in1 + in2 + in3;
result <= sum_temp;
result_p1 <= sum_temp + 1;
end
endmodule
Note that I have moved the variable declaration sum_temp into the process, thereby limiting the scope and removing the need for the named sum block. This compiles on Modelsim and Riviera (example on EDA Playground).
If your tool doesn't support this syntax, raise a bug!

The standard sythesizable way is to use a continuous assignment with a wire:
module sum3(
input clk,
input [7:0] in1,
input [7:0] in2,
input [7:0] in3,
output reg [7:0] result,
output reg [7:0] result_p1);
wire [7:0] sum_temp = in1 + in2 + in3;
always #(posedge clk) begin
result <= sum_temp;
result_p1 <= sum_temp + 1;
end
endmodule

Despite the common guideline, using blocking assignments inside clocked always blocks is ok, and sometime as you mentioned useful. See here: https://stackoverflow.com/a/4774450/1383356
Some tools however, may not support local variables defined inside a begin-end block.
Alternatively, you can try putting some or all of the the body of the always block in a task:
task SUM_TASK();
reg [7:0] sum_temp; // local variable
sum_temp = in1 + in2 + in3;
result <= sum_temp;
result_p1 <= sum_temp + 1;
endtask
always #(posedge clk) begin
SUM_TASK();
end
Verilog tasks can have access to global variables as well as local ones. Also, they can include non-blocking assignments.

Related

I am unable to understand the error in this code that is preventing an output to be displayed

module Calculator(out,a,b,op);
input [3:0] a,b;
input [1:0] op;
output [4:0] out;
reg [32:0] out;
initial
begin
case(op)
2'b00: out <= a+b;
2'b01: out <= a-b;
2'b10: out <= a*b;
2'b11: out <= a/b;
endcase
out = a+b;
end
endmodule
module test_Calci;
reg [3:0]a,b;
reg [1:0] op;
wire [32:0] out;
Calculator ca1 (out,a,b,op);
initial
begin
#40 a=32'b1; b=32'b1; op = 2'b00;
end
endmodule
The code is successfully compiling, but the expected output is not being displayed.
The initial block inside the Calculator module only executes once at time 0. At that time, the last statement which is executed (out = a+b) assigns out to the value X because a and b are X. out never gets assigned again.
You want out to be assigned every time any of the inputs change value. To do that, use an always block:
module Calculator(out,a,b,op);
input [3:0] a,b;
input [1:0] op;
output reg [32:0] out;
always #* begin
case(op)
2'b00: out = a+b;
2'b01: out = a-b;
2'b10: out = a*b;
2'b11: out = a/b;
endcase
end
endmodule
I made other changes to your code as well. For combinational logic, it is a good practice to use blocking assignments (=) instead of nonblocking (<=).
You should not have the assignment to out outside of the case statement since it will override the value assigned in the case.
You declare out with 2 different bit widths (5 and 33), which is a little strange. I merged them into one declaration.

Verilog reg assignment?

I'm totally new to Verilog programming and I do not understand where to initialize reg variables?
Let's have a look at the following snippets:
Edit:
Warning at synthesize
module test (
output LED0
);
reg led = 1'b1;
assign LED0 = led;
endmodule
or
module test (
output LED0
);
reg led;
initial begin
reg led <= 1'b1;
end
assign LED0 = led;
endmodule
Give me: Using initial value of led since it is never assigned at the line: reg led = 1'b1;
Are reg types only assigned in always# block?
Another example:
module fourBitCounter
(input clk,
output [3:0]counter
);
wire clk;
initial begin
reg[3:0] counter = 4'b1;
end
always# (posedge clk) begin
if(counter > 15)
counter <= 0;
else
counter <= counter + 1;
end endmodule
Here the reg has an initial value of 0 but I've set it before to 1... What's wrong? Thank you!
Are reg types only assigned in always# block?
No, reg types can be assigned in always blocks and initial blocks (plus task and function but I'll skip them in the scope of this question)
For your fourBitCounter, the reg[3:0] counter declared in the initial block creates a local variable also called counter that is only accessible within the scope of the block it was created in. You need to remove the reg[3:0] in the initial block so that the assignment get applied the the intended counter. But it will still not work because you declared counter as an inferred wire type and always/initial blocks cannot assign wires.
counter was declared as an output of a 4-bit inferred wire (output [3:0] counter is synonyms to output wire [3:0] counter). Since counter is assigned in an always block and initial block it needs to be a reg type. Therefore it should be declared as output reg [3:0] counter.
Also, you declared clk as in input and as a local wire, it cannot be both. Ports can be accessed locally, there is no reason to re-declare them as local nets.
FYI: for a 4-bit value, 15+1 equals 0 because there is nothing to store the MSB.
module fourBitCounter (
input clk,
output reg [3:0] counter // 'output reg', not 'output'
);
//wire clk; // do not do this, clk is an input
initial begin
counter = 4'b1; // no 'reg' here
end
always #(posedge clk) begin
if(counter > 15) // this will never evaluate as true with counter declared as 4-bit
counter <= 0;
else
counter <= counter + 1;
end
endmodule
For Verilog, assign statements can only be applied on net types (e.g. wire). This is legal:
module test ( output LED0 ); // LED0 is an inferred wire
assign LED0 = 1'b1;
endmodule
This is illegal:
module test ( output reg LED0 ); // Explicit reg
assign LED0 = 1'b1; // illegal, assign on a reg
endmodule
From your first code sample:
reg led; // <-- This declares one register called "led"
initial begin
reg led <= 1'b1; // <-- This declares a *separate* register called "led"
end // which is only valid in the initial block
The same issue exists in your second sample; you're declaring a separate register in the initial block. Don't use the keywords reg or wire if you're just trying to assign a value.

Verilog logical error

module ocircuit (ooutp,s0,s1 ,clk,write,raddA,raddB,wadd,wdata);
output [3:0] ooutp;
input clk, write,s0,s1;
input [2:0] raddA;
input [2:0] wadd;
input [2:0] raddB;
input [3:0] wdata;
reg [9:0] ooutp;
wire [3:0] dataA;
wire [3:0] dataB;
reg [9:0] inner;
regfile y (dataA,dataB,clk,write,raddA,raddB,wadd,wdata);
always #(posedge clk) begin
if (s0==0) begin
assign inner = dataA [3:0]*dataB [3:0];
end
else begin
assign inner = ((dataA [3:0]*dataB [3:0])+inner [9:0]);
end
//inner=inner1;
ooutp =s1?inner [9:0]:10'd0;
end
endmodule
This is the code. regfile is a simple register file. In the testbench, s0 = 0 during the first cycle and s0 = 1.
For subsequent cycles, this code should return the value of A*B+C*D by using one adder and one multiplier. In the first cycle, when c0 = 0, the answer that is saved in inner (a register) is right but in the second cycle, when c0 = 1 the answer is wrong.
Por example: A=1; B=2; C=1; D=1;
First cycle: x=A*B=2
Second cycle (C*D)+x=5
I think there is something wrong with this statement
assign inner = ((dataA [3:0]*dataB [3:0])+inner [9:0]);
Any help or hint will be appreciated.
Although assign can be used from within an always block, I think you just wanted to store a value into inner depending upon the value of s0. To do that, use non-blocking assignments ( <= ).
Also, you can directly output to ooutp instead of saving the final result in inner, avoiding a possible glitch in the multiplexer you instantiate here:
ooutp =s1?inner [9:0]:10'd0;
Which, by the way, it should be outside the always block, in an assign line:
assign ooutp = s1? inner [9:0]:10'd0;
module ocircuit (ooutp,s0,s1 ,clk,write,raddA,raddB,wadd,wdata);
output [3:0] ooutp;
input clk, write,s0,s1;
input [2:0] raddA;
input [2:0] wadd;
input [2:0] raddB;
input [3:0] wdata;
reg [9:0] ooutp;
wire [3:0] dataA;
wire [3:0] dataB;
reg [9:0] inner;
regfile y (dataA,dataB,clk,write,raddA,raddB,wadd,wdata);
always #(posedge clk) begin
if (s0==0) begin
inner <= dataA [3:0]*dataB [3:0];
end
else begin
ooutp <= ((dataA [3:0]*dataB [3:0])+inner [9:0]);
end
end
endmodule

How to assign a register to an output in verilog?

I'm having difficulty figuring out how to assign the value of temp to the out. I searched the web for an answer and tried all kinds of things but still cannot get the output assigned. Here's the code:
module Reg8bit(
input CLK,
input En,
input CLR,
input [7:0] in,
output [7:0] out
);
reg[7:0] temp;
always #(posedge CLK)
begin
if (En)
begin
if (CLR)
out = 8'b0000_0000;
else
out = in;
end
end
assign out = tempQ;
endmodule
Edit: temp should be tempQ, sorry for the typo
You probably meant to write
module Reg8bit(
input CLK,
input En,
input CLR,
input [7:0] in,
output reg [7:0] out // out is a variable, not a wire
);
always #(posedge CLK)
begin
if (En)
begin
if (CLR)
out <= 8'b0000_0000; // use Non-blocking assignments
else
out <= in;
end
end
endmodule
Your code doesn't make much sense. You are assigning to out twice and your not using your temp register.
You probably meant to write something like this:
reg[7:0] temp;
always #(posedge CLK)
begin
if (En)
begin
if (CLR)
temp <= 0;
else
temp <= in;
end
end
assign out = temp;
Its usually (not always) considered good practice to use nonblocking assignments in always blocks. I think in this case you can even do this without the temp register.
The LHS of the assign statement should always be a wire. You have declared out as a reg and it's good to use a reg data type in the LHS inside an always block.

verilog- assign statement reg to output variable not being assigned

I am attempting to use an FPGA as a shift register to some LEDs with pwm, but ran into an error while trying to assign a reg containing the value shifted in to an output variable. When I upload it to the FPGA(i'm using the mojo by embedded micro), it does nothing. when I use the simulator, it reports that all of the output variables are never assigned and have the value of X, while all the other variables inside of the module work just fine. here is my code for the shifting module:
module shifting(
input clk,
input shiftingpin,//data to be shifted in
input rst,
output done,
output [3:0]data//pwm compare value output
);
reg [2: 0] ctr_d, ctr_q;
reg don;
reg [3:0]datas;
always #(*) begin
if(ctr_q == 3'b100) begin
ctr_d[2:0] = 3'b0;
don = 1'b1;
end else begin
ctr_d = ctr_q + 1'b1;
don = 1'b0;
end
end
always #(posedge clk) begin
datas[ctr_q] = shiftingpin;// assign value to the output
if (rst) begin
ctr_q <= 1'b0;
end else begin
ctr_q <= ctr_d;
end
end
assign data = datas;
assign done = don;
endmodule
done tells the containing module when to update and assign the value to pwm.
If I understood the question correctly you have a syntax error when trying to drive ports from within always blocks.
When declaring ports they are typically wire by default which can only be driven by ports or assign. Resulting in the code below
module shifting(
input clk,
input shiftingpin,
input rst,
output done,
output [3:0] data
);
reg don;
reg [3:0] datas;
assign done = don;
assign data = datas;
Solution
The solution is to define ports as reg, logic is preferred if you can support System Verilog.
logic will effectively switch between wire and reg as required to make refactoring code easier.
module shifting(
input clk,
input shiftingpin,
input rst,
output reg done,
output reg [3:0] data
);
always #(posedge clk) begin
data[ctr_q] <= shiftingpin; // <-- data port used directly
//...
NB: shift registers can be done with just
always #(posedge clk) begin
datas[3:0] <= {datas[2:0], shiftingpin};

Resources