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

      之前在培训讲解DS18B22的测试时,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 dff7_in, dff3_in, dff2_in;
26     
27     xor xor0(dff7_in, in     , Q[0]);
28     xor xor1(dff2_in, dff7_in, Q[3]);
29     xor xor2(dff3_in, dff7_in, Q[4]);
30     
31     D_FF dff7(dff7_in, clk, rst, Q[7]);
32     D_FF dff6(Q[7]   , clk, rst, Q[6]);
33     D_FF dff5(Q[6]   , clk, rst, Q[5]);
34     D_FF dff4(Q[5]   , clk, rst, Q[4]);
35     D_FF dff3(dff3_in, clk, rst, Q[3]);
36     D_FF dff2(dff2_in, clk, rst, Q[2]);
37     D_FF dff1(Q[2]   , clk, rst, Q[1]);
38     D_FF dff0(Q[1]   , clk, rst, Q[0]);
39 endmodule
40 
41 module Test;
42     reg data;
43     reg clk;
44     reg rst;
45     wire [0:7] Q;
46     
47     CRC_CHECK DUT(.in(data), .clk(clk), .rst(rst), .Q(Q));
48     
49     initial
50     begin
51         data = 0;
52         clk = 0;
53         rst = 0;
54     end 
55     
56     reg [0:63] in_data;
57     initial 
58     begin
59         // 测试数据,包含CRC,所以有64位,注意是LSB到MSB的顺序
60         in_data = 64'b0100010011110000110110111110010000000000000000000000000010010110;
61     end 
62     
63     initial
64     begin
65         #3 rst = 1;
66         #3 rst = 0;
67     end 
68     
69     always
70     begin
71         #5 clk = ~clk;
72     end 
73     
74     integer i;
75     initial
76     begin
77         for(i = 0; i < 64; i = i + 1)
78         begin
79             @(posedge clk) data = in_data[i];
80         end 
81     end 
82 
83     initial
84     begin
85         $monitor($time," data=%b, Q=%b", data, Q);
86         #640 $stop;
87     end
88 endmodule

 

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

        寄存器电路使用的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的电路是否正确。

       后续补充:出于演示目的,还可以使用Logsim动态演示,其仿真电路如下图所示。将数据输入存储器中,利用计数器改变地址,逐位输出给CRC计算电路。Logsim还是挺容易上手的。很可惜,后续没有再升级了。

 

posted @ 2023-05-28 15:13  颜秋哥  阅读(192)  评论(0编辑  收藏  举报