How to build an up-counter in Verilog - verilog

I have a problem with designing an up-counter. I am trying to implement a Single-cycle MIPS with Verilog, so I am trying to implement a Program counter.
I just need the main idea about how to built a counter and test it. I am new to Verilog, so I don't know where I've gone wrong.
This is my counter.v:
module PC (Clk, CLR, Q);
input Clk, CLR;
output [31:0] Q;
reg [31:0] tmp;
always #(posedge Clk or posedge CLR)
begin
if (CLR)
tmp = 4'b0000;
else
tmp = tmp + 1'b1;
end
assign Q = tmp;
endmodule
And this is my testbench file:
define DELAY 20
module PC_testbench ();
reg clk ;
reg clr ;
wire [31:0] q;
PC exec ( clk , clr , q );
initial clk = 0;
initial clr = 0;
initial begin
clk=~clk;
#`DELAY;
clk=~clk;
#`DELAY;
clk=~clk;
#`DELAY;
clk=~clk;
end
initial begin
$monitor("clk = %b pc_next = %b ",clk , q );
end
endmodule
I got 32 x's as my result. Any ideas?
This is my result:
# clk = 1 pc_next = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# clk = 0 pc_next = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# clk = 1 pc_next = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# clk = 0 pc_next = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Your problem is that counter tmp is initially 32'bx, and it needs to see a rising edge of CLR or be 1 during a rising edge of Clkbefore being reset to 32'b0.

Related

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:

Verilog accumulation code error

I am having a problem with accumulator code in Verilog. I simply generate pseudo random signals. Then, change the random signal level -1 to 1 from 0 to 1 so it is signed. Later, obtained 'acmin'. In this point, I need to accumulate 'acmin' signals. Debugger doesn't give me any error but I can't see any result. Can you help me to find problem?
module lfsr(clk, rst, seed, load, R, acc);
input [3:0] R;
input [26:0] seed;
input load;
input rst;
input clk;
reg [3:0]q;
wire [3:0] S;
wire overflow;
wire [3:0] acmin ;
wire [26:0] state_out;
wire [26:0] state_in;
output [7:0] acc;
reg [7:0] acc;
flipflop F[26:0] (state_out, clk, rst, state_in);
mux M1[26:0] (state_in, load, seed, {state_out[25],state_out[24],state_out[23],state_out[22],state_out[21],state_out[20],state_out[19],state_out[18],state_out[17],state_out[16],state_out[15],state_out[14],state_out[13],state_out[12],state_out[11],state_out[10],state_out[9],state_out[8],state_out[7],state_out[6],state_out[5],state_out[4],state_out[3],state_out[2], state_out[1], state_out[0], nextbit});
xor G1(nextbit, state_out[5], state_out[2], state_out[1], state_out[26]);
// Pseudorandom generator
always#(clk) begin
if (state_out[26]==0)
q=4'b1111; // 0 to -1
else
q=4'b0001; //1 to 1
end
assign acmin= R*q; // accumulator input
always#(clk) begin
if(rst)
acc = 8'b00000000;
else
acc = acc + acmin;
end
endmodule
Test bench;
module lfsrtst;
reg [3:0] R;
reg clk;
reg rst;
reg [26:0] seed;
reg load;
wire [7:0] acc;
lfsr lfsr(clk, rst, seed, load, R, acc);
initial
begin
clk = 0;
load = 0;
seed = 0;
rst = 0;
R=0;
#10 rst = 1;
#10 rst = 0;
#50 R = 4'b0111;
#50 R = 4'b0010;
#100 R = 4'b1111;
#50 R = 4'b1011;
#150 R = 4'b1101;
#50 R = 4'b1000;
end
// drive clock
always
#50 clk = !clk;
// program lfsr
initial begin
#100 seed = 27'b000000110000011000001000001;
load = 1;
#100 load = 0;
#1400 $stop;
end
endmodule
I have 'acmin' as I desired. I want to accumulate 'acmin' variable every time the edge of the clock rises and falls. However, 'acc' results nothing so what is the error?
Thanks.
The main problem that I see is that you have a synchronous reset:
always#(clk) begin
if(rst)
acc = 8'b00000000;
else
acc = acc + acmin;
end
But in your testbench you only strobe the reset for #20
#10 rst = 1;
#10 rst = 0;
This is too short, and the reset is never detected.
If you make these delays longer, then the problem should be fixed.
#100 rst = 1;
#100 rst = 0;
// then later
// program lfsr
initial begin
# also delay this so that it comes after the reset
#300 seed = 27'b000000110000011000001000001;
Alternatively you could make the reset asynchronous.
always#(clk or posedge rst) begin
I would try imply a flip-flop here by adding the posedge and converting to '<='
always#(posedge clk) begin
if(rst)
acc <= 8'b00000000;
else
acc <= acc + acmin;
end

Verilog: one clock cycle delay using register

I'm trying to delay two signals. I wrote a register to do that and instantiated it but a strange thing happens. Delaying "state" signal seems to work, but delaying "nb_bits" signal doesn't.
Here's my code for the register:
`timescale 1ns / 1ps
module register(
input CLK,
input clr,
input en,
input [7:0] in,
output [7:0] out
);
reg [7:0] temp;
always # (posedge CLK or posedge clr) begin
if (clr) begin
temp <= 8'b00010000;
end
else if (en) begin
temp <= in;
end
else begin
temp <= temp;
end
end
assign out = temp;
endmodule
And that's ma instantiation:
wire [3:0] nbb;
nb_bits_register nb_bits_reg(
.CLK(CLK),
.clr(clr),
.en(en),
.in(nb_bits),
.out(nbb)
);
wire [7:0] stt;
register state_reg(
.CLK(CLK),
.clr(clr),
.en(en),
.in(state),
.out(stt)
);
nb_bits_register module is analogical; I didn't want to parametrize before solving this problem.
`timescale 1ns / 1ps
module nb_bits_register(
input CLK,
input clr,
input en,
input [3:0] in,
output [3:0] out
);
reg [3:0] temp;
always # (posedge CLK or posedge clr) begin
if (clr) begin
temp <= 4'b0000;
end
else if (en) begin
temp <= in;
end
else begin
temp <= temp;
end
end
assign out = temp;
endmodule
And here's a simulation:
enter image description here
And testbench:
`timescale 1ns / 1ps
module state_machine_tb();
reg CLK, clr, en;
reg [7:0] symbol;
reg [3:0] nb_bits;
wire [7:0] state;
initial begin
CLK <= 1;
clr <= 0;
en <= 0;
symbol <= 8'b00110010;
nb_bits <= 1;
#10
clr <= 1;
en <= 1;
#10
clr <= 0;
symbol <= 8'b00110001;
nb_bits <= 1;
#10
symbol <= 8'b00110010;
nb_bits <= 2;
#10
symbol <= 8'b00110001;
nb_bits <= 1;
#10
symbol <= 8'b00110001;
nb_bits <= 1;
#10
symbol <= 8'b00110000;
nb_bits <= 3;
#10
$finish;
end
always begin
#5 CLK <= ~CLK;
end
state_machine state_machine_inst(
.CLK(CLK),
.clr(clr),
.en(en),
.symbol(symbol),
.nb_bits(nb_bits),
.state(state)
);
endmodule
It does seem like a rase condition in the scheduler. By definition from the Verilog LRM, the order of evaluating procedural blocks (always blocks and initial blocks) is indeterminate. You might notice a pattern with a particular simulator and version, but that patter can change when changing the simulator or changing the version of the same simulator.
Use blocking assignment with your clock (ex: always #5 CLK = ~CLK;). With will guarantee the CLK will be updated before other stimulus.
In the test bench, change all the #10 to #(posedge CLK). The timing will be the same, however it guarantees CLK was updated before evaluating the new values symbol and other stimulus.
FYI: If you change output [7:0] out to output reg [7:0] out you can assign out directly in your always block, removing the need for temp. This doesn't change anything functionally; just fewer variables and lines of code.
It seems like a race condition: your changes of nb_bits coincide with positive edges of CLK, so there's an ambiguity resolved by the simulator in this way:
change nb_bits (from 1 to 2, etc.)
change CLK from 0 to 1
execute in nb_bits_register: if (en) temp <= in; ... assign out = temp;
As the result, out = in in nb_bits_register.
A solution is to avoid this coincidence, e.g. by changing the first #10 in the testbench to #11.

6-bit binary counter with LED output

I'm really new to verilog world and i can't understand why my program return nothing. I'm trying to make simple 6-bit up counter that counts on button press. The code is
module top (CLK, BTN_RST, LED, BTN_C);
input CLK, BTN_RST, BTN_C; //
output [5:0]LED;
reg [5:0]LED;
always #(posedge CLK or posedge BTN_RST) begin
if (BTN_RST) begin
LED <= 6'b000000;
end
else begin: COUNT
while (BTN_C) begin
LED <= LED + 1'b1;
disable COUNT;
end
end
end
endmodule
And the test bench is
module top_test;
reg CLK;
reg BTN_RST;
reg BTN_C;
reg [5:0]LED;
initial begin
CLK = 0;
BTN_RST = 0;
BTN_C = 0;
#1 BTN_RST = 1;
#5 BTN_RST = 0;
#10 BTN_C = 1;
#50;
end
always
begin
#5 CLK=~CLK;
end
This code compiles and runs (as i can see on iSim), but LED output gives me XXXXXX. I think I'm not only got some mistakes here, but also can't understand how test bench works and how to make right assignments on input and output. Can anyone please help me?
You need to add an instance of your design in your testbench. Now, LED is no longer X; I see it counting up from 0.
module top_test;
reg CLK;
reg BTN_RST;
reg BTN_C;
wire [5:0]LED;
initial begin
CLK = 0;
BTN_RST = 0;
BTN_C = 0;
#1 BTN_RST = 1;
#5 BTN_RST = 0;
#10 BTN_C = 1;
#50;
end
always
begin
#5 CLK=~CLK;
end
top dut (
// Inputs:
.BTN_C (BTN_C),
.BTN_RST (BTN_RST),
.CLK (CLK),
// Outputs:
.LED (LED)
);
endmodule
I changed reg to wire for LED in top_test. I see LED increasing from 0 when I use VCS as a simulator. But, when I switch to Incisive, LED stays at 0.
I think your while/disable code is causing a problem. I have recoded it to look a little more standard:
module top (CLK, BTN_RST, LED, BTN_C);
input CLK, BTN_RST, BTN_C; //
output [5:0]LED;
reg [5:0]LED;
always #(posedge CLK or posedge BTN_RST) begin
if (BTN_RST) begin
LED <= 6'b000000;
end else if (BTN_C) begin
LED <= LED + 1'b1;
end
end
endmodule

Trying to debug program counter / instruction memory module in single-cycle CPU in Verilog

Our assignment is to build a rudimentary single-cycle CPU in Verilog, but I'm not getting even more fundamental modules of it correct. For instance, to test the Instruction Memory module, we've been given a text file "hw3Test.txt" with instructions in hex, and I'm trying to slurp that into the IM.
00221820
AC010000
8C240000
10210001
00001820
00411822
When I run a testbench, I see that the only instructions that get into memory are the second, third, and fourth lines. Here's the IM module:
module IM(addr, clk, inst);
input [31:0] addr;
input clk;
output reg [31:0] inst;
reg [31:0] mem [255:0];
initial begin
$readmemh("hw3Test.txt", mem);
end
always #( posedge clk) begin
inst=mem[addr[31:2]];
end
endmodule
And the testbench:
module imtest;
// Inputs
reg [31:0] addr;
reg clk;
// Outputs
wire [31:0] inst;
// Instantiate the Unit Under Test (UUT)
IM uut (
.addr(addr),
.clk(clk),
.inst(inst)
);
initial begin
// Initialize Inputs
addr = 0;
clk = 0;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
clk = 0;
addr = 0;
#100;
forever begin
#20;
clk = ~clk;
addr = addr + 4;
end
end
endmodule
I'm also not sure I'm even getting the PC-to-IM module correct, because aside from the initialized values, everything but the rst and clk signals show no valid values. Can anyone point out where I'm going wrong?
module pc_im(
// Inputs
rst, clk, PCin,
// Outputs
inst, PCout
);
input clk, rst;
input [31:0] PCin;
output reg [31:0] inst;
output reg [31:0] PCout;
PC mypc (
.clk(clk),
.rst(rst),
.PCin(PCin),
.PCout(PCout)
);
IM myim(
.clk(clk),
.addr(PCout),
.inst(inst)
);
endmodule
Here's the PC.v module:
module PC(rst, clk, PCin, PCout);
input clk, rst;
input [31:0] PCin;
output reg [31:0] PCout;
always #(posedge clk) begin
if (rst) PCout <= 0;
else PCout <= PCin + 4;
end
endmodule
And finally, the testbench:
module pcimtest;
// Inputs
reg rst;
reg clk;
reg [31:0] PCin;
// Outputs
wire [31:0] inst;
wire [31:0] PCout;
// Instantiate the Unit Under Test (UUT)
pc_im uut (
.rst(rst),
.clk(clk),
.PCin(PCin),
// Outputs
.inst(inst),
.PCout(PCout)
);
initial begin
// Initialize Inputs
rst = 1;
clk = 0;
PCin = 0;
// Wait 100 ns for global reset to finish
#100;
rst = 0;
forever begin
#100;
clk <= ~clk;
PCin <= PCout;
end
// Add stimulus here
end
endmodule
Here are a few things that look suspect.
Problem 1
It is normally good to use non-blocking assignments in blocks intended to infer registers.
i.e. change
always #( posedge clk) begin
inst=mem[addr[31:2]];
end
to
always #( posedge clk) begin
inst<=mem[addr[31:2]];
end
Problem 2
You are changing signals twice per clock cycle, once on negative edge and once on positive edge.
Change:
forever begin
#20;
clk = ~clk;
addr = addr + 4;
end
to
forever begin
#20;
clk = 1;
#20;
clk = 0;
addr = addr + 4;
end
Problem 3
You are using synchronous resets but not supplying a clock during reset.
Consider the code
always #(posedge clk) begin
if (rst) PCout <= 0;
else PCout <= PCin + 4;
end
This block will only activate on positive clock edges. However, you make reset high while the clock is paused so no reset will happen.
Change
rst = 1;
clk = 0;
PCin = 0;
// Wait 100 ns for global reset to finish
#100;
to
rst = 1;
clk = 0;
PCin = 0;
#20
clk = 1;
#20
clk = 0;
// Wait 100 ns for global reset to finish
#100;

Resources