--作者:肖肖肖
本文为明德扬原创及录用文章,转载请注明出处!
1.1 总体设计
1.1.1 概述
BCD码(Binary-Coded Decimal),用4位二进制数来表示1位十进制数中的0~9这10个数码,是一种二进制的数字编码形式,用二进制编码的十进制代码。BCD码这种编码形式利用了四个位元来储存一个十进制的数码,使二进制和十进制之间的转换得以快捷的进行。
1.1.2 设计目标
实现BCD译码并显示十进制结果的程序,具体功能要求如下:
1. 串口发送8位十六进制数给FPGA;
2. FPGA接收串口数据并对其进行BCD译码;
3. 在数码管上以十进制显示串口发送的数值。
1.1.3 系统结构框图
系统结构框图如下图一所示:
![145cf06c0e74b792b18e08e247a5eadf.png](https://img-blog.csdnimg.cn/img_convert/145cf06c0e74b792b18e08e247a5eadf.png)
图一
1.1.4 模块功能
Ø 串口接收模块实现功能
1、 接收上位机PC发来的位宽为8的十六进制数据。
Ø BCD译码模块实现功能
1、 对接收到的8位十六进制数据进行BCD译码。
Ø 数码管显示模块实现功能
1、 显示BCD译码后的十进制数值。
1.1.5 顶层信号
![8d02c5600ab906f2b2bd5190dd234891.png](https://img-blog.csdnimg.cn/img_convert/8d02c5600ab906f2b2bd5190dd234891.png)
1.1.6 参考代码
下面是使用工程的顶层代码:
1. module top(
2. clk ,
3. rst_n ,
4. rx_uart ,
5. seg_sel ,
6. segment
7. );
8.
9. parameter DATA_W = 8;
10. parameter SEG_WID = 8;
11. parameter SEL_WID = 3;
12. parameter BCD_OUT = 12;
13.
14. input clk ;
15. input rst_n ;
16. input rx_uart ;
17.
18. output[SEL_WID-1:0] seg_sel ;
19. output[SEG_WID-1:0] segment ;
20.
21. wire [SEL_WID-1:0] seg_sel ;
22. wire [SEG_WID-1:0] segment ;
23.
24. wire [DATA_W-1 :0] rx_dout ;
25. wire rx_dout_vld ;
26. wire [BCD_OUT-1:0] bcd_dout ;
27. wire bcd_dout_vld ;
28.
29. uart_rx u1(
30. .clk ( clk ),
31. .rst_n ( rst_n ),
32. .din ( rx_uart ),
33. .dout ( rx_dout ),
34. .dout_vld ( rx_dout_vld )
35. );
36.
37. bcd_water u2(
38. .clk ( clk ),
39. .rst_n ( rst_n ),
40. .din ( rx_dout ),
41. .din_vld ( rx_dout_vld ),
42. .dout ( bcd_dout ),
43. .dout_vld ( bcd_dout_vld )
44. );
45.
46. seg_disp u3(
47. .clk ( clk ),
48. .rst_n ( rst_n ),
49. .din ( bcd_dout ),
50. .din_vld ( bcd_dout_vld ),
51. .seg_sel ( seg_sel ),
52. .segment ( segment )
53. );
54.
55.
56. endmodule
1.2 串口接收模块设计
1.2.1 接口信号
![6785610b96fe4f4bf7accd9ee256a7c7.png](https://img-blog.csdnimg.cn/img_convert/6785610b96fe4f4bf7accd9ee256a7c7.png)
1.2.2 设计思路
在前面的案例中已经有串口接收模块的介绍,所以这里不在过多介绍
1.2.3 参考代码
1. module uart_rx(
2. clk ,
3. rst_n ,
4. din ,
5. dout ,
6. dout_vld
7. );
8.
9. parameter DATA_W = 8 ;
10. parameter NUM_W = 4 ;
11. parameter CNT_W = 14 ;
12. parameter BPS = 5208 ;
13. parameter BPS_P = BPS/2;
14.
15. input clk ;
16. input rst_n ;
17. input din ;
18. output[DATA_W-1:0] dout ;
19. output dout_vld ;
20.
21. reg [DATA_W-1:0] dout ;
22. reg dout_vld ;
23. reg [NUM_W-1 :0] data_num ;
24. reg [DATA_W-1:0] rx_temp_data ;
25. reg din_ff0 ;
26. reg din_ff1 ;
27. reg din_ff2 ;
28. reg flag_add ;
29. wire end_cnt ;
30. wire end_cnt_p ;
31. wire add_data_num ;
32. wire end_data_num ;
33.
34. reg [CNT_W-1:0] cnt ;
35. wire add_cnt ;
36. always @ (posedge clk or negedge rst_n) begin
37. if(!rst_n) begin
38. din_ff0 <= 1'b1;
39. din_ff1 <= 1'b1;
40. din_ff2 <= 1'b1;
41. end
42. else begin
43. din_ff0 <= din;
44. din_ff1 <= din_ff0;
45. din_ff2 <= din_ff1;
46. end
47. end
48.
49. always @ (posedge clk or negedge rst_n)begin
50. if(!rst_n) begin
51. flag_add <= 1'b0;
52. end
53. else if(din_ff2 & ~din_ff1) begin
54. flag_add <= 1'b1;
55. end
56. else if(data_num==4'd8&&end_cnt) begin
57. flag_add <= 1'b