Reputation: 27
Task: Designing a 8-bit downcounter which takes an initial input value and start the downcount, and when count becomes 8'b0000_0000, it should automatically set to input value.
Ex: If given input is 8'b10010100, counter should start counting down, when value reaches 8'00000000, it should automatically reset to 8'b10010100, and again start downcount repeatedly. For this had written a modified D flip flop using behavioral method, which works as follows: When ld=0, output of d-flip flop q=d1 and q_bar=~d1 and when ld=1, q=d2 and q_bar=~d2 Here d2 stores the initial input values, and ld is being used as switch, i.e. when q=8'b00000000, ld=1 and sets counter output q=d2 and next cycle, ld=0 and takes d1 value.
Modified D-flip flop
module modified_d_flip_flop(q,q_bar,d1,d2,clk,ld
);
input d1,d2,clk,ld;
output q,q_bar;
reg q,q_bar;
always @(posedge clk)
begin
if(ld==0)
begin
q<=d1;
q_bar<=~d1;
end
else if(ld==1)
begin
q<=d2;
q_bar<=~d2;
end
else
begin
q<=q;
q_bar<=q_bar;
end
end
endmodule
Down Counter:
module down_counter(
input [7:0] d,
input clk,
input ld,
output [7:0] q,
output [7:0] q_bar
);
modified_d_flip_flop m_dff1 (.q(q[0]), .q_bar(q_bar[0]), .d1(q_bar[0]), .d2(d[0]), .clk(clk), .ld(ld));
modified_d_flip_flop m_dff2 (.q(q[1]), .q_bar(q_bar[1]), .d1(q_bar[1]), .d2(d[1]), .clk(q[0]), .ld(ld));
modified_d_flip_flop m_dff3 (.q(q[2]), .q_bar(q_bar[2]), .d1(q_bar[2]), .d2(d[2]), .clk(q[1]), .ld(ld));
modified_d_flip_flop m_dff4 (.q(q[3]), .q_bar(q_bar[3]), .d1(q_bar[3]), .d2(d[3]), .clk(q[2]), .ld(ld));
modified_d_flip_flop m_dff5 (.q(q[4]), .q_bar(q_bar[4]), .d1(q_bar[4]), .d2(d[4]), .clk(q[3]), .ld(ld));
modified_d_flip_flop m_dff6 (.q(q[5]), .q_bar(q_bar[5]), .d1(q_bar[5]), .d2(d[5]), .clk(q[4]), .ld(ld));
modified_d_flip_flop m_dff7 (.q(q[6]), .q_bar(q_bar[6]), .d1(q_bar[6]), .d2(d[6]), .clk(q[5]), .ld(ld));
modified_d_flip_flop m_dff8 (.q(q[7]), .q_bar(q_bar[7]), .d1(q_bar[7]), .d2(d[7]), .clk(q[6]), .ld(ld));
endmodule
Down counter Test Bench
module down_counter_tb;
reg [7:0] d;
reg clk;
reg ld;
wire [7:0] q;
wire [7:0] q_bar;
down_counter uut (
.d(d),
.clk(clk),
.ld(ld),
.q(q),
.q_bar(q_bar)
);
always #5 clk = ~clk;
initial begin
clk = 1;
ld = 1;
d = 8'b00000111;
end
initial begin
#20 ld = 0;
#20 ld = 1;
#30 ld = 0;
end
endmodule
Issue: If initial input i.e. d2=8'b11111111, then i am getting the downcounter it works properly for the above code, But if i give some thing like d2=8'10010011, then counter starts from 011, 010, 001 and 111, 110, 101, ........ it counts only the number of high bits from lsb + 1, if 0 is encountered next values till msb becomes x.
ld
function too is not working as expected, when ld
=0 instead of reset counter to initial input, it stops counter and starts it once ld
=0.
Upvotes: 1
Views: 187
Reputation: 27
Thanks @toolic
You code surely gave me an idea. Modified it a little to solve my issue
I am trying to design a frequency divider for my project for that i needed this downcounter.
ld - Use was to make the counter reset to my expected value when ld=0 and again make ld=1 next cycle to start the downcount and again when downcounter value became 0, make ld=0 to reset the counter to expected value. This had to go on forever.
In your testbench we have to set it many times. I just wanted to give one initial value and i wanted it to run forever.
I modified your code, to get my desired result. I removed ld and added, initial q = 0
Down Counter
module down_counter(
input [7:0] d,
input clk,
output reg [7:0] q
);
initial q = 0;
always @(posedge clk)
begin
if (q == 0)
begin
q <= d;
end
else
begin
q <= q-1;
end
end
endmodule
Testbench:
module down_counter_tb;
// Inputs
reg [7:0] d;
reg clk;
// Outputs
wire [7:0] q;
// Instantiate the Unit Under Test (UUT)
down_counter uut (
.d(d),
.clk(clk),
.q(q)
);
always #5 clk=~clk;
initial begin
// Initialize Inputs
d = 8'b00000100;
clk = 1;
end
endmodule
Upvotes: -1
Reputation: 61977
Your code is too hard to debug because you are not designing at the proper level of abstraction. You should always use the highest level of abstraction to make the design easier to understand. Instead of designing an individual flip-flop then trying to connect them together, just design a simple counter.
With all those module instance connections, you may have a simple connection bug.
Another potential issue is a simulation race condition. Every flip-flop uses a different clock signal.
Here is a common way to design a synchronous counter. It uses the same clock for all flops of the counter:
module down_counter (
input [7:0] d,
input clk,
input ld,
output reg [7:0] q
);
always @(posedge clk) begin
if (ld || (q == 0)) begin
q <= d;
end else begin
q <= q - 1;
end
end
endmodule
module down_counter_tb;
reg [7:0] d;
reg clk;
reg ld;
wire [7:0] q;
down_counter uut (
.d(d),
.clk(clk),
.ld(ld),
.q(q)
);
always #5 clk = ~clk;
initial begin
clk = 1;
ld = 1;
d = 7;
repeat (2) @(posedge clk);
ld <= 0;
repeat (15) @(posedge clk);
ld <= 0;
d <= 8'b1001_0011;
repeat (1) @(posedge clk);
ld <= 0;
repeat (500) @(posedge clk);
$finish;
end
endmodule
By using nonblocking assignments (<=
) and driving the inputs on @(posedge clk)
in the testbench (as is done in the design), we also avoid race conditions in the testbench.
You didn't provide a thorough description of the ld
signal. The code I showed loads the counter with the 8-bit input data (d
) when ld
=1. When ld
=0, the counter counts down. When it reaches 0, the counter is automatically reloaded with d
.
Upvotes: 1