Capturing the right posedge clock in Quartus waveform - verilog

I am using Quartus Prime Lite 19.1.0.
module memory_address_register1 #(
parameter ADDR_WIDTH = 4
)(
input clk, rst, load,
input [ADDR_WIDTH-1:0] add_in,
output reg [ADDR_WIDTH-1:0] add_out
);
always #(posedge clk) begin
if (rst) begin
add_out <= 4'b0000;
end else if (load) begin
add_out <= add_in;
end else begin
add_out <= add_out;
end
end
endmodule
module mmr_tb();
reg clk, rst, load;
reg [3:0] add_in;
wire [3:0] add_out;
initial begin
clk <= 1'b0;
rst <= 1'b0;
load <= 1'b0;
end
memory_address_register1 mmr (.clk(clk), .rst(rst), .load(load), .add_in(add_in), .add_out(add_out));
always #10 clk = ~clk;
initial begin
#20 add_in <= 4'd2;
#10 add_in <= 4'd3;
load <= 1'b1;
#30 add_in <= 4'd6;
#10 load <= 1'b1;
end
endmodule
It the output (add_out) accurate? Should the output (add_out) at t=70.0ns be "6" or "7"?
If the expected output is "6", can anyone explain why is that?
img2: posedge clk output value from previous clk cycle
I ran the testbench using modelsim, and I am able to get the expected output I wanted (output on the exact clock edge), but is it expected?
https://imgur.com/a/M85zPKT

You have potential race conditions in your testbench code. You should drive all your inputs in the testbench the same way you drive them in the design:
Use nonblocking assignments (<=) instead of blocking assignments (=)
Use #(posedge clk) instead of # delays
This will guarantee that your inputs will be synchronous to the clock. This also assures that pulsewidths of your inputs are a multiple of the clock period. Some of your signals are half a period wide or 1.5 periods wide.
module mmr_tb();
reg clk, rst, load;
reg [3:0] add_in;
wire [3:0] add_out;
initial begin
clk <= 0;
rst <= 1;
load <= 0;
add_in <= 0;
repeat (2) #(posedge clk);
rst <= 0;
forever #(posedge clk) begin
add_in <= add_in + 1;
end
end
memory_address_register1 mmr (.clk(clk), .rst(rst), .load(load), .add_in(add_in), .add_out(add_out));
always #10 clk = ~clk;
initial begin
repeat (4) #(posedge clk); load <= ~load;
repeat (1) #(posedge clk); load <= ~load;
repeat (4) #(posedge clk); load <= ~load;
repeat (1) #(posedge clk); load <= ~load;
repeat (3) #(posedge clk); $finish;
end
endmodule

Related

Monostable multivibrator simulation

The monostable module implements a monostable multivibrator. It takes in three inputs (clk, reset, trigger) and outputs a single (pulse).
The trigger input triggers the module. When triggered, the output signal (pulse) will switch to a high position for a period of clock ticks, and then return to a low position. The pulse width of the output signal can be set via the PULSE_WIDTH parameter, which represents the period in clock ticks that the signal should stay high.
Now, what is happening is when it gets triggered, immediately output signal (pulse) is getting high.
When triggered, the output signal (pulse) should be high on the next active edge of clk. What changes can be done ?
module monostable(
input clk,
input reset,
input trigger,
output reg pulse = 0
);
parameter PULSE_WIDTH = 20;
reg [4:0] count = 0;
wire countReset = reset | (count == PULSE_WIDTH);
always #(posedge trigger, posedge countReset) begin
if (countReset) begin
pulse <= 1'b0;
end else begin
pulse <= 1'b1;
end
end
always #(posedge clk, posedge countReset) begin
if(countReset) begin
count <= 0;
end else begin
if(pulse) begin
count <= count + 1'b1;
end
end
end
endmodule
module monostable_tb();
reg clk;
reg reset;
reg trigger;
wire pulse;
parameter PULSE_WIDTH = 20;
monostable imonostable(.*);
initial begin
clk=0;
forever #50 clk=~clk;
end
initial begin
$monitor("trigger=%b pulse=%b, count = %0d",trigger,pulse,imonostable.count);
$dumpfile("monostable_tb.vcd");
$dumpvars(0,monostable_tb);
trigger=1'b0;
reset = 1'b0;
#(posedge clk) reset = 1'b1;
#(posedge clk) reset = 1'b0;
#(posedge clk) trigger=1'b1;
#(posedge clk) trigger=1'b0;
repeat(25) #(posedge clk);
$finish;
end
endmodule
Here is a simplified design which sets the output one cycle after the input trigger pulse, and keeps the output high for 20 cycles:
module monostable(
input clk,
input reset,
input trigger,
output reg pulse = 0
);
parameter PULSE_WIDTH = 20;
reg [4:0] count;
always #(posedge clk, posedge reset) begin
if (reset) begin
pulse <= 1'b0;
end else if (trigger) begin
pulse <= 1'b1;
end else if (count == PULSE_WIDTH-1) begin
pulse <= 1'b0;
end
end
always #(posedge clk, posedge reset) begin
if(reset) begin
count <= 0;
end else if (pulse) begin
count <= count + 1'b1;
end
end
endmodule
It now uses a single clock signal, instead of 2. It also uses a simple reset signal, which can avoid potential glitches causing unwanted asynchronous resets.
You should also use nonblocking assignments in the testbench:
#(posedge clk) reset <= 1'b1;
#(posedge clk) reset <= 1'b0;
#(posedge clk) trigger<= 1'b1;
#(posedge clk) trigger<= 1'b0;
If a 1-clock synchronous delay is needed, then run the output thru a flip flop.
module monostable(
input clk,
input reset,
input trigger,
output reg pulse = 0
);
parameter PULSE_WIDTH = 20;
reg [4:0] count = 0;
reg reg_pulse_temp;
wire countReset = reset | (count == PULSE_WIDTH);
always #(posedge trigger, posedge countReset) begin
if (countReset) begin
reg_pulse_temp <= 1'b0;
end else begin
reg_pulse_temp <= 1'b1;
end
end
always #(posedge clk, posedge countReset) begin
if(countReset) begin
count <= 0;
// reset the flop
pulse <= 0;
end else begin
if(pulse) begin
count <= count + 1'b1;
end
end
// flip flop
pulse <= reg_pulse_temp;
end
endmodule

incrementing mod counter every n clock cycle

This is the verilog code for mod 64 counter, incrementing every clock cycle
module modulus64counter
#(parameter N=64,
parameter WIDTH=5)
(input clk,
input rstn,
output reg[WIDTH-1:0] out);
integer i;
always #(posedge clk) begin
if(!rstn) begin
out<=0;
end
else begin
if(out==N-1)
out<=0;
else
out<= out+1;
end
end
endmodule
and the test bench is
module modulus64countertb;
// Inputs
reg clk;
reg rstn;
// Outputs
wire [4:0] out;
// Instantiate the Unit Under Test (UUT)
modulus64counter uut (
.clk(clk),
.rstn(rstn),
.out(out)
);
always #10 clk = ~clk;
initial begin
// Initialize Inputs
clk = 1;
rstn = 0;
$monitor ("T=%0t rstn=%0b out=0X%h", $time,rstn,out);
repeat(2) #(posedge clk);
rstn <=1;
repeat(50) #(posedge clk);
$finish;
end
endmodule
Now if i want to increment the value of out every "n" clock cycle instead of consecutive clock cycle , how can i modify the program
Kindly help
Updated 20220131
Updated the code to produce output after every 2 clock cycles. Similarly, if you wish to delay for even more clock cycle, the simplest way is to continuously flopping it.
For a better implementation, you can try out a shift register.
module modulus64counter #(
parameter N=64,
parameter WIDTH=8,
parameter DELAY_CYCLE=2
)(
input clk,
input rstn,
output reg[WIDTH-1:0] out,
output reg[WIDTH-1:0] actual_out
);
integer i;
reg [WIDTH-1:0] cntr;
reg [WIDTH-1:0] dly1clk;
always #(posedge clk) begin
if(!rstn) begin
out <= 0;
dly1clk <= 0;
end else if(out == DELAY_CYCLE-1) begin
out <= 0;
dly1clk <= dly1clk + 1;
end else begin
out <= out + 1;
end
end
always #(posedge clk) begin
if(!rstn) begin
actual_out <= 0;
end else begin
actual_out <= dly1clk;
end
end
endmodule
The code below should work for you. You can always swap the out and actual_out if you insist on using out as the final counting variable.
Also, removing the out on the monitor line in the testbench will only print the value when it reaches mod n. I kept both out and actual_out on testbench's monitor to ease debugging purpose.
Verilog code
module modulus64counter #(
parameter N=64,
parameter WIDTH=8
)(
input clk,
input rstn,
output reg[WIDTH-1:0] out,
output reg[WIDTH-1:0] actual_out
);
integer i;
reg [WIDTH-1:0] cntr;
always #(posedge clk) begin
if(!rstn) begin
out <= 0;
actual_out <= 0;
end else if(out == N-1) begin
out <= 0;
actual_out <= actual_out + 1;
end else begin
out <= out + 1;
end
end
endmodule
Testbench
module modulus64countertb;
// Inputs
reg clk;
reg rstn;
// Outputs
wire [7:0] out;
wire [7:0] actual_out;
// Instantiate the Unit Under Test (UUT)
modulus64counter uut (
.clk(clk),
.rstn(rstn),
.out(out),
.actual_out(actual_out)
);
always #10 clk = ~clk;
initial begin
// Initialize Inputs
clk = 1;
rstn = 0;
$monitor ("T=%0t rstn=%0b out=%d actual_out=%d", $time,rstn,out,actual_out);
repeat(2) #(posedge clk);
rstn <=1;
repeat(200) #(posedge clk);
$finish;
end
endmodule
Output result simulated using edaplayground:

Designing cpu but Value isn't moving in verilog

module sram(addr,clk,din,dout,we); //sram.v
parameter addr_width = 12, word_depth = 110, word_width = 16;
input clk,we;
input [addr_width-1:0] addr;
input [word_width-1:0] din;
output [word_width-1:0] dout;
reg [word_width-1:0]mem[0:word_depth-1];
reg [word_width-1:0]dout;
always # (posedge clk) begin
if(!we)
mem[addr] <= din[word_width-1:0];
end
always # (posedge clk) begin
if(we)
dout[word_width-1:0] <= mem[addr];
end
endmodule
module cpu(clk,reset); //cpu.v
input clk, reset;
reg [15:0] dr, ac, ir;
reg [11:0] addr, pc;
reg [2:0] opcode;
reg [5:0]t;
reg we;
reg sc;
reg [15:0] din;
wire [15:0] dout;
sram sram(addr,clk,din,dout,we);
always # (posedge clk or negedge reset) begin
if(!reset) begin
ir <= 16'd0; dr <= 16'd0; ac <= 16'd0; addr <= 12'd0; pc <= 12'd0; sc <= 0; t <= 0; we<=1;
end
else if(t==0) begin
addr <= pc; sc<=1;
end
else if(t==1) begin
ir[15:0] <= dout[addr]; pc <= pc+1;
end
else if(t==2) begin
opcode <= ir[14:12];
addr <= ir[11:0]; //no indirect mode, no i
sc<=0;
end
else if(t==3) begin
if(opcode==3'b111) begin
ac <= 0;
end
if(opcode==3'b000) begin
end
end
end
always # (negedge clk) begin
if(!sc) begin
t<=0;
end
else t<=t+1;
end
endmodule
module tbcpu(); //tbcpu.v
reg clk,reset;
integer file_pointer;
cpu cpu(clk,reset);
always #5 clk = ~clk;
initial begin
$readmemb("memory.dat", tbcpu.cpu.sram.mem); //assembly
clk = 0; reset = 1;
#1 reset = 0;
#1 reset = 1;
#100 $finish;
end
endmodule
I'm designing cpu and having hard time because ir[15:0] value doesn't change and fixed in 0000.
I'm expecting when t comes 01 (in 15ns),
this conditional sentence work :
else if(t==1) begin
ir[15:0] <= dout[addr]; pc <= pc+1;
so dout[0] value 7800 go into ir[15:0], but it doesn't work. How can I fix this? I'm also confusing about sc, t timing so I solved that problem by changing sc,t values in negedge clk.
Change:
ir[15:0] <= dout[addr];
to:
ir[15:0] <= dout;
dout[addr] selects a single bit of the 16-bit dout signal. You were treating dout as if it were a memory variable, instead of a vector signal. At 15ns, dout='h7800 and addr=0, which means ir=dout[addr]=dout[0]=0.

Driving a internal wire in my module from my interface task

EDIT: I tried out the methods mentioned below: I set my interface to wires instead of logic, and I drive 'Z from the driver that wants to relinquish control of the signal so that the other driver can take over. Still doesn't work as I see u_slave_dut not being driven from my interface. Any clues on what is wrong? My working example: https://www.edaplayground.com/x/4SSP
I am writing a testbench for a top-level module that has a number of sub-modules. I want to instantiate an interface and hook it up to one of my sub-modules, say my_submodule. Easy enough, and I can see my interface pins toggling when my_submodule pins are toggled. This makes for great observation.
Next, I decided I wanted to be able to toggle the pins myself from my interface (using a task). I realize this leads to 2 drivers on the same bus. So, is there a way for me to do this?
I created a small example of edaplayground to experiment, and here I see that none of my writes from my task in the interface actually toggle the pins on u_slave_dut. Also, I get no warnings from the compiler which bothers me too.
My working example is here: https://www.edaplayground.com/x/5fcP
testbench.sv
`include "my_interface.sv"
module tb;
bit clk = 1'b1;
bit control = 1'b0;
initial begin
forever begin
#5 clk = ~clk;
end
end
my_interface my_vif(clk);
assign my_vif.addr = (control)? tb.u_top.u_slave_dut.i_addr : 'hz;
assign my_vif.wdata = (control)? tb.u_top.u_slave_dut.i_wdata : 'hz;
assign my_vif.write = (control)? tb.u_top.u_slave_dut.i_write : 'hz;
top u_top(.clk(clk));
initial begin
#80 my_vif.master_write_something;
#160 $finish;
end
initial begin
$dumpfile("dump.vcd");
$dumpvars(0);
end
endmodule
interface.sv
interface my_interface(input clk);
logic [3:0] addr;
logic write;
logic [3:0] wdata;
logic [3:0] rdata;
logic resp;
clocking master_cb #(posedge clk);
input resp, rdata;
output addr, write, wdata;
endclocking
clocking slave_cb #(posedge clk);
input addr, write, wdata;
output resp, rdata;
endclocking
task master_write_something;
#(master_cb);
master_cb.write <= 1'b1;
#(master_cb);
master_cb.wdata <= 3'b101;
master_cb.addr <= 3'b111;
#(master_cb);
master_cb.write <= 1'b0;
endtask
task slave_write_something;
#(slave_cb);
slave_cb.resp <= 1'b1;
#(slave_cb);
slave_cb.rdata <= 3'b101;
#(slave_cb);
slave_cb.resp <= 1'b0;
slave_cb.rdata <= 3'b000;
endtask
endinterface
design.sv
module slave_dut (
input clk,
input [3:0] i_addr,
input [3:0] i_wdata,
input i_write,
output o_resp,
output [3:0] o_rdata
);
reg o_resp_reg;
reg [3:0] o_rdata_reg;
initial begin
o_resp_reg <= 1'b0;
o_rdata_reg <= 'h0;
end
always #(posedge clk) begin
if (i_write == 1'b1) begin
o_resp_reg <= 1'b1;
o_rdata_reg <= i_wdata;
end
else begin
o_resp_reg <= 1'b0;
o_rdata_reg <= 'h0;
end
end
assign o_resp = o_resp_reg;
assign o_rdata = o_rdata_reg;
endmodule : slave_dut
module master_dut (
input clk,
output [3:0] o_addr,
output [3:0] o_wdata,
output o_write,
input i_resp,
input [3:0] i_rdata
);
reg [3:0] o_addr_reg;
reg [3:0] o_wdata_reg;
reg o_write_reg;
initial begin
o_addr_reg <= 'h0;
o_wdata_reg <= 'h0;
o_write_reg <= 'h0;
repeat (2) #(posedge clk);
o_addr_reg <= 'hF;
o_wdata_reg <= 'hB;
o_write_reg <= 1'b1;
#(posedge clk);
o_addr_reg <= 'h0;
o_wdata_reg <= 'h0;
o_write_reg <= 'h0;
repeat (2) #(posedge clk);
o_addr_reg <= 'h4;
o_wdata_reg <= 'hD;
o_write_reg <= 1'b1;
#(posedge clk);
o_addr_reg <= 'h0;
o_wdata_reg <= 'h0;
o_write_reg <= 'h0;
end
assign o_addr = o_addr_reg;
assign o_wdata = o_wdata_reg;
assign o_write = o_write_reg;
endmodule : master_dut
module top(input clk);
wire [3:0] addr;
wire [3:0] wdata;
wire write;
wire resp;
wire [3:0] rdata;
master_dut u_master_dut (
.clk(clk),
.o_addr(addr),
.o_wdata(wdata),
.o_write(write),
.i_resp(resp),
.i_rdata(rdata)
);
slave_dut u_slave_dut (
.clk(clk),
.i_addr(addr),
.i_wdata(wdata),
.i_write(write),
.o_resp(resp),
.o_rdata(rdata)
);
endmodule
Any idea where I am going wrong?
I believe the one simulator you chose to run the simulator on does not give any warnings or errors. Any other simulator will correctly give the errors about mixing continuous assignments with procedural assignments from the clocking block.
If you are going to have the same signal driven from two different places, you need to deal with that by using a wire instead of a variable. You also need to turn off one of the drivers by setting it to high-impedance ('z), so the other driver can control the signal. This needs to be done regardless of whether the two drivers are within your design or between the design and testbench. I wrote a DVCon paper a few years ago that explains this in more detail.
As Dave explained, it is the only way to control the multi driver nets by enabling only one driver to drive the net at a time. And from hardware point of view as well, only one driver should drive any wire at a time.
This can be achieved in your design by using additional reg.
Please refer the following code.
module tb;
bit clk = 1'b1;
reg control = 1'b1;
initial begin
forever begin
#5 clk = ~clk;
end
end
my_interface my_vif(clk);
assign my_vif.addr = (control)? tb.u_top.u_slave_dut.i_addr : 'hz;
assign my_vif.wdata = (control)? tb.u_top.u_slave_dut.i_wdata : 'hz;
assign my_vif.write = (control)? tb.u_top.u_slave_dut.i_write : 'hz;
top u_top(.clk(clk));
initial begin
#80 my_vif.master_write_something (control);
#160 $finish;
end
initial begin
$dumpfile("dump.vcd");
$dumpvars(0);
end
endmodule
// Interface Task
task master_write_something (ref reg x);
#(master_cb);
x = 1'b0;
master_cb.write <= 1'b1;
#(master_cb);
master_cb.wdata <= 3'b101;
master_cb.addr <= 3'b111;
#(master_cb);
master_cb.write <= 1'b0;
endtask
And the dump file is as follow.

Event counter in verilog

i'm a verilog beginner, i'm try to write a "event counter" on verilog.... this is my code, but it work only with "period" set to 16'b0000000000000001, if try set period to 16'b0000000000001000, result(out_event) is always '0'.
Someone can help me to fix it ?
module mymodule(
input wire clk,
input wire enable,
input wire reset,
input wire [15:0] period,
input wire in_event,
output reg out_event
);
reg en = 1'b0;
reg re = 1'b0;
reg [15:0] count = 16'b0000000000000000;
always #(posedge clk) en <= enable;
always #(posedge clk) re <= reset;
always #(in_event)begin
if(in_event == 1'b1)begin
if(re)begin
count <= 0 ;
out_event <= 1'b0;
end else begin
if(en) begin
if(count == period-1)begin
out_event <= 1'b1;
count <= 0;
end else begin
count <=count + 1;
out_event <= 1'b0;
end
end else begin
out_event <= 1'b0;
end
end
end else begin
out_event <= 1'b0;
end
end
endmodule
thanks in advance
The counter counts number of posedge of in_event wire. So, can you use #(posedge in_event)?
I simulated your code, providing a testbench to it.
I do not have much knowledge about hardware synthesis, but personally, I would suggest to write your logic based on edge/level of clock.
This code works completely well. Have a look at this link.
You can configure various values of period in testbench, hope this will be helpful.
I came up with a test bench and the design for your problem and it works.
`timescale 1s / 1s
module TB();
reg clk;
reg enable;
reg reset;
reg [15:0] period;
wire out_event;
wire [15:0] counter;
initial begin
clk = 1'b0;
forever begin
#1 clk = ~clk;
end
end
stack_exch_code test (.clk(clk),
.enable(enable),
.reset(reset),
.period(period),
.out_event(out_event),
.tb_counter(counter)
);
integer i;
initial
begin
#(negedge clk) reset = 1'b1; enable = 1'b0; period = 16'h0000;
#(negedge clk) reset = 1'b0; enable = 1'b1; period = 16'h00FF;
for (i = 0 ; i < 500 ; i = i + 1) begin
#(negedge clk) period = period - 1;
#(posedge clk) $display ("Period = %h , Counter = %h, Out_Event = %b ", period, counter, out_event);
end
#(negedge clk) $finish;
end
endmodule //TB
module stack_exch_code (input clk,
input enable,
input reset,
input [15:0] period,
//input inevent,
output reg out_event,
output [15:0] tb_counter
);
// initialization doesnt matter in hardware, its not C or C++
reg en;
reg re;
reg [15:0] count;
always # (posedge clk) begin
re <= reset;
en <= enable;
end
always # (posedge clk) begin
if (re) begin
count <= 16'h0000;
out_event <= 1'b0;
end
else if (en) begin
if ((count == period - 1) && !(period == 16'h0000)) begin
out_event <= 1'b1;
count <= 16'h0000;
end
else if (!(period == 16'h0000)) begin
count <= count + 1;
out_event <= 1'b0;
end
else if (period == 16'h0000)
out_event <= 1'b0;
end
end
assign tb_counter = count;
endmodule //stack_exch_code

Resources