CRC设计

CRC设计

一、以CRC-16-USB x16+x15+x2+1的多项式为例

CRC设计需要考虑CRC初始值,输入值反转,输出值反转,结果异或值这些条件;
(1)初始值为移位寄存器的初始值;
(2)输入值反转指的是以字节为单位进行反序,例如16‘hff_f0反序后为16’hff_0f;
(3)输出反序为按照bit进行反序;
(4)结果异或值是对结果异或处理,它在crc执行步骤中为输出反序之前;

CRC电路算法实际是基于线性反馈移位寄存器;

二、下面给出设计代码

1、支持特性
(1)采用CRC的串行方式计算,17个时钟周期输出结果(性能有待提升);
(2)非流水线形,只能处理单次CRC计算,未处理完发送下一笔数据上一笔会丢失;
(3)初始值,结果异或值,输入逆序,输出逆序寄存器可配置;
2、RTL代码

//CRC-16-USB x16+x15+x2+1
//serial CRC
module CRC_16_USB #(
	parameter DATA_SIZE = 16,
	parameter CRC_SIZE= 16
)
(
	input clk,
	input rst_n,
	input [DATA_SIZE-1:0] data_in,
	input vlid_i,
	output reg [CRC_SIZE-1:0] crc_out,
	output reg vlid_o
);
//reg [CRC_SIZE-1:0] crc_poly = 16'h8005;
localparam init_value_reg = 16'hffff;
reg [CRC_SIZE-1:0] init_value; 
reg [CRC_SIZE-1:0] xor_value = 16'hffff;
reg refin = 1'b1;
reg refout = 1'b1;
reg [DATA_SIZE-1:0] refin_data;
reg [DATA_SIZE-1:0] refout_data;
reg [4:0] cnt;
reg [DATA_SIZE-1:0] vlid_data;
//reg finish_flag;
reg start;
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		vlid_data <= 16'h0;
	end
	else if(vlid_i == 1'b1);
		vlid_data <= data_in;
end

always@(*)begin
	for(integer i=0; i<8; i++)begin
		if(refin == 1'b1)begin
			refin_data[15-i] = vlid_data[8+i]; //reverse by byte
			refin_data[7-i] = vlid_data[i];
		end
		else
			refin_data[i] = data_in[i];
	end
end

always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt <= 5'b0;
	end
	else if(vlid_i == 1'b1)
		cnt <= 5'b0_1111;
	else if(cnt > 5'b0)
		cnt <= cnt - 5'b1;
	else
		cnt <= cnt;
end

always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		start <= 1'b0;
	end
	else if(vlid_i == 1'b1)
		start <= 1'b1;
	else if(start == 1'b1 && cnt == 5'b0)
		start <= 1'b0;
end

always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		vlid_o <= 1'b0;
	end
	else if(start == 1'b0)
		vlid_o <= 1'b0;
	else if(cnt == 5'b0 && start == 1'b1)
		vlid_o <= 1'b1;
end

always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		init_value <= init_value_reg;
	end
	else if(vlid_i == 1'b1)
		init_value <= init_value_reg;
	else if(start == 1'b0)
		init_value <= init_value;
	else
		init_value = {init_value[14]^init_value[15]^refin_data[cnt], init_value[13], init_value[12], init_value[11], init_value[10], init_value[9], init_value[8], init_value[7], init_value[6], init_value[5], init_value[4], init_value[3], init_value[2], init_value[1]^init_value[15]^refin_data[cnt], init_value[0], init_value[15]^refin_data[cnt]};	
end
	

always@(*)begin
	refout_data = init_value[15:0]^xor_value[15:0];
end

always@(*)begin
	for(integer k=0;k<16; k++)begin
		if(refout == 1'b1)
			crc_out[k] = refout_data[15-k];
		else
			crc_out[k] = refout_data[k];
	end
end


endmodule

3、简单的TestBench示例

`timescale 1ns/10ps
module top_tb();
logic clk;
logic rst_n;
logic vlid_i;
logic [15:0] data_in;
logic [15:0] data_out;

CRC_16_USB #(
	.DATA_SIZE(16),
	.CRC_SZIE(16)
) u_crc_16_usb (
	.data_in(data_in),
	.clk(clk),
	.vlid_i(vlid_i),
	.vlid_o(vlid_o),
	.rst_n(rst_n),
	.crc_out(data_out)
);
initial begin
   clk = 0;
   forever begin
      #10 clk = ~clk;
   end
end


initial begin
	rst_n = 0;
	vlid_i = 0;
	data_in = 0;
	#100ns;
	rst_n = 0;
	#10ns;
	rst_n = 1;
	vlid_i = 1;
	data_in = $urandom()%65536;
	#20ns;
	vlid_i = 0;
	#60ns;
	vlid_i = 1;
	data_in = $urandom()%65536;
	#20ns;
	vlid_i = 0;
	#10ns;
	wait(vlid_o == 1);
	#100ns;
	vlid_i = 1;
	data_in = $urandom()%65536;
	#50ns;
	vlid_i = 0;
	#500ns;
	$finish();
end

initial begin
	$fsdbDumpfile("tb.fsdb");
	$fsdbDumpvars;
end

endmodule

4、Makefile脚本

all: clean elab sim verdi

elab:
	vcs  -sverilog -full64 -debug_all +fsdb+region -timescale=1ns/1ps \
    -f filelist.f \
	-top top_tb \
	-P ${VERDI_HOME}/share/PLI/VCS/LINUX64/novas.tab ${VERDI_HOME}/share/PLI/VCS/LINUX64/pli.a \
	-l com.log \
	-cm cond+line+tgl+branch+fsm+assert
sim:
	./simv +fsdb+delta -cm cond+line+tgl+branch+fsm+assert -l sim.log
verdi:
	verdi  -sv -f filelist.f -ssf ./tb.fsdb &
clean:
	rm -rf AN.DB csrc
	rm -rf *simv*
	rm -rf DVEfiles
	rm -rf ucli.key
	rm -rf *.fsdb *.log *.conf

三、运行结果

1、fsdb波形
在这里插入图片描述
2、覆盖率收集
在这里插入图片描述
verdi的cov未破解的解决方案如下
在这里插入图片描述

killall lmgrd,杀死所有的lmgrd进程;
在这里插入图片描述
在已有的破解工具的src文件加入VerdiCoverage关键词

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于Verilog HDL的CRC32校验电路设计代码,适用于Xilinx FPGA平台: ```verilog module crc32 ( input clk, input rst, input [7:0] data_in, output reg [31:0] crc_out ); // CRC32寄存器 reg [31:0] crc_reg; // 码多项式 reg [31:0] poly = 32'hEDB88320; // 码表 reg [31:0] crc_table [0:255]; // 比较器 reg cmp; // 初始化码表 initial begin for (int i = 0; i < 256; i = i + 1) begin crc_table[i] = crc32_update(32'h00000000, i); end end // 更新CRC32寄存器 function [31:0] crc32_update; input [31:0] crc_in; input [7:0] data; reg [31:0] crc_out; begin crc_out = crc_in ^ data; for (int i = 0; i < 8; i = i + 1) begin if (crc_out[0] == 1) begin crc_out = {crc_out[30:0], 1'b0} ^ poly; end else begin crc_out = {crc_out[30:0], 1'b0}; end end crc32_update = crc_out; end endfunction // 状态机 reg [2:0] state; localparam IDLE = 3'b000; localparam CALCULATE = 3'b001; localparam OUTPUT = 3'b010; always @(posedge clk) begin if (rst) begin state <= IDLE; crc_reg <= 32'h00000000; crc_out <= 32'h00000000; end else begin case (state) IDLE: begin if (data_in) begin state <= CALCULATE; end else begin state <= IDLE; end end CALCULATE: begin cmp <= (crc_reg == 32'hFFFFFFFF); crc_reg <= crc32_update(crc_reg, data_in); if (cmp) begin state <= OUTPUT; end else begin state <= CALCULATE; end end OUTPUT: begin crc_out <= ~crc_reg; state <= IDLE; end default: state <= IDLE; endcase end end endmodule ``` 以上代码实现了基于Verilog HDL的CRC32校验电路设计,实现了数据输入、CRC32校验、比较器、输出等功能,并通过有限状态机控制了整个流程。需要注意的是,以上代码仅供参考,实际应用中需要根据具体需求进行修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值