admin管理员组文章数量:1130349
Verilog
Verilog --crc16 modbus
1 、CRC 校验原理
CRC 的基本原理就是在一个 n 位二进制数据序列之后附加一个 r 位二进制检验码序列,从而构成一个总长为 p = n + r 位的二进制序列。这里附加在数据序列之后的 CRC 码与数据序列的内容之间存在某种特定的关系。
如果在数据传输过程中,由于噪声或传输特性不理想而使数据序列中的某一位或某些位发生错误,这种特定关系就会被破坏。可见在数据的接收端通过检查这种特定关系,可以很容易地实现对数据传输正确性的检验。
下面是verilog代码:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: cui
//
// Create Date: 2020/05/24 17:04:30
// Design Name:
// Module Name: CRC16_modbus
// Width:8
// Poly:0x8005
// Init:0xFFFF;
// Refin:True;
// Refout:True;
// Xorout:0x0000;
//
//////////////////////////////////////////////////////////////////////////////////module CRC16_modbus(input sys_clk,input rst_n,input[7:0] data_l,input vld,output crc_vld,output crc_reg);
reg[7:0] d;
always @(posedge sys_clk or negedge rst_n) beginif(~rst_n) begind<= 0;end else if(vld) begind<=data_n ;end
end
reg[15:0] crc;
reg[15:0] newcrc;
reg[15:0] nextCRC16_D8;
wire[15:0] c;
assign c=newcrc;
always @(posedge sys_clk or negedge rst_n) beginif(~rst_n) beginnewcrc<= 16'hFFFF;end else if(count==8'd5) beginnewcrc[0] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ d[0] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[15];newcrc[1] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[15];newcrc[2] = d[1] ^ d[0] ^ c[8] ^ c[9];newcrc[3] = d[2] ^ d[1] ^ c[9] ^ c[10];newcrc[4] = d[3] ^ d[2] ^ c[10] ^ c[11];newcrc[5] = d[4] ^ d[3] ^ c[11] ^ c[12];newcrc[6] = d[5] ^ d[4] ^ c[12] ^ c[13];newcrc[7] = d[6] ^ d[5] ^ c[13] ^ c[14];newcrc[8] = d[7] ^ d[6] ^ c[0] ^ c[14] ^ c[15];newcrc[9] = d[7] ^ c[1] ^ c[15];newcrc[10] = c[2];newcrc[11] = c[3];newcrc[12] = c[4];newcrc[13] = c[5];newcrc[14] = c[6];newcrc[15] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ d[0] ^ c[7] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[15];nextCRC16_D8 = newcrc;end
end
reg[7:0] count;
always @(posedge sys_clk or negedge rst_n) beginif(~rst_n) begincount<= 0;end else if(vld) begincount<=1 ;end else if (count==8'd8) begincount<=0; end else if (count!==0) begincount<=count+1;end
end
reg[15:0] crc_reg;
reg crc_vld;
always @(posedge sys_clk or negedge rst_n) beginif(~rst_n) begincrc_reg<= 0;end else if(count==8'd8) begincrc_reg<=crc_n^xor_a ;crc_vld<=1;end else begin crc_vld<=0;end
end
parameter xor_a=16'd0;
wire[7:0] data_n;
assign data_n[7]=data_l[0];
assign data_n[6]=data_l[1];
assign data_n[5]=data_l[2];
assign data_n[4]=data_l[3];
assign data_n[3]=data_l[4];
assign data_n[2]=data_l[5];
assign data_n[1]=data_l[6];
assign data_n[0]=data_l[7];wire[15:0] crc_n;
assign crc_n[15]=nextCRC16_D8[0];
assign crc_n[14]=nextCRC16_D8[1];
assign crc_n[13]=nextCRC16_D8[2];
assign crc_n[12]=nextCRC16_D8[3];
assign crc_n[11]=nextCRC16_D8[4];
assign crc_n[10]=nextCRC16_D8[5];
assign crc_n[9]=nextCRC16_D8[6];
assign crc_n[8]=nextCRC16_D8[7];
assign crc_n[7]=nextCRC16_D8[8];
assign crc_n[6]=nextCRC16_D8[9];
assign crc_n[5]=nextCRC16_D8[10];
assign crc_n[4]=nextCRC16_D8[11];
assign crc_n[3]=nextCRC16_D8[12];
assign crc_n[2]=nextCRC16_D8[13];
assign crc_n[1]=nextCRC16_D8[14];
assign crc_n[0]=nextCRC16_D8[15];endmodule
testbench:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Module Name: vtf_crc16_test
//////////////////////////////////////////////////////////////////////////////////module vtf_crc16_test;
// Inputs
reg sys_clk;
reg rst_n ;
// Outputs
wire crc_vld;
wire[15:0] crc_reg;
reg[7:0] data;
reg vld;
// Instantiate the Unit Under Test (UUT)
CRC16_modbus uut (.sys_clk(sys_clk), .rst_n(rst_n),.vld(vld),.data_l(data),.crc_vld(crc_vld),.crc_reg(crc_reg));initial
begin
// Initialize Inputssys_clk = 0;rst_n = 0 ;vld=0;#1000 ;rst_n = 1;#10 begin data=8'h11;end #10 @(posedge sys_clk)begin vld=1;end#500 begin data=8'hFF;end#10 @(posedge sys_clk)begin vld=1;end#2000 begin $finish; end
end
//Create clock
always #10 sys_clk = ~ sys_clk;
always @(posedge sys_clk or negedge rst_n) beginif(~rst_n) beginvld<= 0;end else if(vld) beginvld<=0 ;end
endendmodule
仿真波形:
从波形中可以看出,发送0x11,得到的crc为4c7f,和使用crc计算器计算的是一致的。
crc计算器链接:.html
crc生成器链接:
Verilog
Verilog --crc16 modbus
1 、CRC 校验原理
CRC 的基本原理就是在一个 n 位二进制数据序列之后附加一个 r 位二进制检验码序列,从而构成一个总长为 p = n + r 位的二进制序列。这里附加在数据序列之后的 CRC 码与数据序列的内容之间存在某种特定的关系。
如果在数据传输过程中,由于噪声或传输特性不理想而使数据序列中的某一位或某些位发生错误,这种特定关系就会被破坏。可见在数据的接收端通过检查这种特定关系,可以很容易地实现对数据传输正确性的检验。
下面是verilog代码:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: cui
//
// Create Date: 2020/05/24 17:04:30
// Design Name:
// Module Name: CRC16_modbus
// Width:8
// Poly:0x8005
// Init:0xFFFF;
// Refin:True;
// Refout:True;
// Xorout:0x0000;
//
//////////////////////////////////////////////////////////////////////////////////module CRC16_modbus(input sys_clk,input rst_n,input[7:0] data_l,input vld,output crc_vld,output crc_reg);
reg[7:0] d;
always @(posedge sys_clk or negedge rst_n) beginif(~rst_n) begind<= 0;end else if(vld) begind<=data_n ;end
end
reg[15:0] crc;
reg[15:0] newcrc;
reg[15:0] nextCRC16_D8;
wire[15:0] c;
assign c=newcrc;
always @(posedge sys_clk or negedge rst_n) beginif(~rst_n) beginnewcrc<= 16'hFFFF;end else if(count==8'd5) beginnewcrc[0] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ d[0] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[15];newcrc[1] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[15];newcrc[2] = d[1] ^ d[0] ^ c[8] ^ c[9];newcrc[3] = d[2] ^ d[1] ^ c[9] ^ c[10];newcrc[4] = d[3] ^ d[2] ^ c[10] ^ c[11];newcrc[5] = d[4] ^ d[3] ^ c[11] ^ c[12];newcrc[6] = d[5] ^ d[4] ^ c[12] ^ c[13];newcrc[7] = d[6] ^ d[5] ^ c[13] ^ c[14];newcrc[8] = d[7] ^ d[6] ^ c[0] ^ c[14] ^ c[15];newcrc[9] = d[7] ^ c[1] ^ c[15];newcrc[10] = c[2];newcrc[11] = c[3];newcrc[12] = c[4];newcrc[13] = c[5];newcrc[14] = c[6];newcrc[15] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ d[0] ^ c[7] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[15];nextCRC16_D8 = newcrc;end
end
reg[7:0] count;
always @(posedge sys_clk or negedge rst_n) beginif(~rst_n) begincount<= 0;end else if(vld) begincount<=1 ;end else if (count==8'd8) begincount<=0; end else if (count!==0) begincount<=count+1;end
end
reg[15:0] crc_reg;
reg crc_vld;
always @(posedge sys_clk or negedge rst_n) beginif(~rst_n) begincrc_reg<= 0;end else if(count==8'd8) begincrc_reg<=crc_n^xor_a ;crc_vld<=1;end else begin crc_vld<=0;end
end
parameter xor_a=16'd0;
wire[7:0] data_n;
assign data_n[7]=data_l[0];
assign data_n[6]=data_l[1];
assign data_n[5]=data_l[2];
assign data_n[4]=data_l[3];
assign data_n[3]=data_l[4];
assign data_n[2]=data_l[5];
assign data_n[1]=data_l[6];
assign data_n[0]=data_l[7];wire[15:0] crc_n;
assign crc_n[15]=nextCRC16_D8[0];
assign crc_n[14]=nextCRC16_D8[1];
assign crc_n[13]=nextCRC16_D8[2];
assign crc_n[12]=nextCRC16_D8[3];
assign crc_n[11]=nextCRC16_D8[4];
assign crc_n[10]=nextCRC16_D8[5];
assign crc_n[9]=nextCRC16_D8[6];
assign crc_n[8]=nextCRC16_D8[7];
assign crc_n[7]=nextCRC16_D8[8];
assign crc_n[6]=nextCRC16_D8[9];
assign crc_n[5]=nextCRC16_D8[10];
assign crc_n[4]=nextCRC16_D8[11];
assign crc_n[3]=nextCRC16_D8[12];
assign crc_n[2]=nextCRC16_D8[13];
assign crc_n[1]=nextCRC16_D8[14];
assign crc_n[0]=nextCRC16_D8[15];endmodule
testbench:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Module Name: vtf_crc16_test
//////////////////////////////////////////////////////////////////////////////////module vtf_crc16_test;
// Inputs
reg sys_clk;
reg rst_n ;
// Outputs
wire crc_vld;
wire[15:0] crc_reg;
reg[7:0] data;
reg vld;
// Instantiate the Unit Under Test (UUT)
CRC16_modbus uut (.sys_clk(sys_clk), .rst_n(rst_n),.vld(vld),.data_l(data),.crc_vld(crc_vld),.crc_reg(crc_reg));initial
begin
// Initialize Inputssys_clk = 0;rst_n = 0 ;vld=0;#1000 ;rst_n = 1;#10 begin data=8'h11;end #10 @(posedge sys_clk)begin vld=1;end#500 begin data=8'hFF;end#10 @(posedge sys_clk)begin vld=1;end#2000 begin $finish; end
end
//Create clock
always #10 sys_clk = ~ sys_clk;
always @(posedge sys_clk or negedge rst_n) beginif(~rst_n) beginvld<= 0;end else if(vld) beginvld<=0 ;end
endendmodule
仿真波形:
从波形中可以看出,发送0x11,得到的crc为4c7f,和使用crc计算器计算的是一致的。
crc计算器链接:.html
crc生成器链接:
本文标签: Verilog
版权声明:本文标题:Verilog 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://it.en369.cn/jiaocheng/1698415300a290532.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。


发表评论