基于rs232的lcd图像显示

1.使用uart_rx模块作为图像接受模块

  1. 波特率的计算

波特率:每秒钟通过信号传输的码元数称为码元的传输速率

使用时钟频率 除以 波特率 可以得到传输每个码源所占用的时钟周期数

$baud_cnt_max = $

  1. 为什么要做打两拍操作

消除亚稳态,稳定信号。

在找下降沿时,不能使用\(rx\_reg1\)\(rx\_reg2\) 求得,因为\(rx\_reg1\) 信号不稳定,使用其求得的结果也不稳定,因此将 \(rx\_reg2\)再打一拍,使用\(rx\_reg2\)\(rx\_reg3\) 求得。

  1. 代码中 \(bit\_cnt\) 只计数到8

这是因为没有计数停止位,所以只有0~8 共计数 9位(1位起始位+8位数据位)。

  1. rs232数据移位方向:

最先传输的比特在低位,最后传输的比特在高位

PC机通过串口调试助手往FPGA发8bit数据时,FPGA通过串口线rx一位一位地接收,从最低位到最高位依次接收,最后在FPGA里面位拼接成8比特数据。

  1. 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
module uart_rx
#parameter
(
parameter UART_BPS = 'd9600,
CLK_FREQ = 'd50_000_000
)
(
input sys_clk,sys_rst_n,
input rx,

output reg [7:0] po_data,
output reg po_flag
);

localparam BAUD_CNT_MAX = CLK_FREQ / UART_BPS;

reg rx_reg1;
reg rx_reg2;
reg rx_reg3;
reg start_nedge;
reg work_en;
reg [12:0] baud_cnt;
reg bit_flag;
reg [3:0] bit_cnt;
reg [7:0] rx_data;
reg rx_flag;

always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
rx_reg1 <= 1'b0;
else
rx_reg1 <= rx;

always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
rx_reg2 <= 1'b0;
else
rx_reg2 <= rx_reg1;

always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
rx_reg3 <= 1'b0;
else
rx_reg3 <= rx_reg2;

always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
start_nedge <= 1'b0;
else if(rx_reg2 == 1'b0 && rx_reg3 == 1'b1)
start_nedge <= 1'b1;
else
start_nedge <= 1'b0;

always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
work_en <= 1'b0;
else if(start_nedge == 1'b1) // 开始工作条件
work_en <= 1'b1;
else if(bit_cnt == 4'd8 && bit_flag == 1'b1) // 停止工作条件:完成一个字节的传输
work_en <= 1'b0;

always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
baud_cnt <= 13'b0;
else if(baud_cnt == BAUD_CNT_MAX - 1 && work_en == 1'b1)
baud_cnt <= 13'b0;
else if(work_en == 1'b1)
baud_cnt <= baud_cnt + 1;
else
baud_cnt <= 13'b0; // 传输完成,停止工作,波特计数器清零

always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
bit_flag <= 1'b0;
else if(baud_cnt == BAUD_CNT_MAX / 2 - 1)
bit_flag <= 1'b1;
else
bit_flag <= 1'b0;

// 这里由于没有计数停止位,所以只对0~8计数
// 传输停止位时已经将work_en拉低,不会使bit_flag有效,因此bit_cnt也不会计数
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
bit_cnt <= 4'b0;
else if(bit_cnt == 4'd8 && bit_flag == 1'b1)
bit_cnt <= 4'd0;
else if(bit_flag == 1'b1)
bit_cnt <= bit_cnt + 1;

// 对数据进行移位
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
rx_data <= 8'b0;
else if(bit_flag == 1'b1 && bit_cnt >= 4'd1 && bit_cnt <= 4'd8)
rx_data = {rx_reg3,rx_data[7:1]};

// 传输完8比特,拉高rx_flag
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
rx_flag <= 1'b0;
else if(bit_cnt == 4'd8 && bit_flag == 1'b1) // 8位的最后一个比特传输完成
rx_flag <= 1'b1;
else
rx_flag <= 1'b0;

// po_data 和 po_flag 都以 rx_data 为基准,可以实现统一时间输出
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
po_data <= 8'b0;
else if(rx_flag == 1'b1)
po_data <= rx_data;

always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
po_flag <= 1'b0;
else
po_flag <= rx_flag;

endmodule