概述
这里写目录标题
- 一、UART基础知识
- 四、代码
- 三、代码
- 四、ModelSim仿真
一、UART基础知识
UART 是一种采用异步串行通信方式的通用异步收发传输器
UART串口通信需要两根信号线来实现,一根用于串口发送,另外一根负责串口接收
传输速率:串口通信的速率用波特率表示,常用的波特率有9600、19200、38400、57600以及115200等。
四、代码
三、代码
//参数定义
//波特率
`define BAUD_9600 5208
`define BAUD_19200 2604
`define BAUD_38400 1302
`define BAUD_115200 434
`define STOP_BIT 1'b1 //数据停止位
`define START_BIT 1'b0 //数据开始位
uart_test
module uart_test(
input clk ,
input rst_n ,
input uart_rxd ,
output uart_txd
);
//参数定义
//中间信号定义
//control-->uart_tx
wire [7:0] rx_dout ;
wire rx_dout_vld ;
//uart_rx-->control
wire [7:0] tx_din ;
wire tx_din_vld ;
//uart_tx-->control
wire busy ;
//模块例化
control u_control
(
/*input */.clk (clk ),
/*input */.rst_n (rst_n ),
/*input [7:0] */.byte_din (rx_dout ),
/*input */.byte_din_vld (rx_dout_vld ),
/*input */.busy (busy ),
/*output [7:0] */.byte_dout (tx_din ),
/*output */.byte_dout_vld (tx_din_vld )
);
uart_rx u_uart_rx
(
/*input */.clk (clk ),
/*input */.rst_n (rst_n ),
/*input */.rx_din (uart_rxd ),
/*input [1:0] */.baud_sel (2'b0 ),
/*output [7:0] */.rx_byte (rx_dout ),
/*output */.rx_byte_vld (rx_dout_vld )
);
uart_tx u_uart_tx
(
/*input */.clk (clk ),
/*input */.rst_n (rst_n ),
/*input [1:0] */.baud_sel (2'b0 ),
/*input [7:0] */.tx_byte (tx_din ),
/*input */.tx_byte_vld (tx_din_vld ),
/*output */.tx_dout (uart_txd ),
/*output */.busy (busy )
);
endmodule
control
module control
(
input clk ,
input rst_n ,
input [7:0] byte_din ,
input byte_din_vld ,
input busy ,
output [7:0] byte_dout ,
output byte_dout_vld
);
//信号定义
reg [7:0] rxfifo_data ;
reg rxfifo_data_vld ;
reg rxfifo_wrreq_flag ;
//rxfifo
wire [7:0] rxfifo_din ;
wire rxfifo_rdreq ;
wire rxfifo_wrreq ;
wire rxfifo_empty ;
wire rxfifo_full ;
wire [7:0] rxfifo_dout ;
wire [7:0] rxfifo_usedw ;
//rxfifo_data 数据寄存
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
rxfifo_data <= 0;
end
else if(byte_din_vld)begin
rxfifo_data <= byte_din;
end
else begin
rxfifo_data <= rxfifo_data;
end
end
//rxfifo_data_vld
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
rxfifo_data_vld <= 0;
end
else begin
rxfifo_data_vld <= byte_din_vld;
end
end
//rxfifo_wrreq_flag 当fifo存储数据大于5,fifo存储的数据全部输出
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
rxfifo_wrreq_flag <= 0;
end
else if(rxfifo_usedw > 5)begin
rxfifo_wrreq_flag <= 1;
end
else if(rxfifo_empty)begin
rxfifo_wrreq_flag <= 0;
end
end
//模块例化
//rxfifo
rxfifo u_rxfifo (
.aclr ( ~rst_n ),
.clock ( clk ),
.data ( rxfifo_din ),
.rdreq ( rxfifo_rdreq ),
.wrreq ( rxfifo_wrreq ),
.empty ( rxfifo_empty ),
.full ( rxfifo_full ),
.q ( rxfifo_dout ),
.usedw ( rxfifo_usedw )
);
assign rxfifo_din = rxfifo_data;
assign rxfifo_wrreq = rxfifo_data_vld && !rxfifo_full;
assign byte_dout = rxfifo_dout;
assign rxfifo_rdreq = !rxfifo_empty && (rxfifo_wrreq_flag) && (busy == 0);
assign byte_dout_vld = rxfifo_rdreq;
endmodule
uart_rx
`include "param.v"
module uart_rx
(
input clk ,
input rst_n ,
input rx_din ,
input [1:0] baud_sel ,
output [7:0] rx_byte ,
output rx_byte_vld
);
//信号定义
reg [12:0] cnt_baud ;
wire add_cnt_baud ;
wire end_cnt_baud ;
reg [12:0] baud_num ;
reg flag ;
reg [3:0] cnt_byte ;
wire add_cnt_byte ;
wire end_cnt_byte ;
reg [1:0] din_r ;
wire nege ;
reg [9:0] rx_data ;
reg rx_data_vld ;
//计数器
//波特率计数器
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_baud <= 0;
end
else if(add_cnt_baud)begin
if(end_cnt_baud)begin
cnt_baud <= 0;
end
else begin
cnt_baud <= cnt_baud + 1;
end
end
else begin
cnt_baud <= cnt_baud;
end
end
assign add_cnt_baud = flag;
assign end_cnt_baud = add_cnt_baud && cnt_baud == baud_num-1;
//比特计数器
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_byte <= 0;
end
else if(add_cnt_byte)begin
if(end_cnt_byte)begin
cnt_byte <= 0;
end
else begin
cnt_byte <= cnt_byte + 1;
end
end
else begin
cnt_byte <= cnt_byte;
end
end
assign add_cnt_byte = end_cnt_baud;
assign end_cnt_byte = add_cnt_byte && cnt_byte == 9;
//flag 波特率计数器运行标志 1:运行 0:停止
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
flag <= 0;
end
else if(nege)begin
flag <= 1;
end
else if(cnt_byte == 9 && end_cnt_baud)begin
flag <= 0;
end
end
//baud_num 波特率选择 baud_sel:0 ————>9600 1————>19200 2————>38400 3————>115200
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
baud_num <= 0;
end
else begin
case (baud_sel)
0 : begin
baud_num <= `BAUD_9600;
end
1 : begin
baud_num <= `BAUD_19200;
end
2 : begin
baud_num <= `BAUD_38400;
end
3 : begin
baud_num <= `BAUD_115200;
end
default: begin
baud_num <= baud_num;
end
endcase
end
end
//nege din_r 打拍 检测数据起始位
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
din_r <= 0;
end
else begin
din_r <= {din_r[0],rx_din};
end
end
assign nege = !din_r[0]&din_r[1];
//rx_data 将比特数据转换为字节
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
rx_data <= 0;
end
else if(flag && cnt_baud ==2500)begin
rx_data[cnt_byte] <= rx_din;
end
else begin
rx_data <= rx_data;
end
end
//rx_data_vld 当数据停止位等于1,数据有效
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
rx_data_vld <= 0;
end
else if(cnt_byte == 9 )begin
rx_data_vld <= flag && cnt_baud ==2700 && rx_data[9] == 1;
end
else begin
rx_data_vld <= rx_data_vld;
end
end
assign rx_byte = rx_data[8:1];
assign rx_byte_vld = rx_data_vld;
endmodule
uart_tx
`include "param.v"
module uart_tx
(
input clk ,
input rst_n ,
input [1:0] baud_sel ,
input [7:0] tx_byte ,
input tx_byte_vld ,
output tx_dout ,
output busy
);
//信号定义
reg [12:0] cnt_baud ;
wire add_cnt_baud;
wire end_cnt_baud;
reg [12:0] baud_num ;
reg [3:0] cnt_bit ;
wire add_cnt_bit ;
wire end_cnt_bit ;
reg dout ;
reg [9:0] tx_data ;
reg flag ;
//计数器
//波特率计数器
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_baud <= 0;
end
else if(add_cnt_baud)begin
if(end_cnt_baud)begin
cnt_baud <= 0;
end
else begin
cnt_baud <= cnt_baud + 1;
end
end
else begin
cnt_baud <= cnt_baud;
end
end
assign add_cnt_baud = flag;
assign end_cnt_baud = add_cnt_baud && cnt_baud == baud_num-1;
//比特计数器
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_bit <= 0;
end
else if(add_cnt_bit)begin
if(end_cnt_bit)begin
cnt_bit <= 0;
end
else begin
cnt_bit <= cnt_bit + 1;
end
end
else begin
cnt_bit <= cnt_bit;
end
end
assign add_cnt_bit = end_cnt_baud;
assign end_cnt_bit = add_cnt_bit && cnt_bit == 9;
//flag 波特率计数器使用标志信号 1:计数器运行 0:计数器停止
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
flag <= 0;
end
else if(tx_byte_vld)begin //数据长有效,数据一直发送同一个?
flag <= 1;
end
else if(cnt_bit==9 && end_cnt_baud)begin
flag <= 0;
end
end
//baud_num 波特率选择 baud_sel:0 ————>9600 1————>19200 2————>38400 3————>115200
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
baud_num <= 0;
end
else begin
case (baud_sel)
0 : begin
baud_num <=`BAUD_9600;
end
1 : begin
baud_num <= `BAUD_19200;
end
2 : begin
baud_num <= `BAUD_38400;
end
3 : begin
baud_num <= `BAUD_115200;
end
default: begin
baud_num <= baud_num;
end
endcase
end
end
//tx_data 添加数据的起始位:0 停止位: 1 发送数据低位-->高位
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
tx_data <= 0;
end
else if(tx_byte_vld)begin
tx_data <= {`STOP_BIT,tx_byte,`START_BIT};
end
else begin
tx_data <=tx_data;
end
end
//输出
//dout 将字节数据转换为比特输出
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
dout <= 1;
end
else if(flag)begin
dout <= tx_data[cnt_bit];
end
else begin
dout <= dout;
end
end
//busy tx_dout
assign tx_dout = dout; //uart tx 数据输出
assign busy = flag; //busy 忙标志 1:忙状态 0:空闲状态
endmodule
四、ModelSim仿真
最后
以上就是甜美玉米为你收集整理的【FPGA】UART串口通信一、UART基础知识四、代码三、代码四、ModelSim仿真的全部内容,希望文章能够帮你解决【FPGA】UART串口通信一、UART基础知识四、代码三、代码四、ModelSim仿真所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复