尝试使用硬件电路来解释CRC计算(DS1820或者DS1822的CRC计算)

发布时间 2023-05-28 15:20:14作者: 颜秋哥

      之前在培训讲解DS1822的测试时,CRC计算都是以C语言进行讲解的。今天在练习Verilog的时候,觉得也可以使用硬件电路来讲解。

      DS1820的CRC计算硬件电路示意图如下:

     这个是示意图,方框代表寄存器,XOR代表异或门。Verilog的硬件描述如下:

 1 module D_FF
 2 (
 3     input wire D, 
 4     input wire clk, 
 5     input wire rst,
 6     output reg Q
 7 );
 8     always @ (posedge clk, posedge rst)
 9     begin
10         if(rst) 
11             Q = 0;
12         else
13             Q = D;
14     end
15 endmodule
16 
17 module CRC_CHECK
18 (
19     input wire in,
20     input wire clk,
21     input wire rst,
22     output wire [7:0] Q
23 );
24     
25     wire xor7_in, xor3_in, xor2_in;
26     xor xor0(xor7_in, in, Q[0]);
27     xor xor1(xor2_in, xor7_in, Q[3]);
28     xor xor2(xor3_in, xor7_in, Q[4]);
29     
30     D_FF dq7(xor7_in, clk, rst, Q[7]);
31     D_FF dq6(Q[7], clk, rst, Q[6]);
32     D_FF dq5(Q[6], clk, rst, Q[5]);
33     D_FF dq4(Q[5], clk, rst, Q[4]);
34     D_FF dq3(xor3_in, clk, rst, Q[3]);
35     D_FF dq2(xor2_in, clk, rst, Q[2]);
36     D_FF dq1(Q[2], clk, rst, Q[1]);
37     D_FF dq0(Q[1], clk, rst, Q[0]);
38 endmodule
39 
40 module Test;
41     reg data;
42     reg clk;
43     reg rst;
44     wire [0:7] Q;
45     
46     CRC_CHECK DUT(.in(data), .clk(clk), .rst(rst), .Q(Q));
47     
48     initial
49     begin
50         data = 0;
51         clk = 0;
52         rst = 0;
53     end 
54     
55     reg [0:63] in_data;
56     initial 
57     begin
58         // 测试数据,包含CRC,所以有64位,注意是LSB到MSB的顺序
59         in_data = 64'b0100010011110000110110111110010000000000000000000000000010010110;
60     end 
61     
62     initial
63     begin
64         #3 rst = 1;
65         #3 rst = 0;
66     end 
67     
68     always
69     begin
70         #5 clk = ~clk;
71     end 
72     
73     integer i;
74     initial
75     begin
76         for(i = 0; i < 64; i = i + 1)
77         begin
78             @(posedge clk) data = in_data[i];
79         end 
80     end 
81 
82     initial
83     begin
84         $monitor($time," data=%b, Q=%b", data, Q);
85         #640 $stop;
86     end
87 endmodule

      因为ATE读取数据的时候,是LSB在前,所以Testbench中定义的时候是[0:63]而不是[63:0]。在Queta中查看原理图,结果如下:

        寄存器电路使用的D触发器,但是自动生成的电路中,寄存器的顺序有点颠倒,好像《数字设计-原理与实践》的作者吐槽过这个问题。这个不重要,这样原理图就能够和原理示意图对得上了。运行仿真,最终输出的结果为:

#                    0 data=0, Q=xxxxxxxx
#                    3 data=0, Q=00000000
#                   15 data=1, Q=00000000
#                   25 data=0, Q=10001100
#                   35 data=0, Q=01000110
#                   45 data=0, Q=00100011
#                   55 data=1, Q=10011101
#                   65 data=0, Q=01001110
#                   75 data=0, Q=00100111
#                   85 data=1, Q=10011111
#                   95 data=1, Q=01001111
#                  105 data=1, Q=00100111
#                  115 data=1, Q=00010011
#                  125 data=0, Q=00001001
#                  135 data=0, Q=10001000
#                  145 data=0, Q=01000100
#                  155 data=0, Q=00100010
#                  165 data=1, Q=00010001
#                  175 data=1, Q=00001000
#                  185 data=0, Q=10001000
#                  195 data=1, Q=01000100
#                  205 data=1, Q=10101110
#                  215 data=0, Q=11011011
#                  225 data=1, Q=11100001
#                  235 data=1, Q=01110000
#                  245 data=1, Q=10110100
#                  255 data=1, Q=11010110
#                  265 data=1, Q=11100111
#                  275 data=0, Q=01110011
#                  285 data=0, Q=10110101
#                  295 data=1, Q=11010110
#                  305 data=0, Q=11100111
#                  315 data=0, Q=11111111
#                  325 data=0, Q=11110011
#                  335 data=0, Q=11110101
#                  345 data=0, Q=11110110
#                  355 data=0, Q=01111011
#                  365 data=0, Q=10110001
#                  375 data=0, Q=11010100
#                  385 data=0, Q=01101010
#                  395 data=0, Q=00110101
#                  405 data=0, Q=10010110
#                  415 data=0, Q=01001011
#                  425 data=0, Q=10101001
#                  435 data=0, Q=11011000
#                  445 data=0, Q=01101100
#                  455 data=0, Q=00110110
#                  465 data=0, Q=00011011
#                  475 data=0, Q=10000001
#                  485 data=0, Q=11001100
#                  495 data=0, Q=01100110
#                  505 data=0, Q=00110011
#                  515 data=0, Q=10010101
#                  525 data=0, Q=11000110
#                  535 data=0, Q=01100011
#                  545 data=0, Q=10111101
#                  555 data=0, Q=11010010
#                  565 data=1, Q=01101001
#                  575 data=0, Q=00110100
#                  585 data=0, Q=00011010
#                  595 data=1, Q=00001101
#                  605 data=0, Q=00000110
#                  615 data=1, Q=00000011
#                  625 data=1, Q=00000001
#                  635 data=0, Q=00000000

  因为只是简单的仿真练习,就先不从文件读取数据了。后续可以从文件读取数据,然后对多行数据进行计算来验证CRC的电路是否正确。