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.
Related
I am not getting any response from the uut in the testbench. The module exp2_up_down_counter works ok without testbench, but gives output as xxxx when instantiated in the testbench.
Here is the main module of the up-down counter:
`timescale 1ns/1ps
module exp2_up_down_counter (input clk, reset, mode, output reg [3:0] count);
always #(posedge clk)
if (reset == 1)
count <= 0; // reset the counter if reset is high
else if (mode == 1)
count <= count + 1; // works as up counter if mode pin is high
else
count <= count - 1; // works as down counter if mode pin is low
endmodule
Simulation without testbench:
Testbench for up-down counter
`timescale 1ns/1ps
module exp2_up_down_counter_tb;
reg clk, reset, mode;
wire [3:0] count;
exp2_up_down_counter uut(.clk(clk), .reset(reset), .mode(mode), .count(count));
initial begin
clk = 1'b0;
end
always #(*) #5 clk <= ~clk;
initial begin
// initializing the inputs
reset = 1;
mode = 0;
#5;
reset = 0;
#10
mode = 1;
#5000 $finish;
end
endmodule
Simulation with testbench:
In exp2_up_down_counter, count is declared as a reg. This means that its default value is X at time 0. Since the reset signal is synchronous to the clock, you need to wait for the 1st posedge of clock before you release the reset. Currently, the reset is released at the 1st posedge of clock in the testbench, which is a race condition. Therefore, count does not get assigned the value of 0, and it retains the value of X for the whole simulation.
You need to delay the reset release. For example, change:
#5;
reset = 0;
to:
#15;
reset = 0;
However, it is better to drive your synchronous inputs in the testbench the same way you drive your signals in the design: using #(posedge clk) and using nonblocking assignments (<=):
initial begin
reset = 1;
mode = 0;
repeat (2) #(posedge clk);
reset <= 0;
repeat (1) #(posedge clk);
mode <= 1;
#5000 $finish;
end
Also, this is a more standard way to drive the clock in the testbench:
always #5 clk = ~clk;
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 have a problem in the test bench code, and I am not getting correct waveforms. Even the clock does not trigger.
CODE for D Flipflop:
module D_FF(o,D,clk);
output reg o;
input D,clk;
always # (posedge clk)
begin
if(D==1'b1)begin
o=1'b1;
end
else begin
o=1'b0;
end
end
endmodule
Code for TestBench:
module DD_flipflop_tb();
reg clk,D;
wire o;
D_FF i1(o,D,clk);
initial begin
clk=1'b0;
D=1'b0;
end
always begin
#20 clk=~clk;
#35 D=~D;
#5000 $finish;
end
endmodule
Here is what happens in the always block in your testbench.
At time 0, clk and D are 0.
At time 20, you invert clk, which becomes 1.
At time 55, you invert D, which becomes 1.
At time 5055, you call $finish which terminates the simulation. The statements in the block only execute once, which is why your inputs never change more than once.
In your testbench, initialize them as 0 in an initial block, then separate the clock generation from the data signal.
initial begin
clk = 0;
forever #20 clk=~clk;
end
initial begin
D=0;
forever #35 D=~D;
end
initial #5000 $finish;
You might want to assign separately the clock and the stimulus in the testbench:
initial begin
clk = 0;
D = 0;
#5000 $finish;
end
//..clock
always
#20 clk = ~clk;
//..stimulus
always
#35 D = ~D;
I wrote code in Verilog that is supposed to create a 12Hz square signal at 50MHz clock signal.
Is it correct?
module w_m(clk, cnt);
input clk;
output [21:0] cnt;
reg [21:0] cnt = 0;
always #(posedge clk)
cnt = cnt + 1;
endmodule
module w_tf;
reg clk;
wire [21:0] cnt;
w_m uut
(
.clk(clk),
.cnt(cnt)
);
initial begin
// Initialize Inputs
clk = 0;
forever begin
#10
clk = !clk;
end
end
endmodule
Yes, it correctly simulates as described, assuming the timescale is set to 1ns.
The clk period is 20ns, and its frequency is 50MHz.
The MSB of cnt (cnt[21]) has a frequency of approximately 12Hz (11.921Hz, according to my simulation results).
You can verifiy this by running a simulation and looking at waveforms. You can post your code on edaplayground, for example.
The logic is right. However, there are some inaccuracies. I have varied the register size in order to run the simulation as allowed by EDA playground.
DUT:
module w_m(clk, clk_out);
input clk;
//output [21:0] cnt;
output clk_out;
reg [11:0] cnt = 0; // make 11 to 21
always #(posedge clk)
cnt = cnt + 1;
assign clk_out = cnt[11];
endmodule
Also, the testbench needs a $finish to stop the forever block from running infinite, taking up the disk space. Added a parallel path in order to run the sim, and exit after 10000ns. You can vary this as per your need.
TB:
module w_tf;
reg clk;
wire cnt;
w_m uut
(
.clk(clk),
.clk_out(cnt)
);
initial begin
// Initialize Inputs
clk = 0;
fork
begin
forever begin
#10 clk = !clk; end
end
begin
#10000000 $finish; // increase this number as per the simulation requirement
end
join
end
endmodule
I have used following code to generate clock (whichever value I pass through task it will create that frequency), but the code only works if I use CLKSEL_global = clksel_local (i.e. blocking assignment) but that creates delta delay.
How do I generate variable clock without introducing delta delay? Is their another way of using a task. I am using task so that I can pass real values
`timescale 1ns/1ps
module tb();
real CLKSEL_global;
reg CLK7;
new dut(clk,clk_out);
task task_CLOCK;
input real clksel_local;
begin
CLKSEL_global = clksel_local;
end
endtask
initial begin
CLK7 = 0;
forever begin
#(500.0/CLKSEL_global) CLK7 = 1;
#(500.0/CLKSEL_global) CLK7 = 0;
end
end
initial begin
task_CLOCK(340.0);
end
initial begin
#100 $finish ;
end
endmodule
This solution feels like a nasty hack but I think achieves the requirement. When changing the Clock frequency it will change on the next edge, but allows #(posedge clk) to be used for the edge you want to change it on. The change is actually 1ns after the positive edge.
Normally the you would set the frequency and allow it to take effect on the edge giving a full cycle of setup.
module tb();
real CLKSEL_global = 500;
reg clk;
task task_CLOCK;
input real clksel_local;
begin
CLKSEL_global <= clksel_local;
end
endtask
initial begin
#1ns;
clk = 1'b0;
forever begin
#((500.0ns/CLKSEL_global) -1ns) clk = ~clk;
end
end
initial begin
$dumpfile("dump.vcd"); $dumpvars;
task_CLOCK(1);
repeat(2)
#(posedge clk);
task_CLOCK(2);
repeat(2)
#(posedge clk);
$finish ;
end
endmodule
Working copy of above on EDA Playground.