Do different begin end statements executed concurrently in verilog?
Here's the code:
//Sample test values to run simulation (module jkflop_top continues)
initial begin
j=0; k=0; rst=1;
#4
j=1; k=1; rst=0;
#50
j=0; k=1; rst=0;
#20
j=1; k=1; rst=0;
end
//Carry out simulation for 100 units of time
initial begin
#100
$finish;
end
endmodule
What the code does is it provides sample input for a j-k flip flop. As the second begin should be finished after 100 units delay from starting of the program if they are concurrent, will the total program run for 100 time units only?
Different initial statements operate concurrently.This has nothing to do with begin/end.
The begin/end only 'group' all the code with one initial.
Here we have two begin/end statements. They do not operate concurrently, they operate sequentially.
for (i=0; i<8; i=i+1)
begin
... // some code
end
for (j=0; j<8; j=j+1)
begin
... // some more code
end
Here we have two initial statement, without begin/end. They operate concurrently.
initial
#50 reset = 1'b0;
initial
#100 clk= 1'b1;
Related
I have a simple Verilog code for a sequential logic network. It consists of a design and a testbench file; it compiles, but it runs for too long. I'm not sure why; apart from the clk, I didn't put any loops in it. Maybe I have some syntax mistakes using the binary numbers. I ran it using the online EDA Playground software; I didn't try it on Xilinx.
Simulator: Icarus Verilog 0.9.7, compile options: -Wall. "Execution
interrupted or reached maximum runtime."
This is what the log wrote.
Design file:
module hazimodul(
input clk,
input rst,
input ce,
input x,
output z
);
reg[1:0] all;
reg[3:0] y;
reg[0:0] zout;
always#(posedge clk)
begin
if(rst)
begin
zout <= 1'b0;
all <= 2'b00;
y <= 4'b0111;
end
else if(ce)
begin
if(all == 2'b00)
begin
if(x== 1'b0)
zout<=1'b0;
else
all <=2'b01;
end
if(all==2'b01)
begin
zout <= y[3:3];
y <= {y[2:0],y[3:3]};
if (y == 4'b0111)
all <= 2'b10;
end
if(all==2'b10)
begin
if(x == 1'b0)
all <= 2'b00;
end
end
end
assign z = zout;
endmodule
Test file:
module test;
reg clk;
reg rst;
reg x;
reg ce;
// Outputs
wire z;
// Instantiate the Unit Under Test (UUT)
hazimodul uut (
.clk(clk),
.rst(rst),
.x(x),
.ce(ce),
.z(z)
);
initial begin
// Initialize Inputs
clk = 0;
rst = 0;
x=0;
ce=0;
#10;
rst<=1;
#20;
rst<=0;
#30
ce<=1;
#40
x<=1;
#80
x<=0;
#90
x<=1;
end
always #5
clk <=~clk;
endmodule
You need to tell the simulator when to stop running. One way is to use the $finish system task, which you can add to your testbench:
initial #1000 $finish;
Now, the simulation finishes on edaplayground. You can change the #1000 delay to something more meaningful to your design.
Here is an explanation of why your code continues to run. Your testbench has 2 parallel threads: one initial block and one always block. In both threads, you add events to the Verilog event queue. The initial block ends after the last assignment to x.
However, the always block continues to add events to the event queue, so the simulation never ends.
Adding the second initial block with the $finish forces the simulation to end, regardless of the infinite always block.
I've got an initial block which calls a task named power_task as below
initial begin
#10;
power_task;
end
Inside the power task, I've two signals power_a and power_b. Initially, power_a goes low and after a certain skew, power_b goes low. As long as both the signals are low, I need to check the output q. Output q should be low during the time window where power_a and power_b signals are low. Since there are no other signals like a clock, I'm not sure how to continuously monitor q. I've written something like below
task power_task;
#1;
power_a=0;
#5; //skew
power_b=0;
if (power_a==0 && power_b==0 && q==0) begin
$display("pass");
end
#50;
power_b=1;
#5;
power_a=1;
end
endtask
In the above task, the if statements check the value of q only after both signals are low and not during the entire 50 ns time window. Can someone please help?
You can use a wait statement in a fork block
task power_task;
begin
reg fail;
fail = 0;
#1 power_a=0;
#5 power_b=0; //skew
fork : check_q
wait (q) fail = 1;
#50 begin
if (fail)
$display("fail");
else
$display("pass");
disable check_q;
end
join
power_b=1;
#5 power_a=1;
end
endtask
Not exactly sure why you need to check that power_a/b are still 0 unless there is some other code that could change it.
Use an always block outside of the task, a control signal (check_en) and a flag variable (pass):
reg pass = 1;
reg check_en = 0;
always #(check_en, q) begin
if (check_en && q) begin
$display("fail");
pass = 0;
end
end
initial begin
#10;
power_task();
if (pass) $display("pass");
end
task power_task;
#1;
power_a=0;
#5; //skew
power_b=0;
check_en = 1;
#50;
check_en = 0;
power_b=1;
#5;
power_a=1;
endtask
The always block will continuously monitor the q signal for any changes when enabled.
I am implementing a sequential circuit in verilog . I want a clock of time period 10 . For implementing that I have done something like
initial begin
forever begin
clk=0;
#5
clk=1;
#5
clk=0;
end
end
But when I run the code , it keeps on running without showing any output. Is there any error in above implementation?
One way of implementing it is as follows (assuming you are using this in a testbench):
parameter clock_period=10;
always
#(clock_period/2) clock=~clock;
initial begin
clock=0;
#1000 $finish; // You can put the delay as per your requirement.
end
Your code keeps on running since there is no $finish. So it's a free running oscillator.
Following are some of the methods for clock generation. More or less, they all are same.
Method 1 :
parameter int clk_tgl_period = 5;
parameter timeout = 500;
module clkgen1;
reg clk;
initial begin
clk <= '0;
forever #(clk_tgl_period) clk = ~clk;
end
initial begin
#(timeout) $finish
end
endmodule
Method - 2
parameter int clk_tgl_period = 5;
parameter timeout = 500;
module clkgen2;
reg clk;
initial begin
clk = 0;
#(timeout) $finish;
end
always #(clk_tgl_period) clk = ~clk;
endmodule
Method - 3
parameter int clk_tgl_period = 5;
parameter timeout = 500;
module clkgen3;
reg clk;
initial begin
clk = 0;
#(timeout) $finish;
end
always #(clk_tgl_period) clk++;
endmodule
For more information, you may want to have a look at Section-4 of CummingsSNUG2006Boston_SystemVerilog_Events Paper.
I have following codes with blocking (code 1) and nonblocking (code 2) assignment in always block.
But output is different in both cases. Why?
Event queue I know, but probably I am not able to understand where "always # (clk)" statement will be placed in event queue.
// Code 1
module osc2 (clk, d);
output clk;
reg clk;
input d;
initial
begin
#10 clk = 0;
$monitor ("%d %b", $time, clk);
end
initial #100 $finish;
always # (clk) #10 clk = ~clk;
endmodule
// Output of Code 1
10 0
20 1
// Code 2
module osc2 (clk, d);
output clk;
reg clk;
input d;
initial
begin
#10 clk = 0;
$monitor ("%d %b", $time, clk);
end
initial #100 $finish;
always # (clk) #10 clk <= ~clk;
endmodule
// Output of Code 2
10 0
20 1
30 0 (goes on upto 90)
90 0
For explanatory purposes, I unraveled the content of the first two loops and expanded components for break down. The below code will simulate.
always # (clk) #10 clk = ~clk;
initial while (1) // to see the loop, functionally equivalent to 'always'
begin // procedural block
begin : loop0_unraveled
#(clk); // suspend continuation of loop until change in clk
#10; // suspend continuation of loop 10 time units
clk = ~clk; /* eval '~clk' now
* update clk now
*/
end
begin : loop1_unraveled
begin // this block is functionally equivalent to '#(clk)'
reg smpl_clk; // local variable
smpl_clk = clk; // sample
$display("%t::Pre-Suspend : smpl_clk=%b clk=%b", $time, smpl_clk, clk);
wait(clk != smpl_clk); // suspend continuation of loop until
/* 1. no other blocking statements can execute, go to next region
* 2. All other regions are empty
* 3. Remaining events are block
* 4. Nothing left to do, exit simulation
*/
$display("%t::Post-Suspend : smpl_clk=%b clk=%b", $time, smpl_clk, clk);
end
#10; // unreachable
clk = ~clk;
end
end
always # (clk) #10 clk <= ~clk;
initial while (1) // to see the loop, functionally equivalent to 'always'
begin // procedural block
begin : loop0_unraveled
#(clk); // suspend continuation of loop until change in clk
#10; // suspend continuation of loop 10 time units
clk <= ~clk; /* eval '~clk' now,
* update clk after all blocking statements are suspended
*/
end
begin : loop1_unraveled
begin // this block is functionally equivalent to '#(clk)'
reg smpl_clk; // local variable
smpl_clk = clk; // sample
$display("%t::Pre-Suspend : smpl_clk=%b clk=%b",$time, smpl_clk, clk);
wait(clk != smpl_clk); // suspend continuation of loop until true
/* 1. no other blocking statements can execute, go to next region
* 2. In NBA region update clk
* 3. Go back to active region
* 4. Eval true, continue
*/
$display("%t::Post-Suspend : smpl_clk=%b clk=%b", $time, smpl_clk, clk);
end
#10; // reached
clk <= ~clk;
end
end // Go to top of the loop
As I already mentioned here, self triggering blocks are not very common in practice. Clock generator are usually implanted something similar to:
initial begin
#10 clk = 0;
forever #10 clk = ~clk;
end
Or
always #10 clk = (clk===1'b0);
I want to design an counter which counts up to some number, lets say it is 3, for this I write a code that work well with "$finish" but not with "disable".
I want to use this counter for synthesis so I have to use "disable" statement .....
I have attached my both code-
(1) With $finish that stops easily & accurately
// Code with $finish
module counter(input wire clk);
reg [23:0]N=24'b0000_0000_0000_0000_0000_0000;
always # (posedge clk)
begin
if (N == 24'b0000_0000_0000_0000_0000_0011)
begin
$display("Inside If N=%d in Time=",N,$time);
$finish;
end
else
begin
N <= N +1;
$display("Inside Else N=%d in Time=",N,$time);
end
end
endmodule
(2) With disable that not stop at all..
// Code with disable that not stop
module counter(input wire clk);
reg [23:0]N=24'b0000_0000_0000_0000_0000_0000;
always # (posedge clk)
begin :close
if (N == 24'b0000_0000_0000_0000_0000_0011)
begin
$display("Inside If N=%d in Time=",N,$time);
disable close;
end
else
begin
N <= N +1;
$display("Inside Else N=%d in Time=",N,$time);
end
end
endmodule
toolic and Greg have both indicated to incorrect uses of $finish and disable, this is just to add to both of those points and show a possible solution, seperating test from synthesizable RTL.
module counter(input clk);
reg [23:0] N = 24'b0;
always # (posedge clk) begin
if (N < 24'd3) begin
N <= N +1;
$display("Inside If N=%d in Time=",N,$time);
end
else begin
$display("Inside Else N=%d in Time=",N,$time);
end
end
endmodule
To test it:
module test;
//Create clk
reg clk;
initial begin
clk = 0 ;
forever begin
#5 clk = ~clk;
end
end
//instantiate DUT (Device Under Test)
counter counter_i0(
.clk( clk )
);
// The test
// Run for 6 clock cycles then end
initial begin
repeat (6) begin
#(posedge clk)
end
$finish;
end
endmodule
If you mean to stop at count 3, I would use decimal notation 24'd3 for the constant, as it gives clear intent.
also if using == to stop a counter a glitch could cause this to be missed and you have to wait for this to wrap arround. Or using a less than comparator means that the count target can be adjusted on the fly with out fear of skipping the exact value in == and having to wait a really long time for it to wrap around.
inputs are implicitly wires, no need to define them as such but you can if you want.
Put the $finish at the end of your test bench, not in your synthetically RTL.
$finish stops all running processes and ends the simulation. disable stops one process and its child processes. In your sample code, disable close terminates the code within the always block, it does not stop the clock. The next positive edge clock and the always block will try to run again.
See IEEE std 1800-2012 § 20.2 for the $finish statement and § 9.6.2 for the Disable statement