I tried to make the watch that counts the time given that cycle of clk is a minute. But, I had troubles with finding which two assignment are being clashed. (I have been looking for two days but I couldn't find it)
First I tried these codes in the EDA playground.
//code for "design.sv"
module clock(
input clk, rstn,
output reg[6:0] minute, //line 1
output reg[5:0] hour //line 2
);
always @ (posedge clk, negedge rstn) begin
if(!rstn) begin
minute <= 0; hour = 0;
end
else begin
minute = minute + 1;
end
end
always @ (posedge clk) begin
if((minute%60==0)&&(minute != 0)) begin
minute <= 0;
hour = hour + 1;
end
if((hour%24==0)&&(hour !=0)) hour <= 0;
end
endmodule
//code for "testbench.sv"
module test;
reg clk, rstn;
reg [6:0] minute;
reg [5:0] hour;
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
rstn = 1; minute = 0; hour = 0; //line 3
#30 rstn = 0;
#1 rstn = 1;
#600 $finish;
end
clock clock_inst(clk, rstn, minute, hour);
initial begin
$dumpfiles("wave.vcd");
$dumpvars(0, test);
end
endmodule
I simulated these first codes and got the error below.
"Variable ""minute"" cannot be driven by both the procedural and continuous assignment statements. "Variable ""hour"" cannot be driven by both the procedural and continuous assignment statements.
My first conclusion:
I concluded that assignments on line 1
and line 2
are making conflict with those of line 3
.
I thought output reg minute
and output reg hour
in clock_inst
are implicit continuous assignment.
Accordingly line 1
and line 2
clashes with assignments on minute
and hour
(placed in line 3
) leading to multidriver issue in one variable.
However, in order to check my conclusion, I revised the code like below.
//revised code for "design.sv"
module clock(
input clk, rstn,
output reg[6:0] minute,
output reg[5:0] hour
);
initial begin // newly added block
minute = 0; hour = 0;
end
always @ (posedge clk, negedge rstn) begin
if(!rstn) begin
minute <= 0; hour = 0;
end
else begin
minute = minute + 1;
end
end
always @ (posedge clk) begin
if((minute%60==0)&&(minute != 0)) begin
minute <= 0;
hour = hour + 1;
end
if((hour%24==0)&&(hour !=0)) hour <= 0;
end
endmodule
//revised code for "testbench.sv"
module test;
reg clk, rstn;
reg [6:0] minute;
reg [5:0] hour;
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
rstn = 1; //revised line
#30 rstn = 0;
#1 rstn = 1;
#600 $finish;
end
clock clock_inst(clk, rstn, minute, hour);
initial begin
$dumpfiles("wave.vcd");
$dumpvars(0, test);
end
endmodule
What I thought is that these codes would give me error because assignment on newly added block
would be clashed with output reg[6:0] minute
and output reg[5:0] hour
assignments.
But it worked really well
VSIM: Simulation has finished. There are no more test vectors to simulate.
VSIM: Simulation has finished.
Now, I cannot find what lines constigate multi-driving error in my first code.
In the original code, variable (reg) minute
is driven from more than one always
block.
That is the definition multiple drivers, and will not synthesize.
The solution is to put all drivers to the variables (regs) in one always block.
Like this:
always @ (posedge clk, negedge rstn) begin
if(!rstn) begin
minute <= 0;
hour <= 0;
end
else begin
if(minute < 60)
minute <= minute + 1;
else
minute <= 0;
if(minute < 24)
hour <= hour + 1;
else
hour <= 0;
end
end
The modulus operator will not synthesize well except in cases where you are taking a modulus which is a power of 2^N example: 2,4,8,16,32...
Also take care to always use non-blocking assignments <=
in a synchronous always block rather than blocking assignments =
. Using blocking assignments in a synchronous always block can cause simulation/ synthesis mismatched behavior.
What you are seeing in the revised code is an example of the simulator not correctly detecting the multiple drivers associated with the verilog always
block in simulation. The SystemVerilog statement always_ff
corrects this and will consistently detect a multiple drivers error in simulation and synthesis.
To demonstrate, I changed the always
blocks to always_ff
and re-ran on eda playground.
Like this:
module clock(
input clk, rstn,
output reg[6:0] minute,
output reg[5:0] hour
);
initial begin // newly added block
minute = 0; hour = 0;
end
always_ff @ (posedge clk, negedge rstn) begin
if(!rstn) begin
minute <= 0; hour = 0;
end
else begin
minute = minute + 1;
end
end
always_ff @ (posedge clk) begin
if((minute%60==0)&&(minute != 0)) begin
minute <= 0;
hour = hour + 1;
end
if((hour%24==0)&&(hour !=0)) hour <= 0;
end
endmodule
Produces:
xmelab: *E,MULAXX (./design.sv,13|10): Multiple drivers to always_ff output variable minute detected.
always_ff @ (posedge clk, negedge rstn) begin
|
xmelab: *E,MULAXX (./design.sv,13|10): Multiple drivers to always_ff output variable minute detected.
always_ff @ (posedge clk, negedge rstn) begin
|
xmelab: *E,MULAXX (./design.sv,13|10): Multiple drivers to always_ff output variable minute detected.
always_ff @ (posedge clk, negedge rstn) begin
|
xmelab: *E,MULAXX (./design.sv,13|10): Multiple drivers to always_ff output variable minute detected.
always_ff @ (posedge clk, negedge rstn) begin
|
xmelab: *E,MULAXX (./design.sv,13|10): Multiple drivers to always_ff output variable minute detected.
always_ff @ (posedge clk, negedge rstn) begin
|
xmelab: *E,MULAXX (./design.sv,13|10): Multiple drivers to always_ff output variable minute detected.
always_ff @ (posedge clk, negedge rstn) begin
|
xmelab: *E,MULAXX (./design.sv,13|10): Multiple drivers to always_ff output variable minute detected.
always_ff @ (posedge clk) begin
|
xmelab: *E,MULAXX (./design.sv,22|10): Multiple drivers to always_ff output variable minute detected.
always_ff @ (posedge clk) begin
|
xmelab: *E,MULAXX (./design.sv,22|10): Multiple drivers to always_ff output variable minute detected.
always_ff @ (posedge clk) begin
|
xmelab: *E,MULAXX (./design.sv,22|10): Multiple drivers to always_ff output variable minute detected.
always_ff @ (posedge clk) begin
|
xmelab: *E,MULAXX (./design.sv,22|10): Multiple drivers to always_ff output variable minute detected.
always_ff @ (posedge clk) begin
|
xmelab: *E,MULAXX (./design.sv,22|10): Multiple drivers to always_ff output variable minute detected.
always_ff @ (posedge clk) begin
|
xmelab: *E,MULAXX (./design.sv,22|10): Multiple drivers to always_ff output variable minute detected.
always_ff @ (posedge clk) begin
|
xmelab: *E,MULAXX (./design.sv,22|10): Multiple drivers to always_ff output variable minute detected.
always_ff @ (posedge clk, negedge rstn) begin
|
xmelab: *E,MULAXX (./design.sv,13|10): Multiple drivers to always_ff output variable hour detected.
always_ff @ (posedge clk, negedge rstn) begin
|
xmelab: *E,MULAXX (./design.sv,13|10): Multiple drivers to always_ff output variable hour detected.
always_ff @ (posedge clk, negedge rstn) begin
|
xmelab: *E,MULAXX (./design.sv,13|10): Multiple drivers to always_ff output variable hour detected.
always_ff @ (posedge clk, negedge rstn) begin
|
xmelab: *E,MULAXX (./design.sv,13|10): Multiple drivers to always_ff output variable hour detected.
always_ff @ (posedge clk, negedge rstn) begin
|
xmelab: *E,MULAXX (./design.sv,13|10): Multiple drivers to always_ff output variable hour detected.
always_ff @ (posedge clk, negedge rstn) begin
|
xmelab: *E,MULAXX (./design.sv,13|10): Multiple drivers to always_ff output variable hour detected.
always_ff @ (posedge clk) begin
|
xmelab: *E,MULAXX (./design.sv,22|10): Multiple drivers to always_ff output variable hour detected.
always_ff @ (posedge clk) begin
|
xmelab: *E,MULAXX (./design.sv,22|10): Multiple drivers to always_ff output variable hour detected.
always_ff @ (posedge clk) begin
|
xmelab: *E,MULAXX (./design.sv,22|10): Multiple drivers to always_ff output variable hour detected.
always_ff @ (posedge clk) begin
|
xmelab: *E,MULAXX (./design.sv,22|10): Multiple drivers to always_ff output variable hour detected.
always_ff @ (posedge clk) begin
|
xmelab: *E,MULAXX (./design.sv,22|10): Multiple drivers to always_ff output variable hour detected.
always_ff @ (posedge clk) begin
|
xmelab: *E,MULAXX (./design.sv,22|10): Multiple drivers to always_ff output variable hour detected.
xrun: *E,ELBERR: Error during elaboration (status 1), exiting.
Using Cadence and similar using Modelsim/Questa.
always_ff
caught the multiple drivers and always
missed it in simulation.