FPGA和外围接口-第一章 爱上FPGA(1.8 FPGA和数码管)

在这里插入图片描述

FPGA和数码管

1.1.1 数码管基础知识
  数码管由8个发光二极管(以下简称字段)构成,通过不同的组合可显示数字0~9、字符A~F、H、L、P、R、U、Y、符号“”及小数点“”。数码管的外型结构如图所示。数码管又分为共阴极和共阳极两种结构,分别如图所示。
在这里插入图片描述
                图1‑94共阴极和共阳极数码管

                (a)共阴极(b)共阳极

  共阳极数码管的8个发光二极管的阳极(二极管正端)连接在一起,通常接高电平(一般接电源),其它管脚接段驱动电路输出端。当某段驱动电路的输出端为低电平时,该端所连接的字段导通并点亮,根据发光字段的不同组合可显示出各种数字或字符。此时,要求段驱动电路能吸收额定的段导通电流,还需根据外接电源及额定段导通电流来确定相应的限流电阻。

  共阴极数码管的8个发光二极管的阴极(二极管负端)连接在一起,通常接低电平(一般接地),其它管脚接段驱动电路输出端。当某段驱动电路的输出端为高电平时,该端所连接的字段导通并点亮,根据发光字段的不同组合可显示出各种数字或字符。此时,要求段驱动电路能提供额定的段导通电流,还需根据外接电源及额定段导通电流来确定相应的限流电阻。

  数据线D0与a字段对应,D1字段与b字段对应……,依此类推。如使用共阳极数码管,则数据为0表示对应字段亮,数据为1表示对应字段暗;如使用共阴极数码管,则相反。

                    表1‑38数码管字型编码表

在这里插入图片描述

在这里插入图片描述

  数码管工作方式有两种:静态显示方式和动态显示方式。
1、静态显示接口

  从下图可以看出,静态显示方式的特点是各位数码管相互独立,公共端恒定接地(共阴极)或接正电源(共阳极)。每个数码管的8个字段分别与一个8位I/O口地址相连,I/O口只要有段码输出,相应字符即显示出来并保持不变,直到I/O口输出新的段码。

在这里插入图片描述

              图1‑95两位的LED数码管静态显示示意图

  采用静态显示方式时,用较小的电流即可获得较高的亮度,且占用CPU时间少,编程简单,显示便于监测和控制,但其占用的口线多,硬件电路复杂,成本高,只适用于显示位数较少的场合。

2、动态显示
  当需要显示的位数较多时,为了节省硬件接口,往往采用动态显示的方式。

  动态显示的特点是将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。动态显示的亮度比静态显示要差一些,所以在选择限流电阻时应略小于静态显示电路中的。

  动态显示是指一位一位地轮流点亮各位数码管,这种逐位点亮显示器的方式称为位扫描。通常,各位数码管的段选线相应并联在一起,由一个8位的I/O口控制;各位的位选线(公共阴极或公共阳极)由另外的I/O口线控制。以动态方式显示时,各数码管分时轮流选通。要使其稳定显示,必须采用扫描方式,即在某一时刻只选通一位数码管,并送出相应的段码,在另一时刻选通另一位数码管,并送出相应的段码。依此规律循环,即可使各位数码管显示将要显示的字符,虽然这些字符是在不同的时刻分别显示的,但由于人眼存在视觉暂留效应,因此只要每位显示间隔足够短就可以给人以同时显示的感觉。

在这里插入图片描述

            图1‑96四位的LED数码管动态显示示意图

1.1.2 FPGA和数码管驱动
  使用动态扫描还是静态扫描其实取决于硬件设计,并不取决于驱动程序,一旦硬件确定下来那么就需要驱动去适配硬件,本次设计使用的数码管为共阳极数码管,动态扫描加载,电路如下:

在这里插入图片描述

                  图1‑97动态数码管设计电路

                    表1‑39数码管设计资源

在这里插入图片描述

  设计的资源如表1‑39所示,其中扫描频率是1s扫描的频率,即1/6ms≈166.67Hz。

  数码管主要考虑输入调用它的输入。即如何充分减少资源以实现数码管动态显示。

在这里插入图片描述

                  图1‑98数码管电路设计建模图

                  表 1‑40建模图中模块间信号定义

  整个系统设计结构如图1‑98所示,上图的组合模块-数码管接口 smg_interface.v 中,输入信号 Number_Sig 占了 24 位宽,然而 Number_Sig 的位分配如下表:
在这里插入图片描述
                  表1‑42 Number_Sig的位分配表

  整个系统设计结构如图1‑98所示,上图的组合模块-数码管接口smg_interface.v 中,输入信号 Number_Sig 占了 24 位宽,然而Number_Sig 的位分配如下表:

  为什么每一位数字数码管,都用 4 位位宽来代表呢?

  每数码管可以支持显示 0~F,正是因为如此,如果我们用每 4 位位宽来代表某一个数码管显示的信号,那么可以避免“使用除法或者求余运算符执行十进制的取位操作”。一来方便设计,而来减少资源。

  举个例子: 24’h123456, 亦即 00010010 0011 0100 0101 0110。

  smg_encode_module.v 在这里的功能就是就是将数字 0~F 加码为数码管码。然而,比较特别的是, smg_control_module.v 和 smg_scan_module.v 有并行操作的性质。

  smg_interface.v 的大致操作如下:

  假设我往 Number_Sig 输入 24’h123456

(1)在 T1,smg_control_module.v 会将 Number_Sig[23:20] 送往至smg_encode_module.v 加码并且送往数码管。在同一时间 smg_scan_module.v 会扫描第一位数码管(使能)。

(2)在 T2,smg_control_module.v 会将 Number_Sig[19:16] 送往至smg_encode_module.v 加码并且送往数码管,在同一时间smg_scan_module.v 会扫描第二位数码管(使能)。

(3)在 T3, smg_control_module.v会将 Number_Sig[15:12]送往至smg_encode_module.v 加码并且送往数码管,在同一时间 smg_scan_module.v 会扫描第三位数码管(使能)。

(4)在 T4,smg_control_module.v 会将 Number_Sig[11:8] 送往至 smg_encode_module.v 加码并且送往数码管,在同一时间 smg_scan_module.v 会扫描第四位数码管(使能)。

(5)在 T5,smg_control_module.v 会将 Number_Sig[7:4] 送往至 smg_encode_module.v 加码并且送往数码管,在同一时间 smg_scan_module.v 会扫描第五位数码管(使能)。

(6)在 T6,smg_control_module.v 会将 Number_Sig[3:0] 送往至 smg_encode_module.v 加码并且送往数码管,在同一时间 smg_scan_module.v 会扫描第六位数码管(使能)。

  在 T1 的时候第一位数码管会显示1。在 T2 的时候第二位数码管会显示 2,其他的依此类推。最后在 T6 的时候,第六位数码管会显示 6。就这样一次性的扫描(六位数码管全扫描)就完成。啊,别忘了!每位数码管扫描停留的时间(使能的时间)大约是 1ms。所以一次性扫描所需要的时间大约是6ms,亦即在每一秒内,一组 6 位的数码管会扫描 166 次左右。

在这里插入图片描述

                图1‑100数码管控制模块结构图

            代码1‑13数码管控制模块(smg_control_module)代码

1. //****************************************************************************//  

2. //# @Author: 碎碎思  

3. //# @Date:   2019-05-18 23:59:39  

4. //# @Last Modified by:   zlk  

5. //# @WeChat Official Account: OpenFPGA  

6. //# @Last Modified time: 2019-05-19 01:27:11  

7. //# Description:   

8. //# @Modification History: 2019-05-19 01:27:11  

9. //# Date                By             Version             Change Description:   

10.//# ========================================================================= #  

11.//# 2019-05-19 01:27:11  

12.//# ========================================================================= #  

13.//# |                                                                       | #  

14.//# |                                OpenFPGA                               | #  

15.//****************************************************************************//  

16.module smg_control_module  

17.(  

18.    input CLOCK,  

19.     input RST_n,  

20.     input [23:0]Number_Sig,  

21.     output [3:0]Number_Data  

22.);  

23.  

24.    /******************************************/      

25.       

26.     parameter T1MS = 16'd49999;   //定义 1ms 的常量  

27.       

28.     /******************************************/    

29.     //1ms 的定时器  

30.      reg [15:0]C1;  

31.       

32.     always @ ( posedge CLOCK or negedge RST_n )  

33.         if( !RST_n )  

34.              C1 <= 16'd0;  

35.          else if( C1 == T1MS )  

36.              C1 <= 16'd0;  

37.          else  

38.              C1 <= C1 + 1'b1;  

39.       

40.     /******************************************/   

41.       

42.     reg [3:0]i;  

43.     reg [3:0]rNumber;  

44.       

45.     always @ ( posedge CLOCK or negedge RST_n )  

46.         if( !RST_n )  

47.              begin  

48.                  i <= 4'd0;  

49.                     rNumber <= 4'd0;  

50.                end  

51.          else   

52.              case( i )  

53.                  

54.                    0:  

55.                     if( C1 == T1MS ) i <= i + 1'b1;  

56.                     else rNumber <= Number_Sig[23:20];  

57.      

58.                     1:  

59.                     if( C1 == T1MS ) i <= i + 1'b1;  

60.                     else rNumber <= Number_Sig[19:16];  

61.                       

62.                     2:  

63.                     if( C1 == T1MS ) i <= i + 1'b1;  

64.                     else rNumber <= Number_Sig[15:12];  

65.                       

66.                     3:  

67.                     if( C1 == T1MS ) i <= i + 1'b1;  

68.                     else rNumber <= Number_Sig[11:8];  

69.                       

70.                     4:  

71.                     if( C1 == T1MS ) i <= i + 1'b1;  

72.                     else rNumber <= Number_Sig[7:4];  

73.                       

74.                     5:  

75.                     if( C1 == T1MS ) i <= 4'd0;  

76.                     else rNumber <= Number_Sig[3:0];  

77.                  

78.                endcase  

79.                  

80.    /******************************************/   

81.       

82.     assign Number_Data = rNumber;  

83.       

84.     /******************************************/  

85.       

86.    endmodule  

  rNumber 是每一位数字的暂存器(43 行)用来驱动Number_Data(82 行)。(52~78 行)每隔 1ms该控制模块就会将不同位的数字往 Number_Data 输出

在这里插入图片描述

                图1‑101数码管加码模块结构图

          代码 1‑14数码管加码模块(smg_encode_module)代码

1.   //****************************************************************************//  

2.   //# @Author: 碎碎思  

3.   //# @Date:   2019-05-18 23:59:39  

4.   //# @Last Modified by:   zlk  

5.   //# @WeChat Official Account: OpenFPGA  

6.   //# @Last Modified time: 2019-07-21 03:32:41  

7.   //# Description:   

8.   //# @Modification History: 2019-07-20 20:54:39  

9.   //# Date                By             Version             Change Description:   

10.//# ========================================================================= #  

11.//# 2019-07-20 20:54:39  

12.//# ========================================================================= #  

13.//# |                                                                       | #  

14.//# |                                OpenFPGA                               | #  

15.//****************************************************************************//  

16.module smg_encode_module  

17.(  

18.     input CLOCK,  

19.     input RST_n,  

20.     input [3:0]Number_Data,  

21.     output [7:0]SMG_Data  

22.);  

23.  

24.     /***************************************/  

25.       

26.     parameter _0 = 8'b1100_0000, _1 = 8'b1111_1001, _2 = 8'b1010_0100,   

27.               _3 = 8'b1011_0000, _4 = 8'b1001_1001, _5 = 8'b1001_0010,   

28.               _6 = 8'b1000_0010, _7 = 8'b1111_1000, _8 = 8'b1000_0000,  

29.               _9 = 8'b1001_0000, _A = 8'b1000_1000, _B = 8'b1000_0011,  

30.               _C = 8'b1100_0110, _D = 8'b1010_0001, _E = 8'b1000_0110,  

31.               _F = 8'b1000_1110;  

32.       

33.     /***************************************/  

34.       

35.     reg [7:0]rSMG;  

36.  

37.     always @ ( posedge CLOCK or negedge RST_n )  

38.         if( !RST_n )  

39.              begin  

40.                    rSMG <= 8'b1111_1111;  

41.                end  

42.        else   

43.               case( Number_Data )  

44.                     

45.                    4'd0  :  rSMG <= _0;  

46.                    4'd1  :  rSMG <= _1;  

47.                    4'd2  :  rSMG <= _2;  

48.                    4'd3  :  rSMG <= _3;  

49.                    4'd4  :  rSMG <= _4;  

50.                    4'd5  :  rSMG <= _5;  

51.                    4'd6  :  rSMG <= _6;  

52.                    4'd7  :  rSMG <= _7;  

53.                    4'd8  :  rSMG <= _8;  

54.                    4'd9  :  rSMG <= _9;  

55.                    4'd10 :  rSMG <= _A;  

56.                    4'd11 :  rSMG <= _B;  

57.                    4'd12 :  rSMG <= _C;  

58.                    4'd13 :  rSMG <= _D;  

59.                    4'd14 :  rSMG <= _E;  

60.                    4'd15 :  rSMG <= _F;  

61.                        

62.                 endcase  

63.                

64.     /***************************************/  

65.       

66.     assign SMG_Data = rSMG;  

67.       

68.     /***************************************/  

69.                

70.endmodule  

  第 26~31 行声明了 SMG 码的常量。第 43~62 行是针对“十位数”的加码操作,但是是针对“个位数”(58 行)。第66 行是输出。
在这里插入图片描述
                图1‑102数码管扫描模块结构图

            代码 1‑15数码管扫描模块(smg_scan_module)代码

1.   //****************************************************************************//  

2.   //# @Author: 碎碎思  

3.   //# @Date:   2019-05-18 23:59:39  

4.   //# @Last Modified by:   zlk  

5.   //# @WeChat Official Account: OpenFPGA  

6.   //# @Last Modified time: 2019-07-21 03:37:17  

7.   //# Description:   

8.   //# @Modification History: 2019-05-19 01:41:56  

9.   //# Date                By             Version             Change Description:   

10.//# ========================================================================= #  

11.//# 2019-05-19 01:41:56  

12.//# ========================================================================= #  

13.//# |                                                                       | #  

14.//# |                                OpenFPGA                               | #  

15.//****************************************************************************//  

16.module smg_scan_module  

17.(  

18.    input CLOCK,   

19.     input RST_n,   

20.     output [5:0]Scan_Sig  

21.);  

22.       

23.     /*****************************/  

24.       

25.     parameter T1MS = 16'd49999;  

26.       

27.     /*****************************/  

28.       

29.     reg [15:0]C1;  

30.       

31.     always @ ( posedge CLOCK or negedge RST_n )  

32.         if( !RST_n )  

33.              C1 <= 16'd0;  

34.          else if( C1 == T1MS )  

35.              C1 <= 16'd0;  

36.          else  

37.              C1 <= C1 + 1'b1;  

38.      

39.     /*******************************/  

40.       

41.     reg [3:0]i;  

42.     reg [5:0]rScan;  

43.       

44.     always @ ( posedge CLOCK or negedge RST_n )  

45.         if( !RST_n )  

46.              begin  

47.                  i <= 4'd0;  

48.                  rScan <= 6'b100_000;  

49.               end  

50.          else   

51.              case( i )  

52.                      

53.                     0:  

54.                  if( C1 == T1MS ) i <= i + 1'b1;  

55.                     else rScan <= 6'b011_111;  

56.                       

57.                     1:  

58.                     if( C1 == T1MS ) i <= i + 1'b1;  

59.                     else rScan <= 6'b101_111;  

60.                       

61.                     2:  

62.                     if( C1 == T1MS ) i <= i + 1'b1;  

63.                     else rScan <= 6'b110_111;  

64.                       

65.                     3:  

66.                     if( C1 == T1MS ) i <= i + 1'b1;  

67.                     else rScan <= 6'b111_011;  

68.                       

69.                     4:  

70.                     if( C1 == T1MS ) i <= i + 1'b1;  

71.                     else rScan <= 6'b111_101;  

72.                       

73.                     5:  

74.                     if( C1 == T1MS ) i <= 4'd0;  

75.                     else rScan <= 6'b111_110;  

76.                       

77.                       

78.                endcase  

79.                  

80.     /******************************/  

81.       

82.     assign Scan_Sig = rScan;  

83.       

84.     /******************************/  

85.                

86.  

87.endmodule  

  第 25 行是 1ms 的常量声明,在 31~37 行是 1ms 的定时器。该模块和smg_control_module.v一样,都是每隔 1ms 都有一个动作。smg_scan_module.v 每隔 1ms就会使能不同的数码管(56~78行)。然而数码管实际的扫描顺序是自左向右。在位操作的角度上,逻辑 0 从最高位到最低位交替移位。

  接下来将上诉模块进行封装,详细的连接图见图1‑98,综合后的RTL电路图如下:

在这里插入图片描述
                图1‑103数码管电路综合后的RTL图

  结果和图1‑98一样。

  下面进行模块的调用和验证,验证结构图如下:

在这里插入图片描述

                  图1‑104数码管电路验证结构图

  验证中会建立一个名为demo_control_module.v输出 24’h000000 ~ 24’h999999 用来驱动smg_interface.v 的输入。具体的内容还是直接看代码:

                  代码 1‑16数码管电路验证代码

1.    //****************************************************************************//  

2.    //# @Author: 碎碎思  

3.    //# @Date:   2019-05-18 23:59:39  

4.    //# @Last Modified by:   zlk  

5.    //# @WeChat Official Account: OpenFPGA  

6.    //# @Last Modified time: 2019-07-20 21:04:39  

7.    //# Description:   

8.    //# @Modification History: 2019-07-20 21:04:39  

9.    //# Date                By             Version             Change Description:   

10.   //# ========================================================================= #  

11.   //# 2019-07-20 21:04:39  

12.   //# ========================================================================= #  

13.   //# |                                                                       | #  

14.   //# |                                OpenFPGA                               | #  

15.   //****************************************************************************//  

16.   module demo_control_module  

17.   (  

18.       input CLOCK,  

19.        input RST_n,  

20.        output [23:0]Number_Sig  

21.   );  

22.        

23.        /******************************/  

24.          

25.        parameter T100MS = 23'd4_999_999;  

26.          

27.        /******************************/  

28.          

29.        reg [22:0]C1;  

30.          

31.        always @ ( posedge CLOCK or negedge RST_n )  

32.            if( !RST_n )  

33.                 C1 <= 23'd0;  

34.             else if( C1 == T100MS )  

35.                 C1 <= 23'd0;  

36.             else   

37.                 C1 <= C1 + 1'b1;  

38.         

39.         /*******************************************************/  

40.          

41.        reg [3:0]i;  

42.        reg [23:0]rNum;  

43.        reg [23:0]rNumber;  

44.          

45.        always @ ( posedge CLOCK or negedge RST_n )  

46.             if( !RST_n )  

47.                   begin  

48.                       i <= 4'd0;  

49.                         rNum <= 24'd0;  

50.                         rNumber <= 24'd0;  

51.                    end  

52.              else  

53.                   case( i )  

54.                      

55.                        0:  

56.                         if( C1 == T100MS ) begin rNum[3:0] <= rNum[3:0] + 1'b1; i <= i + 1'b1; end  

57.                           

58.                         1:  

59.                         if( rNum[3:0] > 4'd14 ) begin rNum[7:4] <= rNum[7:4] + 1'b1; rNum[3:0] <= 4'd0; i <= i + 1'b1; end  

60.                         else i <= i + 1'b1;   

61.                           

62.                         2:  

63.                         if( rNum[7:4] > 4'd14 ) begin rNum[11:8] <= rNum[11:8] + 1'b1; rNum[7:4] <= 4'd0; i <= i + 1'b1; end  

64.                         else i <= i + 1'b1;  

65.                           

66.                         3:  

67.                         if( rNum[11:8] > 4'd14 ) begin rNum[15:12] <= rNum[15:12] + 1'b1; rNum[11:8] <= 4'd0; i <= i + 1'b1; end  

68.                         else i <= i + 1'b1;  

69.                           

70.                         4:  

71.                         if( rNum[15:12] > 4'd14 ) begin rNum[19:16] <= rNum[19:16] + 1'b1; rNum[15:12] <= 4'd0; i <= i + 1'b1; end  

72.                       else i <= i + 1'b1;  

73.                           

74.                         5:  

75.                         if( rNum[15:12] > 4'd14 ) begin rNum[19:16] <= rNum[19:16] + 1'b1; rNum[15:12] <= 4'd0; i <= i + 1'b1; end      

76.                         else i <= i + 1'b1;  

77.                           

78.                         6:  

79.                         if( rNum[19:16] > 4'd14 ) begin rNum[23:20] <= rNum[23:20] + 1'b1; rNum[19:16] <= 4'd0; end  

80.                         else i <= i + 1'b1;  

81.                           

82.                         7:  

83.                         if( rNum[23:20] > 4'd14 ) begin rNum <= 24'd0; i <= i + 1'b1; end  

84.                         else i <= i + 1'b1;   

85.                           

86.                         8:  

87.                         begin rNumber <= rNum; i <= 4'd0; end  

88.                      

89.                    endcase  

90.     

91.       /*******************************************************/  

92.          

93.        assign Number_Sig = rNumber;  

94.          

95.        /*******************************************************/  

96.          

97.   endmodule  

  第 20~37 行之间,包含了100ms 定时的常量(25 行)和 100ms 的定时器(31~37行)。

  在 41~89 就是该模块的核心部分。寄存器rNum 操作空间(42 行),然而 rNumber 是用于驱动Number_Sig(93 行)。每隔 100ms 的定时都会是rNum 递增(56 行), 58~84行之间就会执行“4 位宽”数字之间的“进位操作”。

  我们假设一个情况,当rNum 的值是 24’h000009,然后在下一个100ms 的定时钟, rNum的值就会 +1 操作。在59行, if条件就会成立,rNum[3:0]就会被赋值位零,然后rNum[7:4]就会执行 +1 操作,rNum 的值成为 24’h000010。接下来的几个步骤也会执行类似的操作。

  在 72~84 行表示了当 rNum 的值超过24’h999999 的时候,就会恢复为 24’h000000。

  在这里我们有一个问题?为什么不直接使用rNum 驱动 Number_Sig 而是选择使用rNumber寄存器来驱动Number_Sig。如果我们把 rNum 当着 Number_Sig 的驱动对象,在 i 步骤 16~22 之间,由于“进位操作”的关系,会使得Number_Sig 的输出产生许多毛刺,因此才使用 rNumber 驱动Number_Sig。当 rNum 完成“进位操作”以后,再赋值与rNumber,由 rNumber 驱动 Number_Sig ( 87行)。

  然后按照图1‑104进行顶层模块的设计,代码如下:

              代码 1‑17数码管电路验证代码的顶层代码

1.   //****************************************************************************//  

2.   //# @Author: 碎碎思  

3.   //# @Date:   2019-05-18 23:59:39  

4.   //# @Last Modified by:   zlk  

5.   //# @WeChat Official Account: OpenFPGA  

6.   //# @Last Modified time: 2019-07-21 03:49:46  

7.   //# Description:   

8.   //# @Modification History: 2019-05-19 01:41:52  

9.   //# Date                By             Version             Change Description:   

10.//# ========================================================================= #  

11.//# 2019-05-19 01:41:52  

12.//# ========================================================================= #  

13.//# |                                                                       | #  

14.//# |                                OpenFPGA                               | #  

15.//****************************************************************************//  

16.module smg_interface_demo  

17.(  

18.    input CLOCK,  

19.     input RST_n,  

20.     output [7:0]SMG_Data,  

21.     output [5:0]Scan_Sig  

22.);  

23.  

24.    /******************************/   

25.   

26.    wire [23:0]Number_Sig;  

27.       

28.    demo_control_module U1  

29.     (  

30.         .CLOCK( CLOCK ),  

31.          .RST_n( RST_n ),  

32.          .Number_Sig( Number_Sig ) // output - to U2  

33.     );  

34.       

35.     /******************************/   

36.       

37.     smg_interface U2  

38.     (  

39.         .CLOCK( CLOCK ),  

40.          .RST_n( RST_n ),  

41.          .Number_Sig( Number_Sig ), // input - from U1  

42.          .SMG_Data( SMG_Data ),     // output - to top  

43.          .Scan_Sig( Scan_Sig )      // output - to top  

44.     );  

45.       

46.    /******************************/   

47.  

48.endmodule  

  综合后的RTL如下:

在这里插入图片描述

            图1‑105数码管电路验证代码的顶层代码综合后RTL图

  基本和图1‑104一样,将代码下载到目标板上就可以看到数码管已经变成了一个“秒表”了。

  代码地址

github

你笑一次,我就可以高兴好几天;可看你哭一次,我就难过了好几年…
https://github.com/suisuisi/FPGA/tree/master/FPGAandPI

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章