请选择 进入手机版 | 继续访问电脑版

明德扬论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信扫一扫,快捷登录!

查看: 15741|回复: 2

【每周FPGA案例】至简设计系列_BCD译码实现

[复制链接]
发表于 2020-9-1 21:32:55 | 显示全部楼层 |阅读模式

马上注册,看完整文章,学更多FPGA知识。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
至简设计系列_BCD译码实现
【上板现象】

BCD译码实现在MP801的上板现象
https://www.bilibili.com/video/BV1Af4y117H4?p=24

BCD译码实现在点拨开发板的上板现象

https://www.bilibili.com/video/BV1Af4y117H4?p=25

BCD译码实现在实验箱的上板现象

https://www.bilibili.com/video/BV1Af4y117H4?p=23
--作者:肖肖肖

本文为明德扬原创及录用文章,转载请注明出处

1.1 总体设计1.1.1 概述
BCD码(Binary-Coded Decimal‎),用4位二进制数来表示1位十进制数中的0~910个数码,是一种二进制的数字编码形式,用二进制编码的十进制代码。BCD码这种编码形式利用了四个位元来储存一个十进制的数码,使二进制和十进制之间的转换得以快捷的进行。

1.1.2 设计目标
实现BCD译码并显示十进制结果的程序,具体功能要求如下:
1.       串口发送8位十六进制数给FPGA
2.       FPGA接收串口数据并对其进行BCD译码;
3.       在数码管上以十进制显示串口发送的数值。

1.1.3 系统结构框图
系统结构框图如下图一所示:
1.JPG

图一
1.1.4模块功能Ø  串口接收模块实现功能
1、  接收上位机PC发来的位宽为8的十六进制数据。
Ø  BCD译码模块实现功能
1、  对接收到的8位十六进制数据进行BCD译码。
Ø  数码管显示模块实现功能
1、  显示BCD译码后的十进制数值。
1.1.5顶层信号
  
信号名
  
I/O
位宽
定义
clk
I
1
系统工作时钟 50M
rst_n
I
1
系统复位信号,低电平有效
rx_uart
I
1
1bit串口接收数据
Segment
O
8
8位数码管段选信号
Seg_sel
O
3
3位数码管位选信号


1.1.6参考代码
下面是使用工程的顶层代码:
  1. module top(
  2.     clk     ,
  3.     rst_n   ,
  4.     rx_uart ,
  5.     seg_sel ,
  6.     segment
  7.     );

  8.     parameter      DATA_W         =         8;
  9.     parameter      SEG_WID        =         8;
  10.     parameter      SEL_WID        =         3;
  11.     parameter      BCD_OUT        =        12;

  12.     input                clk      ;
  13.     input                rst_n    ;
  14.     input                rx_uart  ;

  15.     output[SEL_WID-1:0]  seg_sel  ;
  16.     output[SEG_WID-1:0]  segment  ;

  17.     wire   [SEL_WID-1:0]  seg_sel  ;
  18.     wire   [SEG_WID-1:0]  segment  ;

  19.     wire  [DATA_W-1 :0]  rx_dout        ;
  20.     wire                 rx_dout_vld    ;
  21.     wire  [BCD_OUT-1:0]  bcd_dout       ;
  22.     wire                 bcd_dout_vld   ;

  23.     uart_rx     u1(
  24.         .clk          (  clk             ),
  25.         .rst_n        (  rst_n           ),
  26.         .din          (  rx_uart         ),
  27.         .dout         (  rx_dout         ),
  28.         .dout_vld     (  rx_dout_vld     )
  29.     );

  30.     bcd_water   u2(
  31.         .clk          (  clk             ),
  32.         .rst_n        (  rst_n           ),
  33.         .din          (  rx_dout         ),
  34.         .din_vld      (  rx_dout_vld     ),
  35.         .dout         (  bcd_dout        ),
  36.         .dout_vld     (  bcd_dout_vld    )
  37.     );

  38.     seg_disp#(.SEG_NUM(SEL_WID))    u3(
  39.         .clk          (  clk             ),
  40.         .rst_n        (  rst_n           ),
  41.         .din          (  bcd_dout        ),
  42.         .din_vld      (  bcd_dout_vld    ),
  43.         .seg_sel      (  seg_sel         ),
  44.         .segment      (  segment         )
  45.     );


  46. endmodule
复制代码



1.2 串口接收模块设计1.2.1接口信号
  
信号名
  
I/O
位宽
定义
clk
I
1
系统工作时钟 50M
rst_n
I
1
系统复位信号,低电平有效
din
I
1
1bit串口接收数据
dout
O
8
8bit的输出数据
dout_vld
O
1
输出数据有效指示信号


1.2.2 设计思路
在前面的案例中已经有串口接收模块的介绍,所以这里不在过多介绍,详细介绍请看下方链接:

1.2.3参考代码
  1. module uart_rx(
  2.     clk      ,
  3.     rst_n    ,
  4.     din      ,
  5.     dout     ,
  6.     dout_vld
  7.     );

  8. parameter          DATA_W = 8    ;
  9. parameter          NUM_W  = 4    ;
  10. parameter          CNT_W  = 14   ;
  11. parameter               BPS          =        5208 ;        
  12. parameter                BPS_P  = BPS/2;        

  13. input               clk          ;               
  14. input               rst_n        ;        
  15. input               din          ;
  16. output[DATA_W-1:0]  dout         ;               
  17. output              dout_vld     ;

  18. reg   [DATA_W-1:0]  dout         ;
  19. reg                 dout_vld     ;
  20. reg   [NUM_W-1 :0]  data_num     ;
  21. reg   [DATA_W-1:0]  rx_temp_data ;
  22. reg                 din_ff0      ;        
  23. reg                 din_ff1      ;        
  24. reg                 din_ff2      ;        
  25. reg                 flag_add     ;
  26. wire                end_cnt      ;
  27. wire                end_cnt_p    ;
  28. wire                add_data_num ;
  29. wire                end_data_num ;

  30. reg   [CNT_W-1:0]   cnt          ;        
  31. wire                add_cnt      ;
  32. always @ (posedge clk or negedge rst_n) begin
  33.         if(!rst_n) begin
  34.                 din_ff0 <= 1'b1;
  35.         din_ff1 <= 1'b1;
  36.         din_ff2 <= 1'b1;
  37.         end
  38.         else begin
  39.                 din_ff0 <= din;
  40.         din_ff1 <= din_ff0;
  41.         din_ff2 <= din_ff1;
  42.         end
  43. end

  44. always @ (posedge clk or negedge rst_n)begin
  45.         if(!rst_n) begin
  46.                 flag_add <= 1'b0;
  47.         end
  48.         else if(din_ff2 & ~din_ff1) begin               
  49.                 flag_add <= 1'b1;        
  50.         end
  51.         else if(data_num==4'd8&&end_cnt) begin               
  52.                 flag_add <= 1'b0;        
  53.         end
  54. end

  55. always @ (posedge clk or negedge rst_n)begin
  56.     if(!rst_n)begin
  57.         cnt <= 0;
  58.     end
  59.     else if(add_cnt)begin
  60.         if(end_cnt)begin
  61.             cnt <= 0;         
  62.         end
  63.         else begin
  64.             cnt <= cnt+1'b1;
  65.         end
  66.     end
  67.     else begin
  68.         cnt <= 0;
  69.     end
  70. end
  71. assign add_cnt = flag_add;
  72. assign end_cnt = add_cnt && cnt == BPS-1;



  73. always @(posedge clk or negedge rst_n) begin
  74.     if (rst_n==0) begin
  75.         data_num <= 0;
  76.     end
  77.     else if(add_data_num) begin
  78.         if(end_data_num)
  79.             data_num <= 0;
  80.         else
  81.             data_num <= data_num+1 ;
  82.    end
  83. end
  84. assign add_data_num = end_cnt;
  85. assign end_data_num = add_data_num  && data_num == 9-1 ;

  86. always @ (posedge clk or negedge rst_n)begin
  87.         if(!rst_n) begin
  88.                 dout <= 8'd0;
  89.         end
  90.         else if(add_cnt && cnt==BPS_P-1 && data_num!=0) begin               
  91.             dout<={din,{dout[7:1]}};
  92.         end
  93.     else begin
  94.         dout<=dout;
  95.     end
  96. end

  97. always @ (posedge clk or negedge rst_n)begin
  98.         if(!rst_n) begin
  99.                 dout_vld <= 1'b0;
  100.         end
  101.     else if(add_data_num && data_num == 4'd8) begin               
  102.                 dout_vld <= 1'b1;        
  103.         end
  104.         else begin        
  105.         dout_vld <= 1'b0;                        
  106.         end
  107. end
  108. endmodule
复制代码


1.3 BCD译码模块设计1.3.1接口信号
  
信号名
  
I/O
位宽
定义
clk
I
1
系统工作时钟 50M
rst_n
I
1
系统复位信号,低电平有效
din
I
8
8bit的输入数据
din_vld
I
1
输入数据有效指示信号
dout
O
12
12bit的输出BCD译码数据,每 4 bit一
  
组,分别表示百、十、个位的值
dout_vld
O
1
输出数据有效指示信号


1.3.2设计思路
&#216;  左移加3算法
此处二进制转 BCD 码的硬件实现,采用左移加 3 的算法,具体描述如下:(此处以 8-bit 二进制码为例)
1、左移要转换的二进制码 1
2、左移之后,BCD 码分别置于百位、十位、个位
3、如果移位后所在的 BCD 码列大于或等于 5,则对该值加 3
4、继续左移的过程直至全部移位完成

举例:将十六进制码 0xFF 转换成 BCD
2.png

1.3.3参考代码

  1. module bcd_water(
  2.         clk     ,
  3.         rst_n   ,
  4.         din     ,
  5.         din_vld ,
  6.         dout    ,
  7.         dout_vld
  8.     );
  9. input                   clk                 ;
  10. input                   rst_n               ;
  11. input       [ 7:0]      din                 ;
  12. input                   din_vld             ;
  13. output      [11:0]      dout                ;
  14. wire        [11:0]      dout                ;
  15. output                  dout_vld            ;
  16. wire                    dout_vld            ;
  17. reg         [19:0]      din_temp            ;
  18. reg         [19:0]      din_temp_ff0        ;
  19. reg         [19:0]      din_temp_ff1        ;
  20. reg         [19:0]      din_temp_ff2        ;
  21. reg         [19:0]      din_temp_ff3        ;
  22. reg         [19:0]      din_temp_ff4        ;
  23. wire        [20:0]      din_shift_temp      ;
  24. wire        [20:0]      din_shift_temp_ff0  ;
  25. wire        [20:0]      din_shift_temp_ff1  ;
  26. wire        [20:0]      din_shift_temp_ff2  ;
  27. wire        [20:0]      din_shift_temp_ff3  ;
  28. wire        [ 7:0]      din_a_temp          ;
  29. wire        [ 3:0]      din_b_temp          ;
  30. wire        [ 3:0]      din_c_temp          ;
  31. wire        [ 3:0]      din_d_temp          ;
  32. wire        [ 7:0]      din_add_a_temp      ;
  33. wire        [ 3:0]      din_add_b_temp      ;
  34. wire        [ 3:0]      din_add_c_temp      ;
  35. wire        [ 3:0]      din_add_d_temp      ;

  36. wire        [ 7:0]      din_a_temp_ff0      ;
  37. wire        [ 3:0]      din_b_temp_ff0      ;
  38. wire        [ 3:0]      din_c_temp_ff0      ;
  39. wire        [ 3:0]      din_d_temp_ff0      ;
  40. wire        [ 7:0]      din_a_temp_ff1      ;
  41. wire        [ 3:0]      din_b_temp_ff1      ;
  42. wire        [ 3:0]      din_c_temp_ff1      ;
  43. wire        [ 3:0]      din_d_temp_ff1      ;
  44. wire        [ 7:0]      din_a_temp_ff2      ;
  45. wire        [ 3:0]      din_b_temp_ff2      ;
  46. wire        [ 3:0]      din_c_temp_ff2      ;
  47. wire        [ 3:0]      din_d_temp_ff2      ;
  48. wire        [ 7:0]      din_a_temp_ff3      ;
  49. wire        [ 3:0]      din_b_temp_ff3      ;
  50. wire        [ 3:0]      din_c_temp_ff3      ;
  51. wire        [ 3:0]      din_d_temp_ff3      ;
  52. wire        [ 7:0]      din_add_a_temp_ff0  ;
  53. wire        [ 3:0]      din_add_b_temp_ff0  ;
  54. wire        [ 3:0]      din_add_c_temp_ff0  ;
  55. wire        [ 3:0]      din_add_d_temp_ff0  ;
  56. wire        [ 7:0]      din_add_a_temp_ff1  ;
  57. wire        [ 3:0]      din_add_b_temp_ff1  ;
  58. wire        [ 3:0]      din_add_c_temp_ff1  ;
  59. wire        [ 3:0]      din_add_d_temp_ff1  ;
  60. wire        [ 7:0]      din_add_a_temp_ff2  ;
  61. wire        [ 3:0]      din_add_b_temp_ff2  ;
  62. wire        [ 3:0]      din_add_c_temp_ff2  ;
  63. wire        [ 3:0]      din_add_d_temp_ff2  ;
  64. wire        [ 7:0]      din_add_a_temp_ff3  ;
  65. wire        [ 3:0]      din_add_b_temp_ff3  ;
  66. wire        [ 3:0]      din_add_c_temp_ff3  ;
  67. wire        [ 3:0]      din_add_d_temp_ff3  ;
  68. reg                     dout_vld_temp       ;
  69. reg                     dout_vld_temp_ff0   ;
  70. reg                     dout_vld_temp_ff1   ;
  71. reg                     dout_vld_temp_ff2   ;
  72. reg                     dout_vld_temp_ff3   ;
  73. reg                     dout_vld_temp_ff4   ;
  74.          
  75. always  @(posedge clk or negedge rst_n)begin
  76.     if(rst_n==1'b0)begin
  77.         din_temp <= 20'b0;
  78.     end
  79.     else if(din_vld)begin
  80.         din_temp <= {9'b0,din,3'b0};
  81.     end
  82. end
  83. always  @(posedge clk or negedge rst_n)begin
  84.     if(rst_n==1'b0)begin
  85.         dout_vld_temp <= 1'b0;
  86.     end
  87.     else if(din_vld)begin
  88.         dout_vld_temp <= 1'b1;
  89.     end
  90.     else begin
  91.         dout_vld_temp <= 1'b0;
  92.     end
  93. end
  94. assign  din_a_temp     = din_temp[ 7: 0]                                                     ;
  95. assign  din_b_temp     = din_temp[11: 8]                                                     ;
  96. assign  din_c_temp     = din_temp[15:12]                                                     ;
  97. assign  din_d_temp     = din_temp[19:16]                                                     ;
  98. assign  din_add_a_temp = din_a_temp                                                          ;
  99. assign  din_add_b_temp = din_b_temp + ((din_b_temp>=5)?4'd3:4'd0)                            ;
  100. assign  din_add_c_temp = din_c_temp + ((din_c_temp>=5)?4'd3:4'd0)                            ;
  101. assign  din_add_d_temp = din_d_temp + ((din_d_temp>=5)?4'd3:4'd0)                            ;
  102. assign  din_shift_temp = {din_add_d_temp,din_add_c_temp,din_add_b_temp,din_add_a_temp,1'b0}  ;


  103. always  @(posedge clk or negedge rst_n)begin
  104.     if(rst_n==1'b0)begin
  105.         din_temp_ff0 <= 20'b0;
  106.     end
  107.     else begin
  108.         din_temp_ff0 <= din_shift_temp[19:0];

  109.     end
  110. end
  111. always  @(posedge clk or negedge rst_n)begin
  112.     if(rst_n==1'b0)begin
  113.         dout_vld_temp_ff0 <= 1'b0 ;
  114.     end
  115.     else begin
  116.         dout_vld_temp_ff0 <= dout_vld_temp;
  117.     end
  118. end
  119. assign  din_a_temp_ff0     = din_temp_ff0[ 7: 0]                                             ;
  120. assign  din_b_temp_ff0     = din_temp_ff0[11: 8]                                             ;
  121. assign  din_c_temp_ff0     = din_temp_ff0[15:12]                                             ;
  122. assign  din_d_temp_ff0     = din_temp_ff0[19:16]                                             ;
  123. assign  din_add_a_temp_ff0 = din_a_temp_ff0                                                  ;
  124. assign  din_add_b_temp_ff0 = din_b_temp_ff0 + ((din_b_temp_ff0>=5)?4'd3:4'd0)                ;
  125. assign  din_add_c_temp_ff0 = din_c_temp_ff0 + ((din_c_temp_ff0>=5)?4'd3:4'd0)                ;
  126. assign  din_add_d_temp_ff0 = din_d_temp_ff0 + ((din_d_temp_ff0>=5)?4'd3:4'd0)                ;
  127. assign  din_shift_temp_ff0 = {din_add_d_temp_ff0,din_add_c_temp_ff0,din_add_b_temp_ff0,din_add_a_temp_ff0,1'b0};


  128. always  @(posedge clk or negedge rst_n)begin
  129.     if(rst_n==1'b0)begin
  130.         din_temp_ff1 <= 20'b0;
  131.     end
  132.     else begin
  133.         din_temp_ff1 <= din_shift_temp_ff0[19:0];
  134.     end
  135. end
  136. always  @(posedge clk or negedge rst_n)begin
  137.     if(rst_n==1'b0)begin
  138.         dout_vld_temp_ff1 <= 1'b0;
  139.     end
  140.     else begin
  141.         dout_vld_temp_ff1 <= dout_vld_temp_ff0;
  142.     end
  143. end
  144. assign  din_a_temp_ff1     = din_temp_ff1[ 7: 0]                                             ;
  145. assign  din_b_temp_ff1     = din_temp_ff1[11: 8]                                             ;
  146. assign  din_c_temp_ff1     = din_temp_ff1[15:12]                                             ;
  147. assign  din_d_temp_ff1     = din_temp_ff1[19:16]                                             ;
  148. assign  din_add_a_temp_ff1 = din_a_temp_ff1                                                  ;
  149. assign  din_add_b_temp_ff1 = din_b_temp_ff1 + ((din_b_temp_ff1>=5)?4'd3:4'd0)                ;
  150. assign  din_add_c_temp_ff1 = din_c_temp_ff1 + ((din_c_temp_ff1>=5)?4'd3:4'd0)                ;
  151. assign  din_add_d_temp_ff1 = din_d_temp_ff1 + ((din_d_temp_ff1>=5)?4'd3:4'd0)                ;
  152. assign  din_shift_temp_ff1 = {din_add_d_temp_ff1,din_add_c_temp_ff1,din_add_b_temp_ff1,din_add_a_temp_ff1,1'b0};


  153. always  @(posedge clk or negedge rst_n)begin
  154.     if(rst_n==1'b0)begin
  155.         din_temp_ff2 <= 20'b0;
  156.     end
  157.     else begin
  158.         din_temp_ff2 <= din_shift_temp_ff1[19:0];
  159.     end
  160. end
  161. always  @(posedge clk or negedge rst_n)begin
  162.     if(rst_n==1'b0)begin
  163.         dout_vld_temp_ff2 <= 1'b0;
  164.     end
  165.     else begin
  166.         dout_vld_temp_ff2 <= dout_vld_temp_ff1;
  167.     end
  168. end
  169. assign  din_a_temp_ff2     = din_temp_ff2[ 7: 0]                                             ;
  170. assign  din_b_temp_ff2     = din_temp_ff2[11: 8]                                             ;
  171. assign  din_c_temp_ff2     = din_temp_ff2[15:12]                                             ;
  172. assign  din_d_temp_ff2     = din_temp_ff2[19:16]                                             ;
  173. assign  din_add_a_temp_ff2 = din_a_temp_ff2                                                  ;
  174. assign  din_add_b_temp_ff2 = din_b_temp_ff2 + ((din_b_temp_ff2>=5)?4'd3:4'd0)                ;
  175. assign  din_add_c_temp_ff2 = din_c_temp_ff2 + ((din_c_temp_ff2>=5)?4'd3:4'd0)                ;
  176. assign  din_add_d_temp_ff2 = din_d_temp_ff2 + ((din_d_temp_ff2>=5)?4'd3:4'd0)                ;
  177. assign  din_shift_temp_ff2 = {din_add_d_temp_ff2,din_add_c_temp_ff2,din_add_b_temp_ff2,din_add_a_temp_ff2,1'b0};


  178. always  @(posedge clk or negedge rst_n)begin
  179.     if(rst_n==1'b0)begin
  180.         din_temp_ff3 <= 20'b0;
  181.     end
  182.     else begin
  183.         din_temp_ff3 <= din_shift_temp_ff2[19:0];
  184.     end
  185. end
  186. always  @(posedge clk or negedge rst_n)begin
  187.     if(rst_n==1'b0)begin
  188.         dout_vld_temp_ff3 <= 1'b0;
  189.     end
  190.     else begin
  191.         dout_vld_temp_ff3 <= dout_vld_temp_ff2;
  192.     end
  193. end
  194. assign  din_a_temp_ff3     = din_temp_ff3[ 7: 0]                                             ;
  195. assign  din_b_temp_ff3     = din_temp_ff3[11: 8]                                             ;
  196. assign  din_c_temp_ff3     = din_temp_ff3[15:12]                                             ;
  197. assign  din_d_temp_ff3     = din_temp_ff3[19:16]                                             ;
  198. assign  din_add_a_temp_ff3 = din_a_temp_ff3                                                  ;
  199. assign  din_add_b_temp_ff3 = din_b_temp_ff3 + ((din_b_temp_ff3>=5)?4'd3:4'd0)                ;
  200. assign  din_add_c_temp_ff3 = din_c_temp_ff3 + ((din_c_temp_ff3>=5)?4'd3:4'd0)                ;
  201. assign  din_add_d_temp_ff3 = din_d_temp_ff3 + ((din_d_temp_ff3>=5)?4'd3:4'd0)                ;
  202. assign  din_shift_temp_ff3 = {din_add_d_temp_ff3,din_add_c_temp_ff3,din_add_b_temp_ff3,din_add_a_temp_ff3,1'b0};


  203. always  @(posedge clk or negedge rst_n)begin
  204.     if(rst_n==1'b0)begin
  205.         din_temp_ff4 <= 20'b0;
  206.     end
  207.     else begin
  208.         din_temp_ff4 <= din_shift_temp_ff3[19:0];
  209.     end
  210. end
  211. always  @(posedge clk or negedge rst_n)begin
  212.     if(rst_n==1'b0)begin
  213.         dout_vld_temp_ff4 <= 1'b0;
  214.     end
  215.     else begin
  216.         dout_vld_temp_ff4 <= dout_vld_temp_ff3;
  217.     end
  218. end
  219. assign  dout     = din_temp_ff4[19:8];
  220. assign  dout_vld = dout_vld_temp_ff4 ;


  221. endmodule
复制代码




1.4 数码管显示模块设计1.4.1接口信号
  
信号名
  
I/O
位宽
定义
clk
I
1
系统工作时钟 50M
rst_n
I
1
系统复位信号,低电平有效
din
I
12
12位的输入BCD译码数据
din_vld
I
1
输入数据有效指示信号
segment
O
8
8位数码管段选信号
seg_sel
O
3
3位数码管位选信号


1.4.2设计思路
在前面的案例中已经有数码管显示的介绍,所以这里不在过多介绍,详细介绍请看下方链接:

1.4.3参考代码
  1. module  seg_disp(
  2.                  rst_n       ,
  3.                  clk         ,
  4.                  din         ,
  5.                  din_vld     ,
  6.                  seg_sel     ,
  7.                  segment      
  8.              );


  9. parameter  DATA_IN        =       12          ;
  10. parameter  TIME_30MS      =       15000        ;
  11. parameter  SEG_WID        =       8           ;
  12. parameter  SEG_NUM        =       8           ;
  13. parameter  CNT_WID        =       10          ;

  14. parameter  NUM_0          =       8'b1100_0000;
  15. parameter  NUM_1          =       8'b1111_1001;
  16. parameter  NUM_2          =       8'b1010_0100;
  17. parameter  NUM_3          =       8'b1011_0000;
  18. parameter  NUM_4          =       8'b1001_1001;
  19. parameter  NUM_5          =       8'b1001_0010;
  20. parameter  NUM_6          =       8'b1000_0010;
  21. parameter  NUM_7          =       8'b1111_1000;
  22. parameter  NUM_8          =       8'b1000_0000;
  23. parameter  NUM_9          =       8'b1001_0000;
  24. parameter  NUM_ERR        =       8'b1111_1111;


  25. input                             clk         ;
  26. input                             rst_n       ;
  27. input  [DATA_IN - 1:0]            din         ;
  28. input                             din_vld     ;

  29. output [SEG_NUM - 1:0]            seg_sel     ;
  30. output [SEG_WID - 1:0]            segment     ;

  31. reg    [SEG_NUM - 1:0]            seg_sel     ;
  32. reg    [SEG_WID - 1:0]            segment     ;

  33. reg    [ 31    :    0]            cnt_30us      ;
  34. reg    [SEG_NUM - 1:0]            sel_cnt     ;

  35. reg    [ 4 - 1 :    0]            seg_tmp     ;

  36. wire                              add_cnt_30us  ;
  37. wire                              end_cnt_30us  ;
  38. wire                              add_sel_cnt ;
  39. wire                              end_sel_cnt ;


  40. always @(posedge clk or negedge rst_n) begin
  41.     if (rst_n==0) begin
  42.         cnt_30us <= 0;
  43.     end
  44.     else if(add_cnt_30us) begin
  45.         if(end_cnt_30us)
  46.             cnt_30us <= 0;
  47.         else
  48.             cnt_30us <= cnt_30us+1 ;
  49.    end
  50. end
  51. assign add_cnt_30us = 1;
  52. assign end_cnt_30us = add_cnt_30us  && cnt_30us == TIME_30MS-1 ;


  53. always  @(posedge clk or negedge rst_n)begin
  54.     if(rst_n==1'b0)begin
  55.         sel_cnt <= 0;
  56.     end
  57.     else if(add_sel_cnt)begin
  58.         if(end_sel_cnt)
  59.             sel_cnt <= 0;
  60.         else
  61.             sel_cnt <= sel_cnt + 1;
  62.     end
  63. end
  64. assign add_sel_cnt = end_cnt_30us;
  65. assign end_sel_cnt = add_sel_cnt && sel_cnt == SEG_NUM-1;

  66. always  @(posedge clk or negedge rst_n)begin
  67.     if(rst_n==1'b0)begin
  68.         seg_sel <= {SEG_NUM{1'b1}};
  69.     end
  70.     else begin
  71.         seg_sel <= ~(1'b1 << sel_cnt);
  72.     end
  73. end



  74. always  @(posedge clk or negedge rst_n)begin
  75.     if(rst_n==1'b0)begin
  76.         seg_tmp <= 0;
  77.     end
  78.     else begin
  79.         seg_tmp <= din[4*(sel_cnt+1)-1 -:4];
  80.     end
  81. end




  82. always@(posedge clk or negedge rst_n)begin
  83.     if(rst_n==1'b0)begin
  84.         segment<=NUM_0;
  85.     end
  86.     else  begin
  87.         case (seg_tmp)
  88.             0 : segment <= NUM_0;
  89.             1 : segment <= NUM_1;
  90.             2 : segment <= NUM_2;
  91.             3 : segment <= NUM_3;
  92.             4 : segment <= NUM_4;
  93.             5 : segment <= NUM_5;
  94.             6 : segment <= NUM_6;
  95.             7 : segment <= NUM_7;
  96.             8 : segment <= NUM_8;
  97.             9 : segment <= NUM_9;
  98.             default : segment <= NUM_ERR;
  99.         endcase
  100.     end
  101. end

  102. endmodule
复制代码


1.5 效果和总结


&#216;  下图是该工程在db603开发板上的现象——串口发送数据8’h93,数码管显示12’d147
3.jpg


4.jpg


&#216;  下图是该工程在mp801试验箱上的现象——串口发送数据8’he9,数码管显示12’d233

5.jpg



8.jpg


&#216;  下图是该工程在ms980试验箱上的现象——串口发送数据8’h52,数码管显示12’d082
6.jpg


7.jpg




由于该项目的上板现象是串口发送8位的十六进制数经过BCD译码后,在数码管上显示对应的十进制数值,想观看完整现象的朋友可以看一下上板演示的视频。
感兴趣的朋友也可以访问明德扬论坛(http://www.fpgabbs.cn/)进行FPGA相关工程设计学习,也可以看一下我们往期的文章:

1.6 公司简介
明德扬是一家专注于FPGA领域的专业性公司,公司主要业务包括开发板、教育培训、项目承接、人才服务等多个方向。点拨开发板——学习FPGA的入门之选。
MP801
开发板——千兆网、ADDA、大容量SDRAM等,学习和项目需求一步到位。网络培训班——不管时间和空间,明德扬随时在你身边,助你快速学习FPGA周末培训班——明天的你会感激现在的努力进取,升职加薪明德扬来助你。就业培训班——七大企业级项目实训,获得丰富的项目经验,高薪就业。专题课程——高手修炼课:提升设计能力;实用调试技巧课:提升定位和解决问题能力;FIFO架构设计课:助你快速成为架构设计师;时序约束、数字信号处理、PCIE、综合项目实践课等你来选。项目承接——承接企业FPGA研发项目。人才服务——提供人才推荐、人才代培、人才派遣等服务。

【设计教程下载】

至简设计系列案例_BCD译码实现.pdf (2.07 MB, 下载次数: 1773)
mdyBcdDecode.zip (13.78 KB, 下载次数: 1806)
FPGA视频课程  培训班 FPGA学习资料
吴老师 18022857217(微信同号) Q1241003385

0

主题

2

帖子

81

积分

注册会员

Rank: 2

积分
81
发表于 2021-8-18 12:01:31 | 显示全部楼层
谢谢,为什么不能下载

78

主题

106

帖子

4625

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
4625
发表于 2021-9-3 08:52:49 | 显示全部楼层

经测试,可以正常下载的。需要登陆才能下载  
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|MDYBBS ( 粤ICP备16061416号 )

GMT+8, 2024-3-28 21:21 , Processed in 0.082284 second(s), 34 queries .

Powered by Discuz! X3.4

本论坛由广州健飞通信有限公司所有

© 2001-2019 Comsenz Inc.

快速回复 返回顶部 返回列表