基于uart传输数据包协议的数据回环与控制ram读写(三、CRC电路实现)

一、推导过程以及电路生成
crc校验码举例请看CRC校验码举例
在这里插入图片描述
规律:生成多项式除了最高项,其余哪个项的系数为1,相应的寄存器前面插一个异或逻辑。

二、上例对应代码
上例输入数据为1bit,CRC输出5bit

module crc(
  input data_in,//即上图中的ai
  input crc_en,
  output [4:0] crc_out,//输出5位crc校验码
  input rst,
  input clk);

  reg [4:0] lfsr_q;//寄存器输出端Q
  reg [4:0] lfsr_c;//寄存器输入端D,在always语句块里被赋值定义成reg

  assign crc_out = lfsr_q;

  always @(*) begin
    lfsr_c[0] = lfsr_q[4] ^ data_in;//C0的输入端等于C4的输出端与输出的下一bit数据的异或
    lfsr_c[1] = lfsr_q[0] ;
    lfsr_c[2] = lfsr_q[1] ^ lfsr_q[4]^ data_in;
    lfsr_c[3] = lfsr_q[2];
    lfsr_c[4] = lfsr_q[3] ^ lfsr_q[4]^ data_in; //C4的输入端等于lfsr_q[4] ^ data_in的结果与C3异或
  end 

  always @(posedge clk, posedge rst) begin
    if(rst) begin
      lfsr_q <= {5{1'b0}};//初值设为0
    end
    else begin
      lfsr_q <= crc_en ? lfsr_c: lfsr_q;//crc使能有效,寄存器更新值,否则保持。
    end
  end 
endmodule 

testbench:

module tb_crc5();
	reg clk;
	reg rst;
	reg data_in;
	reg crc_en;
	wire [4:0] crc_out;

	always #10 clk = ~clk;

	crc u_crc(
		.data_in(data_in),
		.crc_en(crc_en),
		.crc_out(crc_out),
		.rst(rst),
		.clk(clk)
		);

	initial begin
		clk = 0;
		rst = 1;
		data_in = 1;
		crc_en = 0;

		#40
		rst = 0;
		crc_en = 1;
		#400
		$finish;
	end 
		
endmodule

在这里插入图片描述
与使用CRC校验码举例文中的计算方法的计算结果一致。可自行计算。该方法仅适用于初值为0的情况。
输入第一bit1(data_in初值),即计算1,crc校验码:15
在线crc计算验证一下:
在这里插入图片描述
输入第二bit1,即计算11,crc校验码:0a
在这里插入图片描述
以此类推。可知仿真结果是正确。
该例子的输入为1bit数据,若不是串行输入,则需要进行化简,可通过https://www.easics.com/crctool/设置生成多项式、输入数据位宽从而选择verilog代码并下载。

更多例子,如乐鑫笔试题,请参考此处

三、选择实验所需的crc多项式
由该系列前两篇文章可知,在串口通信中,接收模块接收8bit串行数据,转化为并行数据输出,发送模块把接收到的并行数据转化为串行数据输出。因此需将输入数据位宽设置为8。为了校验更准确,将校验码位数设置多一些,此处选择16位crc码。
在这里插入图片描述


// Copyright (C) 1999-2008 Easics NV.
// This source file may be used and distributed without restriction
// provided that this copyright statement is not removed from the file
// and that any derivative work contains the original copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// Purpose : synthesizable CRC function
//   * polynomial: x^16 + x^12 + x^5 + 1
//   * data width: 8
//
// Info : tools@easics.be
//        http://www.easics.com

module CRC16_D8(
	input		[7:0]		Data,
	input		[15:0]		CRC_in,
	
	output		[15:0]		CRC_out

);

  // polynomial: x^16 + x^12 + x^5 + 1
  // data width: 8
  // convention: the first serial bit is D[7]
  
  function [15:0] nextCRC16_D8;

    input [7:0] Data;
    input [15:0] crc;
    reg [7:0] d;
    reg [15:0] c;
    reg [15:0] newcrc;
  begin
    d = Data;
    c = crc;

    newcrc[0] = d[4] ^ d[0] ^ c[8] ^ c[12];
    newcrc[1] = d[5] ^ d[1] ^ c[9] ^ c[13];
    newcrc[2] = d[6] ^ d[2] ^ c[10] ^ c[14];
    newcrc[3] = d[7] ^ d[3] ^ c[11] ^ c[15];
    newcrc[4] = d[4] ^ c[12];
    newcrc[5] = d[5] ^ d[4] ^ d[0] ^ c[8] ^ c[12] ^ c[13];
    newcrc[6] = d[6] ^ d[5] ^ d[1] ^ c[9] ^ c[13] ^ c[14];
    newcrc[7] = d[7] ^ d[6] ^ d[2] ^ c[10] ^ c[14] ^ c[15];
    newcrc[8] = d[7] ^ d[3] ^ c[0] ^ c[11] ^ c[15];
    newcrc[9] = d[4] ^ c[1] ^ c[12];
    newcrc[10] = d[5] ^ c[2] ^ c[13];
    newcrc[11] = d[6] ^ c[3] ^ c[14];
    newcrc[12] = d[7] ^ d[4] ^ d[0] ^ c[4] ^ c[8] ^ c[12] ^ c[15];
    newcrc[13] = d[5] ^ d[1] ^ c[5] ^ c[9] ^ c[13];
    newcrc[14] = d[6] ^ d[2] ^ c[6] ^ c[10] ^ c[14];
    newcrc[15] = d[7] ^ d[3] ^ c[7] ^ c[11] ^ c[15];
    nextCRC16_D8 = newcrc;
  end
  endfunction
  
  assign CRC_out = nextCRC16_D8(Data,CRC_in);
  
endmodule

该模块的验证放在数据链路层。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值