I need to design a circuit that can count 1011
in a sequence of bits. For example, if the sequence is as shown in the picture, the count should be 1
, but it isn't. I know I'm reading input w
not in a sequence way, but I don't know how to do it either.
w
is our input sequence andCS
andNS
are current state and next state. and parameters are our states. second picture's second state machine is what I used there is a slight difference between those two SMs.
main logic:
module serialCounter(w,clk,resetn,z);
input w,clk,resetn;
output reg z;
reg [2:0] CS,NS;
reg [7:0] count;
parameter S0=3'b000, S1=3'b001, S2=3'b010, S3=3'b011, S4=3'b100;
always @(w,CS)
case(CS)
S0:if(w==1)
begin
NS=S1;
end
else
begin
NS=S0;
end
S1:if(w==1)
begin
NS=S2;
end
else
begin
NS=S0;
end
S2:if(w==1)
begin
NS=S2;
end
else
begin
NS=S3;
end
S3:if(w==1)
begin
NS=S4;
end
else
begin
NS=S0;
end
S4:begin NS=S0;end
endcase
always @(posedge clk, negedge resetn)
begin
if(resetn == 0)
CS<=S0;
else
CS<=NS;
end
always @(CS)
begin
if(CS==S4)
begin
z=1;
count<=count+1;
end
end
endmodule
testbench:
`timescale 1ns/1ns
module counterTB();
reg w,clk,resetn;
reg [2:0] CS,NS;
wire z;
wire [7:0] count;
integer i;
serialCounter sk(.w(w),.clk(clk),.resetn(resetn),.z(z));
initial
begin
resetn = 1'b0;
clk = 1'b0;
CS=3'b000;
end
initial
begin
for(i=0;i<255;i=i+1)
@(posedge clk, negedge resetn) w=i;
end
always #5 clk = ~clk;
always @(posedge clk, negedge resetn) $monitor("w=%b, z=%b, count=%d", w,z,count);
endmodule
I think, there is an easier way to created this state machine. The following example reg [3:0]
pattern register which keeps 4 bits of the pattern. Then it just compares the pattern with the desired one (seq in this case).
module serialCounter(w, clk, resetn, z, counter);
input w, clk, resetn;
output reg z;
output reg[7:0] counter;
reg[3:0] pattern, tmp;
parameter seq = 4'b1011;
always@(posedge clk) begin
if (!resetn) begin
pattern <= 0;
counter <= 0;
end
else begin
tmp = (pattern << 1) | w;
if (tmp == seq) begin
counter <= counter + 1;
z <= 1;
end
else
z <= 0;
pattern <= tmp;
end
end
endmodule
module counterTB();
reg w,clk,resetn;
reg [2:0] CS,NS;
wire z;
reg [7:0] count;
integer i;
serialCounter sk(.w(w), .clk(clk), .resetn(resetn), .z(z), .counter(count));
initial
begin
resetn = 1'b0;
clk = 1'b0;
CS=3'b000;
#30 resetn=1;
#5000 $finish;
end
always #5 clk = ~clk;
initial $monitor("clk=%b, w=%b, z=%b, count=%d pattern=%b", clk, w,z, count, sk.pattern);
initial begin
w = 0;
forever #10 w = $random;
end
endmodule
I also fixed a couple of things in the tb module, e.g. $monitor should be used int an initial block. I changed the way you generate w
as well.