使用结构级别建模设计计数器(问题已解决)

问题描述 投票:0回答:1

Ones Counter 工具(结构层面建模)

我正在实现一个计数器,它将计算 8 位二进制值的个数。

状态图

S0

start
=
0


S1:
R1
=
Inport


S2:
R3
=
0


S3:
R2
=
1


S4
R4
=
R1
AND
R2


S5
R3
=
R3
+
R4


S6:
R1
=
R1
>>
1
S4(如果
Z
=
0


S7
Outport
=
R3

       
done
=
1
(如果
Z
=
1


S0

伪代码

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

我想使用 Verilog 结构层次建模来实现 Ones Counter
下面是我的

code
testbench
和可视化的
result
(其中有很多调试细节):

说明

流程如下

代码

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

测试台

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

可视化结果

我的假设

我认为问题是由时钟引起的,但我不知道如何解决它。看起来输出值都在振荡,因此大多数输出值都会产生

X

verilog counter clock bit-shift synchronous
1个回答
0
投票

当我编译你的代码时,我看到这个警告:

    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

如果您的模拟器没有生成警告,您可以尝试在 EDA playgrpond 网站上的其他模拟器上进行编码。

要修复警告,您需要将

rst
信号连接到
dataPath
实例。变化:

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));

至:

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));

这消除了很多未知数(x)。

© www.soinside.com 2019 - 2024. All rights reserved.