verilogcounterclockbit-shiftsynchronous

Design Ones Counter Using Structural Level Modeling


Ones Counter Implement (Structural Level Modeling)

I am implementing a One's Counter that will count for the number of ones of an 8-bit binary value.

State Diagram

S0: start = 0

S1: R1 = Inport

S2:R3=0

S3:R2=1

S4:R4=R1 AND R2

S5:R3=R3+R4

S6:R1=R1 >> 1S4 (if Z=0)

S7: Outport=R3,
       done=1 (if Z=1)

S0

Pseudocode

Data := Inport
Ocount := 0
Mask := 1
while Data is not 0 repeat
    Temp := Data AND Mask
    Ocount := Ocount + Temp
    Data := Data >> 1
end while
Outport := Ocount


R1 := Inport
R3 := 0
R2 := 1
while ~Z repeat
    R4 := R1 AND R2
    R3 := R3 + R4
    R1 := R1 >> 1
end while
Outport := R3

I want to implement Ones Counter using Verilog Structural Level Modeling.
Below are my code, testbench, and the visualized result (with lots of debugging details in it):

Explanation

The flow is as follows

enter image description here

code

module Mux(A,B,S,Y, muxa, muxb, y);
    input [7:0] A,B;
    input S;
    output [7:0] Y;
    reg [7:0] Y;
    
    output [7:0] muxa, muxb, y;
    assign muxa = A;
    assign muxb = B;
    assign y = Y;
    always@(A or B or S)
    begin
        case(S)
            1'b0: Y = A;
            1'b1: Y = B;
        endcase
    end 
endmodule

module Regfile(WA,WE,RAA,REA,RAB,REB,DATA_W,DATA_A,DATA_B,clk,rst);
    input [2:0] WA, RAA, RAB; // WriteAddress, ReadAddressA, ReadAddressB
    input WE, REA, REB, clk, rst; // WriteEnable, ReadEnableA, ReadEnableB, clock, reset
    input [7:0] DATA_W;
    output [7:0] DATA_A, DATA_B;
    wire [7:0] DATA_A, DATA_B;
    reg [7:0] registers[7:0];
    
    assign DATA_A = REA? registers[RAA]:8'bz;
    assign DATA_B = REB? registers[RAB]:8'bz;
    
    always@(posedge clk, negedge rst)
        begin
            if(~rst) registers[0] <= 1'b0;
            else
                begin
                    if(WE) registers[WA] <= DATA_W;
                end
        end
endmodule

module ALU(A,B,sel,F, a, b);
    input [7:0] A,B;
    input [2:0] sel;
    output [7:0] F;
    reg [7:0] F;
    
    output [7:0] a,b;
    
    assign a = A;
    assign b = B;
    always@(sel or A or B)
        begin
            case(sel)
                3'b000: F = ~A;    // complement A
                3'b001: F = A & B; // and
                3'b010: F = A ^ B; // xor
                3'b011: F = A | B; // or
                3'b100: F = A - 1; // decrement A
                3'b101: F = A + B; // add
                3'b110: F = A - B; // subtract
                3'b111: F = A + 1; // increment A
            endcase
        end
endmodule

module Shifter(Data_in, SR, Data_out);
    input [7:0] Data_in;
    input SR;
    output [7:0] Data_out;
    reg [7:0] Data_out;
    
    always@(Data_in or SR)
        begin
            if(SR==1'b1) Data_out <= {1'b0, Data_in[7:1]};
            else Data_out <= Data_in;
        end
endmodule

module Controller(start, Z, clk, rst, ctrl, done, curState);
    input start, Z, clk, rst;
    output done;
    output [17:0] ctrl;
    reg done;
    reg [17:0] ctrl;
    reg [2:0] Current_State, Next_State;
    parameter S0 = 3'b000, S1 = 3'b001, S2 = 3'b010, S3 = 3'b011;
    parameter S4 = 3'b100, S5 = 3'b101, S6 = 3'b110, S7 = 3'b111;
    
    output [2:0] curState;
    
    always@(posedge clk, negedge rst)
        if(~rst) Current_State <= S0;
        else Current_State <= Next_State;

    assign curState = Current_State;
    always@(start or Z or Current_State)
        begin
            case(Current_State)
                S0:
                    begin
                        ctrl = 18'b0_0000_0000_0000_000_00;
                        done = 1'b0;
                        if(~start) Next_State = S0;
                        else Next_State = S1;
                    end
                S1:
                    begin
                        ctrl = 18'b1_0011_0000_0000_000_00;
                        done = 1'b0;
                        Next_State = S2;
                    end
                S2:
                    begin
                        ctrl = 18'b0_0111_0001_0001_101_00;
                        done = 1'b0;
                        Next_State = S3;
                    end
                S3:
                    begin
                        ctrl = 18'b0_0101_0001_0000_111_00;
                        done = 1'b0;
                        Next_State = S4;
                    end
                S4:
                    begin
                        ctrl = 18'b0_1001_0011_0101_001_00;
                        done = 1'b0;
                        Next_State = S5;
                    end
                S5:
                    begin
                        ctrl = 18'b0_0111_0111_1001_101_00;
                        done = 1'b0;
                        Next_State = S6;
                    end
                S6:
                    begin
                        ctrl = 18'b0_0011_0011_0001_101_10;
                        done = 1'b0;
                        if(Z) Next_State = S7;
                        else Next_State = S4;
                    end
                S7:
                    begin
                        ctrl = 18'b0_0000_0111_0001_101_01;
                        done = 1'b1;
                        Next_State = S0;
                    end
            endcase
        end
endmodule

module DataPath(Inport, ctrl, clk, rst, Outport, Z, bsf, di, a , b, muxa, muxb, y);
    input [7:0] Inport;
    input [17:0] ctrl;
    input clk, rst;
    output [7:0] Outport;
    output Z;
    wire [7:0] B_M, B_RA, B_RB, B_ALU, B_SF;
    
    output [7:0] bsf, di, a, b, muxa, muxb, y;
    
    Mux mux(.A(B_SF), .B(Inport), .S(ctrl[17]), .Y(B_M), .muxa(muxa), .muxb(muxb), .y(y));
    Regfile regfile(.WA(ctrl[16:14]), .WE(ctrl[13]), .RAA(ctrl[12:10]), .REA(ctrl[9]), .RAB(ctrl[8:6]), .REB(ctrl[5]), .DATA_W(B_M), .DATA_A(B_RA), .DATA_B(B_RB), .clk(clk), .rst(rst));
    ALU alu(.A(B_RA), .B(B_RB), .sel(ctrl[4:2]), .F(B_ALU), .a(a), .b(b));
    Shifter shifter(.Data_in(B_ALU), .SR(ctrl[1]), .Data_out(B_SF));
    
    assign Outport = ctrl[0]? B_SF:8'bz;
    assign Z = ~|B_SF; 
    assign di = B_ALU;
    assign bsf = B_SF;
endmodule

module OnesCounter(start, Inport, clk, rst, Outport, done, curState, bsf, di, a, b, muxa, muxb, y);
    input start, clk, rst;
    input [7:0] Inport;
    output done;
    output [7:0] Outport;
    
    output [2:0] curState;
    wire Z;
    wire [17:0] ctrl;
    output [7:0] bsf, di, a, b, muxa, muxb, y;
    
    Controller controller(.start(start), .Z(Z), .clk(clk), .rst(rst), .ctrl(ctrl), .done(done), .curState(curState));
    DataPath dataPath(.Inport(Inport), .ctrl(ctrl), .clk(clk), .Outport(Outport), .Z(Z), .bsf(bsf), .di(di), .a(a), .b(b), .muxa(muxa), .muxb(muxb), .y(y));
endmodule

Testbench

module testbench();
    reg [7:0] Inport;
    reg start, clk, rst;
    wire [7:0] Outport;
    wire done;
    
    wire [2:0] curState;
    wire [7:0] bsf, di, a, b, muxa, muxb, y;
    
    OnesCounter test(.start(start), .Inport(Inport), .clk(clk), .rst(rst), .Outport(Outport), .done(done), .curState(curState), .bsf(bsf), .di(di), .a(a), .b(b), .muxa(muxa), .muxb(muxb), .y(y));
    initial #400 $finish;
    initial begin clk = 0; forever #5 clk = ~clk; end
    initial fork
        rst = 0;
        start = 0;

        #3 rst = 1;
        #30 start = 1; Inport = 215; // 215 = 1101 0111
        #40 start = 0;
    join
endmodule

Visualized Result

enter image description here

My Assumption

I think the problem is caused by the clock, but I have no idea how to fix it. It seems that the output values are all oscillating so most of them produce an X as a result.


Solution

  • When I compile your code, I see this warning:

        DataPath dataPath(.Inport(Inport), .ctrl(ctrl), .clk(clk), .Outport(Outport), .Z(Z), .bsf(bsf), .di(di), .a(a), .b(b), .muxa(muxa), .muxb(muxb), .y(y));
                        |
    xmelab: *W,CUVWSI : 1 input port was not connected:
    xmelab:  rst
    

    If your simulator does not generate a warning, you can try your code on other simulators on the EDA Playground site.

    To fix the warning, you need to connect the rst signal to the dataPath instance. Change:

    DataPath dataPath(.Inport(Inport), .ctrl(ctrl), .clk(clk), .Outport(Outport), .Z(Z), .bsf(bsf), .di(di), .a(a), .b(b), .muxa(muxa), .muxb(muxb), .y(y));
    

    to:

    DataPath dataPath(.rst(rst), .Inport(Inport), .ctrl(ctrl), .clk(clk), .Outport(Outport), .Z(Z), .bsf(bsf), .di(di), .a(a), .b(b), .muxa(muxa), .muxb(muxb), .y(y));
    

    This clears up a lot of the unknowns (x's).