1 CRC算法
如 POLY=10011;
輸入DATA=11100110;
- POLY位寬=5;
- 將DATA后面添加5-1=4位個0;DATA=111001100000;
- 將CRC=4'b0和DATA拼在一起,DATA={CRC,DATA}
- DATA從高到低,每次計算最高位如果為1,則次高4位和POLY做異或計算,否則與0做異或計算;
- 最后1 bit做完除法,即得到CRC:
CRC的演算:

微信圖片_20200819205200.jpg
2 Verilog 快速驗證
硬件實現(xiàn)算法可以先load 4bit data到crc_sft邏輯,然后做8次循環(huán),每次data左移1bit數(shù)據(jù)到crc_sht,如果crc_sft最高位為1,則crc_sft和poly做異或運算;
module crc_test;
//1 stimulator defination
logic clk;
logic rst_n;
logic [11:0] data;
logic [3:0] poly;
logic [3:0] crc;
logic [4:0] crc_sft;
integer i;
//2 algorithm defination
always@(*) begin
crc_sft=5’b0; //load the crc initial var;
for(i=0;i<12;i=i+1) begin //loop 12 for the other data caculation
crc_sft ={crc_sft[3:0],data[7-i]};
crc_sft[3:0] =crc_sft[4] ? crc_sft[3:0]^poly : crc_sft[3:0];
$display("round:%d,data is %b, shift in bit is:%b,crc is: %b",i,data,data[7-i]),crc_sft[3:0]
end
end
always@(posedge clk or nededge rst_n) begin
if(rst_n==1'b0)
crc<=4'b0;
else
crc<=crc_sft[3:0];
end
//3 start the stimulator
initial begin
clk=1'b0;
forever #10 clk=~clk;
end
initial begin
rst_n=1'b0;
data=0;
poly=4'b0011;
#30 rst_n=1'b1;
#100 data=12'b1110_0110_0000;
#3000 $finish()
end
//4 dump wave files
initial begin
$fsdbDumpfile("top_tb.fsdb");
$fsdbDumpvars;
end
endmodule
3 makefile
case := crc
file := $(addsuffix .sv,$(case))
comp:
vcs -sverilog -debug_access $(file)
sim:
./simv
run: comp sim
clean:
rm -r *log *fsdb *.key csrc verdiLog simv.daidir simv *.rc *.conf
4 測試舉例
make run case=crc4_1
測試結(jié)果:

image.png
5 總結(jié)
遇到bit類的運算等和數(shù)字硬件強烈相關(guān)的操作,總感覺使用C或python等語言構(gòu)建模型,仿真還是太不直觀;本文給出了一種簡單的方法來驗證此類算法設(shè)計;