数字IC笔试题|verilog实现CRC-8的串行计算

题目如下:数字IC笔试题|verilog实现CRC-8的串行计算_第1张图片
verilog实现:

`timescale 1ns / 1ps
//
module crc(clk,rst_n,data,data_valid,crc_start,crc_out,crc_valid,crc_out_parallel);
input clk,rst_n;
input data;  //串行输入数据
input data_valid; //串行数据有效标识;
input crc_start;

output wire crc_out;
output reg [7:0] crc_out_parallel;
 
output reg crc_valid;

parameter idle = 3'b001;
parameter crc_cal = 3'b010;
parameter crc_output = 3'b100;
parameter polynomial = 8'b0000_0111;

reg [2:0] current_state,next_state;

always@(posedge clk or negedge rst_n)
begin 
if(rst_n==1'b0)
  
	  current_state<=idle;
else 
      current_state<=next_state;
end 

reg [5:0] cnt_in;
reg [2:0] cnt_out;
 
always@(*)
begin 
        case(current_state)
	        idle :    
			       if(crc_start==1'b1)
				        next_state = crc_cal;
				   else 
				        next_state = idle;
		    crc_cal:
			       if(cnt_in==6'd32)
				        next_state = crc_output;
				   else 
				        next_state = crc_cal;
			crc_out:
			       if(cnt_out==3'd7)
				        next_state = idle;
				   else 
				        next_state = crc_output;
		endcase
end 

always@(posedge clk or negedge rst_n)  //计数输入
begin 
if(rst_n==1'b0)
    cnt_in<=6'd0;
else if(current_state==crc_cal)
    begin
       if(cnt_in==6'd32)
	      cnt_in<=6'd0;
	   else if(data_valid==1'b1)
	      cnt_in<=cnt_in+1'd1;
	   else 
	      cnt_in<=cnt_in;
    end 
else  
    cnt_in<=6'd0;   
end 

//mothed 1 :lsfr_reg calculate crc
reg [7:0] lsfr_reg; 
reg [7:0] lsfr_reg1;

always@(posedge clk or negedge rst_n)
begin 
if(rst_n==1'b0)
    lsfr_reg<=7'b0;
else if(current_state==crc_cal)
    begin 
	     lsfr_reg[0]<=lsfr_reg[7]^data;
		 lsfr_reg[1]<=lsfr_reg[7]^data^lsfr_reg[0];
		 lsfr_reg[2]<=lsfr_reg[7]^data^lsfr_reg[1];
		 lsfr_reg[3]<=lsfr_reg[2];
    	 lsfr_reg[4]<=lsfr_reg[3];
		 lsfr_reg[5]<=lsfr_reg[4];
		 lsfr_reg[6]<=lsfr_reg[5];
		 lsfr_reg[7]<=lsfr_reg[6];
		 lsfr_reg1<=lsfr_reg;
	end 
end

always@(posedge clk or negedge rst_n)
begin 
if(rst_n==1'b0)
   crc_valid<=1'b0;
else if(current_state==crc_output)
  begin
   if(cnt_out==3'd7)
      crc_valid<=1'b0;
   else 
      crc_valid<=1'b1;
   end 
 end 
 
always@(posedge clk or negedge rst_n)
begin 
if(rst_n==1'b0)
   begin 
    cnt_out<=1'b0;
   end
    
else if(crc_valid==1'b1)
    begin
    if(cnt_out==3'd7)
       cnt_out<=3'd7;
    else 
       cnt_out<=cnt_out+1'd1;
    end 
end
 assign crc_out = crc_valid?(lsfr_reg1[7-cnt_out]):1'b0;     
   
// mothed 2 : serial calculate

always@(posedge clk or negedge rst_n)
begin 
if(rst_n==1'b0)
    crc_out_parallel<=8'b0;
else if(current_state==crc_cal)
    begin 
	   if(data_valid==1'b1)
	      crc_out_parallel<=({crc_out_parallel[6:0],1'b0})^({8{(crc_out_parallel[7]^data)}}& polynomial);
	   else  
	      crc_out_parallel<=crc_out_parallel;
	end 
end

endmodule 
   

这里使用了两种方法计算CRC,方法一直接根据LSFR结构计算,第二种根据串行计算公式计算
关于串行计算公式推导可以参考这篇文章:
https://blog.csdn.net/lg2lh/article/details/44465275

testbench:

module crc_tb;

reg clk,rst_n;
reg data_valid;
reg crc_start;
reg data;

wire crc_out;
wire crc_valid;
wire [7:0] crc_out_parallel;

parameter clock_period = 20;

initial clk = 1'b1;
always #(clock_period/2) clk = ~clk;

initial 
      begin 
	     rst_n = 1'b0;
		 crc_start = 1'b0;
         data_valid = 1'b0;
         data = 1'b0;
         #(20*clock_period) 
         rst_n = 1'b1;
         # clock_period
         crc_start = 1'b1;
         # clock_period
         crc_start = 1'b0; 
          
		 # clock_period
		 data = 1'b1;data_valid=1'b1;
		 # clock_period
		 data = 1'b0;data_valid=1'b1;
		 # clock_period
		 data = 1'b1;data_valid=1'b1;
		 # clock_period
		 data = 1'b1;data_valid=1'b1;
         # clock_period
		 data = 1'b1;data_valid=1'b1;
		 # clock_period
		 data = 1'b0;data_valid=1'b1;
		 # clock_period
		 data = 1'b1;data_valid=1'b1;
		 # clock_period
		 data = 1'b1;data_valid=1'b1;
		 		
         # clock_period
         data = 1'b0;data_valid=1'b1;
        # clock_period
        data = 1'b0;data_valid=1'b1;
        # clock_period
        data = 1'b0;data_valid=1'b1;
        # clock_period
        data = 1'b1;data_valid=1'b1;
        # clock_period
        data = 1'b0;data_valid=1'b1;
        # clock_period
        data = 1'b0;data_valid=1'b1;
        # clock_period
        data = 1'b0;data_valid=1'b1;
        # clock_period
        data = 1'b1;data_valid=1'b1;
         
        # clock_period              
        data = 1'b1;data_valid=1'b1;
        # clock_period              
        data = 1'b1;data_valid=1'b1;
        # clock_period              
        data = 1'b1;data_valid=1'b1;
        # clock_period              
        data = 1'b1;data_valid=1'b1;
        # clock_period        
        data = 1'b1;data_valid=1'b1;
        # clock_period              
        data = 1'b1;data_valid=1'b1;
        # clock_period              
        data = 1'b1;data_valid=1'b1;
        # clock_period              
        data = 1'b1;data_valid=1'b1;
        
        # clock_period              
        data = 1'b0;data_valid=1'b1;
        # clock_period              
        data = 1'b0;data_valid=1'b1;
        # clock_period              
        data = 1'b1;data_valid=1'b1;
        # clock_period              
        data = 1'b1;data_valid=1'b1;
        # clock_period        
        data = 1'b0;data_valid=1'b1;
        # clock_period              
        data = 1'b0;data_valid=1'b1;
        # clock_period              
        data = 1'b1;data_valid=1'b1;
        # clock_period              
        data = 1'b1;data_valid=1'b1;
        # clock_period
		 data = 1'b0;data_valid=1'b0;
		
		 #(20*clock_period)
		 $stop;
	  end 

crc inst(.clk(clk),
         .rst_n(rst_n),
         .data(data),
         .data_valid(data_valid),
         .crc_start(crc_start),
         .crc_out(crc_out),
         .crc_valid(crc_valid),
         .crc_out_parallel(crc_out_parallel));
endmodule

仿真结果可见下图,两种方法计算出的CRC的值一致
数字IC笔试题|verilog实现CRC-8的串行计算_第2张图片

你可能感兴趣的:(学习记录)