1.原理简介
在USB通信中,CRC5的计算只是针对地址和终点数据字段。如图1所示。
图1 USB数据帧格式
CRC5的电路通过异或逻辑和触发器实现。图2说明了CRC5循环冗余校验的编码器/解码器的示例电路,该电路采用多项式X5+X2+X0。要进行循环冗余校验,首先要将整个循环冗余校验寄存器crc5_o[4:0]预置为00000,然后在时钟clk的驱动下,将收到的数据位通过crc5_di端口输入,高位优先。全部数据输入完成之后crc5_o[4:0]中的数值就是crc5循环冗余校验码。
图2 CRC5电路示例
2.verilog 代码
verilog代码分为两部分,一部分为crc5源码crc5.v,另一部分为crc5在modelsim下的testbench测试文件crc5.vt。程序源码已上传至资源,供学习交流。
(1)crc5.v
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//CRC5(X5+X2+X0)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
module crc5(crc5_di,crc5_en,crc5_o,reset_l,clk);
//I/O definition
input crc5_di;// CRC5 data (H)
input crc5_en;// CRC5 enable (H)
input reset_l;//Reset (L)
input clk; //Clock (X)
output[4:0] crc5_o;//CRC5 out (H)
//Regs for random logic
reg crc5_0_in,crc5_2_in;
//Regs for DFFs
reg [4:0] crc5_o;
//---------------------------
// random logic
//---------------------------
always @(crc5_o or crc5_di or crc5_0_in)
begin
crc5_0_in <= (crc5_di ^crc5_o[4]);
crc5_2_in <= ~(crc5_0_in ^crc5_o[1]);
end
//----------
// DFFs
//----------
always @(posedge(clk) or negedge (reset_l))
begin
if (~reset_l) crc5_o[4:0]<=1'b0;
else
begin
if(~crc5_en) crc5_o[4:0] <= crc5_o[4:0];
else
begin
crc5_o[4:3] <=crc5_o[3:2];
crc5_o[2] <=crc5_2_in;
crc5_o[1] <=crc5_o[0];
crc5_o[0] <=crc5_0_in;
end
end
end
endmodule
(2) crc5.vt
`timescale 1 ns/ 1 ns
module crc5_vlg_tst();
// constants
// general purpose registers
//reg eachvec;
// test vector input registers
reg clk;
reg crc5_di;
reg crc5_en;
reg reset_l;
// wires
wire [4:0] crc5_o;
integer i,mask;
reg [7:0] crc5_di_8[14:0];
// assign statements (if any)
crc5 i1 (
// port map - connection between master ports and signals/registers
.clk(clk),
.crc5_di(crc5_di),
.crc5_en(crc5_en),
.crc5_o(crc5_o),
.reset_l(reset_l)
);
initial
begin
// code that executes only once
// insert code here --> begin
// --> end
$readmemb("crc5_di.txt" ,crc5_di_8);
clk <=1'b1;
reset_l <=1'b0;
crc5_en <=1'b0;
crc5_di <=1'b0;
#110 reset_l <=1'b1;
#10 crc5_di <=1'b0;
for(i=0;i<15;i=i+1)
begin
for(mask=8'h80; mask>0; mask=(mask>>1))
begin
crc5_di_gen;
end
end
//$display("Running testbench");
#100 $finish;
end
// 20MHz clock generator
always #25 clk<=~clk;
//--------
//Tasks
//--------
task crc5_di_gen;
begin
if (((i%5)==1)&&(mask==8)) reset_l <=1'b0;
else reset_l <=1'b1;
if ((crc5_di_8[i]&mask)==0) #50 crc5_di<=1'b0;
else #50 crc5_di<=1'b1;
if (((i%5)==2)||(((i%5)==3)&&(mask>8'h10)))
begin
crc5_en<=1'b1;
end
else crc5_en<=1'b0;
end
endtask
endmodule
3.仿真效果
图3 Modelsim仿真效果图
图4 Modelsim仿真效果局部放大图