Verilog logical error - verilog

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

Related

trying to do shift left every cycle time Verilog [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed yesterday.
Improve this question
i tried to do it in two ways, and each time i got stuck by the same problem Error (10031): Net "copy_data_in[183]" at RotateText.sv(16) is already driven by input port "data_in[183]", and cannot be driven by another signal.
Hi , i have input of 23 elements that each one is 8 bits.i have output of 6 elements that each one is 8 bits.The input should get change each time. in the end it should be like circular printing. Excuse me but ENABLE should be CLK.
i tried to do it in two ways, and each time i got stuck by the same problem Error (10031): Net "copy_data_in[183]" at RotateText.sv(16) is already driven by input port "data_in[183]", and cannot be driven by another signal.
This first try :
module RotateText( data_in,HEX0S,HEX1S,HEX2S,HEX3S,HEX4S,HEX5S,ENABLE);
input [7:0] data_in [22:0];
input ENABLE;
output reg [7:0] HEX0S;
output reg [7:0] HEX1S;
output reg [7:0] HEX2S;
output reg [7:0] HEX3S;
output reg [7:0] HEX4S;
output reg [7:0] HEX5S;
reg [7:0] tmp;
reg [7:0] copy_data_in [22:0];
reg [7:0] tmp2;
integer i;
integer j=0;
always#(posedge ENABLE)begin
if(j==0)begin
for(i = 0; i < 23; i=i+1) begin
copy_data_in[i] <= data_in[i];
end
end
HEX5S<=copy_data_in[22];
HEX4S<=copy_data_in[21];
HEX3S<=copy_data_in[20];
HEX2S<=copy_data_in[19];
HEX1S<=copy_data_in[18];
HEX0S<=copy_data_in[17];
tmp<= copy_data_in[22];
copy_data_in[22:1]<=copy_data_in[21:0];
copy_data_in[0]<=tmp;
j=j+1;
end
endmodule
This is another approch :
module RotateText( data_in,HEX0S,HEX1S,HEX2S,HEX3S,HEX4S,HEX5S,ENABLE);
input [183:0] data_in ;
input ENABLE;
output reg [7:0] HEX0S;
output reg [7:0] HEX1S;
output reg [7:0] HEX2S;
output reg [7:0] HEX3S;
output reg [7:0] HEX4S;
output reg [7:0] HEX5S;
reg [7:0] tmp;
reg [183:0] copy_data_in;
integer i;
integer j=0;
integer index;
assign copy_data_in=data_in;
always#(posedge ENABLE)begin
HEX5S<=copy_data_in[183:176];
HEX4S<=copy_data_in[175:168];
HEX3S<=copy_data_in[167:160];
HEX2S<=copy_data_in[159:152];
HEX1S<=copy_data_in[151:144];
HEX0S<=copy_data_in[143:136];
tmp<=data_in[183:176];
copy_data_in<=copy_data_in<<8;
copy_data_in[7:0]<=tmp;
end
endmodule
glad to get help .
The post has a circular shift register (sr).
An sr accepts input from the previous stage or from a module input for loading; not both at the same time. Loading & shifting are mutually exclusive behaviors in the same clock clock cycle. The design needs a input control signal to decide load or shift.
The posted code errors out, because its trying to drive the sr internally, and from inputs at the same time.
Here is a solution based on the posted code.
Variable load_shiftn determines load or shift .
module rot(
input logic clk,
input [7:0] data_in [22:0],
input logic load_shiftn,
output reg [7:0] HEX0S,
output reg [7:0] HEX1S,
output reg [7:0] HEX2S,
output reg [7:0] HEX3S,
output reg [7:0] HEX4S,
output reg [7:0] HEX5S
);
// internal
reg [7:0] sr [22:0];
always#(posedge clk)begin
if(load_shiftn)
sr <= data_in;
else begin
sr[22:1] <= sr[21:0];
sr[0] <= sr[22];
end
end
always # * begin
HEX5S =sr[22];
HEX4S =sr[21];
HEX3S =sr[20];
HEX2S =sr[19];
HEX1S =sr[18];
HEX0S =sr[17];
end
endmodule
Testbench
module tb ();
bit clk;
logic [7:0] data_in [22:0];
bit load_shiftn;
logic [7:0] HEX0S;
logic [7:0] HEX1S;
logic [7:0] HEX2S;
logic [7:0] HEX3S;
logic [7:0] HEX4S;
logic [7:0] HEX5S;
always #5 clk = !clk;
initial begin
#270;
$finish;
end
rot u1 (.*);
initial begin
$dumpfile("dump.vcd");
$dumpvars;
end
initial begin
foreach(data_in[i])
data_in[i] = i;
end
initial begin
#(posedge clk)
load_shiftn <= 1;
repeat(2) #(posedge clk);
load_shiftn <= 0;
end
endmodule
Waves

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.

Error (10219): Verilog HDL Continuous Assignment error at Mux.v(19): object "muxout" on left-hand side of assignment must have a net type

I want to make Frequency Divider with Counter and MUX.
I make 3 module for project
// 4-bit Counter
module Counter (input clk, input reset, output reg[3:0] out);
always#(posedge clk or posedge reset)
begin
if(reset)
out = 4'b0000;
else
begin
if(clk)
if(out < 4'b1111)
out = out + 4'b0001;
else
out = 4'b0000;
end
end
endmodule
//module 4by1 Mux
module Mux (input [3:0] muxin , input [1:0] sel, output reg muxout);
function _4by1mux;
input [3:0] muxin;
input [1:0] sel;
case (sel)
2'b00 : _4by1mux = muxin[0];
2'b01 : _4by1mux = muxin[1];
2'b10 : _4by1mux = muxin[2];
2'b11 : _4by1mux = muxin[3];
endcase
endfunction
assign muxout = _4by1mux(muxin, sel);
endmodule
//module freqDivider
module freqDivider(input clk, input reset, input [1:0] sel, output reg muxout);
wire [3:0]counterbus;
Counter ct1 (clk, reset, counterbus);
Mux mux1 (counterbus, sel, muxout);
endmodule
module freqDivider is top, and I call module Counter and Mux
but module Mux has problem with
Error (10219): Verilog HDL Continuous Assignment error at Mux.v(19):
object "muxout" on left-hand side of assignment must have a net type
this error
ps. input sel will be changed by time
The error is a result of the muxout output having type reg instead of type wire. In verilog, lines can have two overarching types, either nets (like wire type) or variables (like reg types). To assign values/logic to net types, you need to use assign statements and not always blocks. To assign values/logic to variable types, you can only use always blocks and not assign statements. So, you can either make your assign in the Mux module an always block or, for an easier solution, don't make the muxout output a reg, just leave out the reg keyword and it will be a wire.
Error is that you have declared mux_out as reg type, instead of wire type. Default type of any port is wire. You are doing continuous assignment on that net through assign keyword. And on reg type nets, assignment can only be done inside procedural block (initial, always).
Change to mux_out from output reg to output only.

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

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.

Resources