我的FPGA学习笔记--串口接收模块
程序员文章站
2022-06-23 17:19:45
...
我的FPGA学习笔记–串口接收模块
1.模块接口信号
信号名 | 位宽 | I/O | 功能 |
---|---|---|---|
clk | 1 | I | 工作时钟,时钟频率为50M |
rst_n | 1 | I | 复位信号,低电平有效 |
din | 1 | I | Uart 输入数据(RX) |
dout | 8 | O | 输出数据信号 |
dout_vld | 1 | O | 数据有效指示信号,高电平有效 |
2.功能说明
该模块的功能:负责接收串口的数据,将串行数据转化为并行数据。串口波特率9600,无奇偶校验位。
串口时序说明:
串口时序如图,包括一个起始位,8个数据位和1个停止位,期中起始位为0,停止位为1,中间的八个位为数据位,期中低拉在前,高位在后。
计数时间说明:
波特率指的是1s内发送接收了多少比特的数据,若波特率为9600b/s,则1s可以传输9600bit,那么传输1bit的时间为:1/9600 s。
输出说明:
dout :din波形如上图所示,din的第一个下降沿表示开始传输数据,din依次为0、{1、0、1、1、0、1、1、0、}1,根据串口协议,当din输出停止位的同时,dout_vld= 1,且dout=8’b0110_1101(8’h6d) 。
3.verilog代码实现
module uart_rx(
clk ,
rst_n ,
rx ,
dout_vld ,
dout
);
input clk ;
input rst_n ;
input rx ;
output dout_vld;
output[7:0] dout ;
reg dout_vld;
reg [7:0] dout ;
reg [12:0] cnt0 ;
wire add_cnt0;
wire end_cnt0;
reg [3:0] cnt1 ;
wire add_cnt1;
wire end_cnt1;
reg rx_ff0 ;
reg rx_ff1 ;
reg rx_ff2 ;
reg flag_add;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt0 <= 0;
end
else if(add_cnt0)begin
if(end_cnt0)
cnt0 <= 0;
else
cnt0 <= cnt0 + 1;
end
end
assign add_cnt0 = flag_add == 1;
assign end_cnt0 = add_cnt0 && cnt0== 5208-1;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt1 <= 0;
end
else if(add_cnt1)begin
if(end_cnt1)
cnt1 <= 0;
else
cnt1 <= cnt1 + 1;
end
end
assign add_cnt1 = end_cnt0;
assign end_cnt1 = add_cnt1 && cnt1== 9-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout_vld <= 0;
end
else if(end_cnt1)begin
dout_vld <= 1;
end
else begin
dout_vld <= 0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout <= 0;
end
else if(add_cnt0 && cnt0==2604-1 cnt1!=0) begin
dout[cnt1-1] <= rx;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
rx_ff0 <= 1;
rx_ff1 <= 1;
rx_ff2 <= 1;
end
else begin
rx_ff0 <= rx;
rx_ff1 <= rx_ff0;
rx_ff2 <= rx_ff1;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
flag_add <= 0;
end
else if(flag_add == 0 && rx_ff1==0 && rx_ff2==1)begin
flag_add <= 1;
end
else if(end_cnt1)begin
flag_add <= 0;
end
end
4.注意事项
由于din是异步信号,按规范需要2拍才能保证正确接收。
因此增加如下代码:
2020/1/19学习笔记
上一篇: 串口收发之ram存取
下一篇: 中医治疗抑郁症的方法?