Verilog中的CRC生成器:始终阻止

时间:2018-03-25 02:39:42

标签: verilog modelsim

我正在尝试在ModelSim中模拟8位数据的16位CRC生成器中的代码。生成CRC字节的逻辑如下, 1.创建一个16位crc寄存器并将其初始化为全零。 2.现在将数据字节的每个位与crc寄存器的位0进行比较,即(data [counter] == crc [0]) 3.如果比较为真,则右移crc寄存器,即crc>> 1并将其保存到crc寄存器。 4.如果比较为假,则右移crc寄存器并用16'h1021(多项式发生器)xor结果。

现在我不确定我在always块内通过FOR循环遍历数据字节的实现是否正确;在我的模拟中,for循环遍历时钟的第一个正边沿上的数据字节,如模拟块中所示。

我的结果对于CRC生成也是错误的。

即。数据= 0xF881正确CRC = 0x1CED

下面是带有测试平台的Verilog代码(Serial_CRC)和仿真结果。

//http://www.asic-world.com/examples/verilog/serial_crc.html#Serial_CRC

`timescale 1ns/1ns
`define WIDTH 16
//**************************************************************************
module Serial_CRC_wTB();
//**************************************************************************

    reg in_enable;
    reg in_clk;
    reg in_rst_n;
    reg [`WIDTH-9:0] in_data;
    wire [`WIDTH-1:0] out_crcOutput;

    Serial_CRC TS (.i_data(in_data), .o_crcOutput(out_crcOutput), .i_clk(in_clk), .i_rst_n(in_rst_n), .i_enable(in_enable));

    initial
        begin
            in_clk = 1'b0 ;in_enable = 1'b0; in_rst_n = 1'b1;
            #1 in_rst_n = 1'b0;
            #2 in_rst_n = 1'b1; in_enable = 1'b1;
            @(negedge in_clk) in_data = 8'hF8;
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(negedge in_clk) in_data = 8'h81;
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            #20 $finish;
        end 

    always 
        #1 in_clk = ~in_clk;

endmodule // Serial_CRC_wTB


//**************************************************************************
module Serial_CRC (input [`WIDTH-9:0] i_data,input i_clk,input i_rst_n,input i_enable, output [`WIDTH-1:0] o_crcOutput);
//**************************************************************************

reg [`WIDTH-1:0] crc;
reg [`WIDTH-9:0] d; 

integer counter;

always @ (posedge i_clk)    begin
    if (~i_rst_n)   begin
        crc <= {16{1'b0}};
        d   <= {8{1'b0}};
    end 
    else if (i_rst_n && i_enable) begin
        d <= i_data;
        for (counter = 0 ; counter <= `WIDTH-9 ; counter = counter + 1) begin 
            if (d[counter] == crc[0])
                crc <= crc >> 1;
            else if (d[counter] != crc[0]) begin
                crc <= crc >> 1;
                crc <= crc ^ 16'h1021; 
            end // else if block
        end // for loop block
    end  // else if block
end // always block


assign o_crcOutput = crc;

endmodule // Serial_CRC

Snapshot from ModelSim

2 个答案:

答案 0 :(得分:0)

我猜你在这里误用了非阻塞作业:

           crc <= crc >> 1;
           crc <= crc ^ 16'h1021; 

第一行不会立即更改为crc,第二行将对旧值crc进行操作

您需要以下内容:

reg [`WIDTH-1:0]tmp ;
...
else if (d[counter] != crc[0]) begin
            tmp = crc >> 1;
            crc <= tmp ^ 16'h1021; 
        end // else if block 

或将其分成一行:

crc <= (crc >> 1) ^ 16'h1021; 

答案 1 :(得分:0)

我通过FSM工作并发布这个答案是一个学习曲线,CRC寄存器初始化和引入数据字节的时间仍然存在挑战。

模拟的答案在这里显示。

Crc输出:0000 Crc输出:0000 Crc输出:0000 Crc输出:0000 Crc输出:1021 Crc输出:0810 Crc输出:1429 Crc输出:0a14 Crc输出:152b Crc输出:0a95 Crc输出:156b Crc输出:1a94 Crc输出:0d4a Crc输出:06a5 Crc输出:1373 Crc产量:1998年 Crc输出:1ced

//http://www.asic-world.com/examples/verilog/serial_crc.html#Serial_CRC

`timescale 1ns/1ns
`define WIDTH 16
//**************************************************************************
module Serial_CRC_wTB();
//**************************************************************************

    //reg in_enable;
    reg in_clk;
    reg in_rst_n;
    reg [`WIDTH-9:0] in_data;
    wire [`WIDTH-1:0] out_crcOutput;

    Serial_CRC TS (.i_data(in_data), .o_crcOutput(out_crcOutput), .i_clk(in_clk), .i_rst_n(in_rst_n));

    initial
        begin
            in_clk = 1'b0 ; in_rst_n = 1'b0; in_data = 8'hF8;
            #1 in_rst_n = 1'b0;
            #2 in_rst_n = 1'b1;
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 0 
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 1
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 2
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 3
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 4
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 5
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 6
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 7
            @(negedge in_clk) in_data = 8'h81;
            @(posedge in_clk) $display("Crc Output :%h",out_crcOutput); // 8
            //@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
             @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
             @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
             @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
             @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
             @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
             @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
             @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
             @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
             //@(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            // @(posedge in_clk) $display("Crc Output :%h",out_crcOutput);
            #1 $finish;
        end 

    always 
        #1 in_clk = ~in_clk;

endmodule // Serial_CRC_wTB


//**************************************************************************
module Serial_CRC (input [`WIDTH-9:0] i_data,input i_clk,input i_rst_n, output [`WIDTH-1:0] o_crcOutput);
//**************************************************************************

    parameter         S0 = 3'b000;      //BIT[0]
    parameter         S1 = 3'b001;      //BIT[1]
    parameter         S2 = 3'b010;      //BIT[2]
    parameter         S3 = 3'b011;      //BIT[3]
    parameter         S4 = 3'b100;      //BIT[4]
    parameter         S5 = 3'b101;      //BIT[5]
    parameter         S6 = 3'b110;      //BIT[6]
    parameter         S7 = 3'b111;      //BIT[7]

    reg [2:0] curr_state;
    reg [2:0] next_state;

    reg [7:0] d;
    reg [15:0] crc;

    // Sequential logic for storing current state
    always @ (posedge i_clk, negedge i_rst_n) begin
        if (~i_rst_n) begin 
            curr_state <= S0;
            crc <= {16{1'b0}}; end
        else 
            curr_state <= next_state;
    end 

    always @ (curr_state, d) begin
        case (curr_state)
            S0: next_state <= S1;

            S1: next_state <= S2;

            S2: next_state <= S3;   

            S3: next_state <= S4;

            S4: next_state <= S5;

            S5: next_state <= S6;

            S6: next_state <= S7;

            S7: next_state <= S0;                       
        endcase // curr_state
    end 

 // need to fix the blocking versus the non-blocking case on the state variables
    // Output Logic
    always @ (posedge i_clk) begin 

        case(curr_state)
            S0: begin 
                d = i_data;

                if (d[0] == crc[0])
                    crc = crc >> 1'b1;
                else if (d[0] != crc[0]) begin
                        crc = crc >> 1'b1;
                        crc = crc ^ 16'h1021; end 
                    end // S0
            S1: begin 
                if (d[1] == crc[0])
                    crc = crc >> 1'b1;
                else if (d[1] != crc[0]) begin
                        crc = crc >> 1'b1;
                        crc = crc ^ 16'h1021; end 
                    end // S1
            S2: begin 
                if (d[2] == crc[0])
                    crc = crc >> 1'b1;
                else if (d[2] != crc[0]) begin
                        crc = crc >> 1'b1;
                        crc = crc ^ 16'h1021; end 
                    end // S2
            S3: begin 
                if (d[3] == crc[0])
                    crc = crc >> 1'b1;
                else if (d[3] != crc[0]) begin
                        crc = crc >> 1'b1;
                        crc = crc ^ 16'h1021; end 
                    end // S3
            S4: begin 
                if (d[4] == crc[0])
                    crc = crc >> 1'b1;
                else if (d[4] != crc[0]) begin
                        crc = crc >> 1'b1;
                        crc = crc ^ 16'h1021; end 
                    end // S4
            S5: begin 
                if (d[5] == crc[0])
                    crc = crc >> 1'b1;
                else if (d[5] != crc[0]) begin
                        crc = crc >> 1'b1;
                        crc = crc ^ 16'h1021; end 
                    end // S5
            S6: begin 
                if (d[6] == crc[0])
                    crc = crc >> 1'b1;
                else if (d[6] != crc[0]) begin
                        crc = crc >> 1'b1;
                        crc = crc ^ 16'h1021; end 
                    end // S6
            S7: begin 
                if (d[7] == crc[0])
                    crc = crc >> 1'b1;
                else if (d[7] != crc[0]) begin
                        crc = crc >> 1'b1;
                        crc = crc ^ 16'h1021; end 
                    end // S7
        endcase // curr_state
        end //always

assign o_crcOutput = crc;       
endmodule // Serial_CRC

和模拟时序图。 Snap 1

Snap2