CRC循环冗余校验(verilog源码及仿真)



循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或电脑文件等数据产生简短固定位数校验码的一种散列函数,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测的。

步骤:选一个多项式,转成n二进制码gx_crc_n,在原始数据后加上n-10,模2整除gx_crc_n,将最后的五位余数补到原始码的末尾。

 

现假设选择的CRC生成多项式为GX= X4 + X3 + 1,要求出二进制序列10110011CRC校验码。下面是具体的计算过程:

 

①将多项式转化为二进制序列,由GX= X4 + X3 + 1可知二进制一种有五位,第4位、第三位和第零位分别为1,则序列为11001

 

②多项式的位数位5,则在数据帧的后面加上5-10,数据帧变为101100110000,然后使用模2除法除以除数11001,得到余数。

 CRC循环冗余校验(verilog源码及仿真)_第1张图片

Verilog源码:多项式为 X5+X4 + X2+ 1    ---110101

 

 

`timescale 1ns / 1ps

//////////////////////////////////////////////////////////////////////////////////

// Company:

// Engineer:

//

// Create Date:    19:35:30 04/24/2018

// Design Name:

// Module Name:    crc_test

// Project Name:

// Target Devices:

// Tool versions:

// Description:

//

// Dependencies:

//

// Revision:

// Revision 0.01 - File Created

// Additional Comments:

//

//////////////////////////////////////////////////////////////////////////////////

module crc_test(

 input data_en,

 input [9:0] data_in,    

 

    input clk,

    input rst_n,

 output reg [4:0] crc_out,      //最后的余数,将其附加至data_out末尾

 output reg [14:0] data_out

    );

wire [14:0] data_in_reg;

//reg[3:0] cnt;

reg [5:0] crc_out_r;

reg crc_start;

parameter gx_crc_8=6'h35;

 

 

reg crc_end;

 

//crc 时钟

reg clk_crc;

reg [3:0] cnt;

 

always @(posedge clk or negedge rst_n)

begin

if(!rst_n)  begin

cnt<=0;

clk_crc<=0;

end

else if(cnt==4'd5) begin

cnt<=0;

clk_crc<=~clk_crc;

end

else

cnt<=cnt+1;

end

reg data_en1,data_en2;

wire data_en_pos;

 

always @(posedge clk or negedge rst_n)

begin

if(!rst_n) begin

data_en1<=1'b0;

data_en2<=1'b0;

end

else begin

data_en1<=data_en;

data_en2<=data_en1;

end

end

assign data_en_pos=(data_en1&(~data_en2));            //检测使能上升沿

 

 

always @(posedge clk or negedge rst_n)

begin

if(!rst_n) begin

crc_start<=1'b0;

end

else if(data_en_pos) begin

crc_start<=1'b1;

end

else if(crc_end)

crc_start<=1'b0;

end

assign data_in_reg={data_in,5'b00_000};

/*always @(posedge clk_crc or negedge rst_n)

begin

if(!rst_n)

data_in_reg<=16'b0;

else  

data_in_reg<={data_in,5'b00_000};

end

*/

 

 

 

 

reg [3:0] i;

//data  width >crc width crc_8

always @(posedge clk or negedge rst_n)

begin

if(!rst_n)  begin

crc_out_r<=data_in_reg[14:9];

i<=4'd8;

crc_end<=1'b0;

 data_out<=0;

 crc_out<=0;

end

else if(crc_start) begin

if (i==0) begin

if(crc_out_r[5])  begin                  //decide shift or conduct xor operate

crc_out_r<=crc_out_r^gx_crc_8;

end

else begin

i<=4'd10;

crc_out_r<={crc_out_r[4:0],1'b0};

crc_end<=1'b1;

end

end

else if(i>0 &&i<=8) begin

if(crc_out_r[5])                    //decide shift or conduct xor operate

crc_out_r<=crc_out_r^gx_crc_8;

else  begin

crc_out_r<={crc_out_r[4:0],data_in_reg[i]};  

   i<=i-1;            //shift

end

end

else if (i==10) begin

crc_out<=crc_out_r[5]?(crc_out_r[4:0]^gx_crc_8[4:0]):crc_out_r[4:0];

data_out<={data_in,crc_out};

end

end

else begin

i<=4'd8;

crc_end<=1'b0;

crc_out_r<=data_in_reg[14:9];

end

end

Endmodule

 

 

 

Testbench

`timescale 1ns / 1ps

 

////////////////////////////////////////////////////////////////////////////////

// Company:

// Engineer:

//

// Create Date:   21:05:36 04/24/2018

// Design Name:   crc_test

// Module Name:   D:/ise ex/crc/crc_test/crc_tsb.v

// Project Name:  crc_test

// Target Device:  

// Tool versions:  

// Description:

//

// Verilog Test Fixture created by ISE for module: crc_test

//

// Dependencies:

//

// Revision:

// Revision 0.01 - File Created

// Additional Comments:

//

////////////////////////////////////////////////////////////////////////////////

 

module crc_tsb;

 

// Inputs

reg data_en;

reg clk;

reg rst_n;

reg [9:0] data_in;

reg clk_crc;

// Outputs

wire [4:0] crc_out;

wire [14:0] data_out;

// Instantiate the Unit Under Test (UUT)

crc_test uut (

.data_en(data_en),

.data_in(data_in),

.clk(clk),

.rst_n(rst_n),

.crc_out(crc_out),

.data_out(data_out)

);

 

initial begin

// Initialize Inputs

data_en = 0;

clk = 0;

clk_crc=0;

rst_n = 0;

data_in=10'b1010001101;

// Wait 100 ns for global reset to finish

#100;

rst_n =1;

#100;

data_en=1;

#100;

data_en=0;

data_in=10'b1011001101;

#300;

data_en=1;

#100;

data_en=0;

data_in=10'b1011011101;

#300;

    如果直接repeat,会执行一个顺序块,也就是data_en完成后再产生数据

 //repeat (10) @(posedge clk_crc) data_en=~data_en;

 //repeat (10) @(posedge clk_crc) data_in<=data_in+1;

解决办法:用fork join 生成并行块

fork

 repeat (10) @(posedge clk_crc) data_en<=~data_en;  

 repeat (10) @(posedge clk_crc) data_in<=data_in+1;

      join

 

// Add stimulus here

end

always #10 clk=~clk;

always #100 clk_crc=~clk_crc;

      

endmoduleCRC循环冗余校验(verilog源码及仿真)_第2张图片



你可能感兴趣的:(CRC循环冗余校验(verilog源码及仿真))