一、Fpga--PLL锁相环的使用
通过PLL锁相环IP的使用,可以输入时钟进行分频,倍频,也可以产生多路时钟输出信号。
外部提供晶振的原因:①Fpga电路大多数需要时序分析
②晶振在Fpga内部占空间大,所以放置于外部PCB板上
Uart异步传输速率不能很快的原因:考虑到工程实际问题,假如时钟周期大(传输速率慢的话),采取到数据电平变化的边沿时刻的概率会小很多,这样数据也很准确,通常uart适用于2M.
二、Uart 发送
2.1 uart_byte_tx(字节发送)

2.1.1模块设计框图

2.1.2 Verilog设计及仿真
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Description: UART 字节发送
//////////////////////////////////////////////////////////////////////////////////
module uart_tx_byte(
Clk ,
Rst_n ,
data_byte ,
send_en ,
Baud_Set ,
uart_tx ,
Tx_Done ,
uart_state
);
input Clk ; //模块全局时钟输入,50M
input Rst_n ; //复位信号输入,低有效
input [7:0] data_byte ; //待传输8bit数据
input send_en ; //发送使能
input [2:0] Baud_Set ; //波特率设置
output reg uart_tx ; //串口输出信号
output reg Tx_Done ; //1byte数据发送完成标志
output reg uart_state ; //发送数据状态
localparam START_BIT = 1'b0;
localparam STOP_BIT = 1'b1;
reg bps_clk ; //波特率时钟
reg [15:0] div_cnt ; //分频计数器
reg [15:0] bps_DR ; //分频计数最大值
reg [3:0] bps_cnt ; //波特率时钟计数器
reg [7:0] data_byte_reg; //data_byte寄存后数据
//******************** UART发送状态标志 ****************** \\
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
uart_state <= 1'b0;
else if(send_en)
uart_state <= 1'b1;
else if(bps_cnt >= 4'd11)
uart_state <= 1'b0;
else
uart_state <= uart_state;
end
//******************** 输入数据锁存 ****************** \\
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
data_byte_reg <= 8'd0;
else if(send_en)
data_byte_reg <= data_byte;
else
data_byte_reg <= data_byte_reg;
end
//******************** 波特率时钟的生成模块 ****************** \\
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
bps_DR <= 16'd5207;
else begin
case(Baud_Set)
0:bps_DR <= 16'd5207; //波特率为9600 1_000_000_000/9600/20
1:bps_DR <= 16'd2603; //波特率为19200
2:bps_DR <= 16'd1301; //波特率为38400
3:bps_DR <= 16'd867; //波特率为57600
4:bps_DR <= 16'd433; //波特率为115200
default:bps_DR <= 16'd5207;
endcase
end
end
//counter
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
div_cnt <= 16'd0;
else if(uart_state)begin
if(div_cnt >= bps_DR)
div_cnt <= 16'd0;
else
div_cnt <= div_cnt + 1'b1;
end
else
div_cnt <= 16'd0;
end
// bps_clk gen
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
bps_clk <= 1'b0;
else if(div_cnt == 16'd1) //由于UART发送是从bps_cnt =1 发起始位,而不是从0,因此为了尽快进入发送模块,我们计数器不计满+1,等于一时+1
bps_clk <= 1'b1;
else
bps_clk <= 1'b0;
end
//******************** Uart的数据发送模块 ****************** \\
//bps counter
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
bps_cnt <= 4'd0;
else if(bps_cnt >= 4'd11)
bps_cnt <= 4'd0;
else if(bps_clk)
bps_cnt <= bps_cnt + 1'b1;
else
bps_cnt <= bps_cnt;
end
//数据发送
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
uart_tx <= 1'b1;
else begin
case(bps_cnt)
0:uart_tx <= 1'b1;
1:uart_tx <= START_BIT; // 从1开始,避免了起始位0与空闲态1冲突
2:uart_tx <= data_byte_reg[0];
3:uart_tx <= data_byte_reg[1];
4:uart_tx <= data_byte_reg[2];
5:uart_tx <= data_byte_reg[3];
6:uart_tx <= data_byte_reg[4];
7:uart_tx <= data_byte_reg[5];
8:uart_tx <= data_byte_reg[6];
9:uart_tx <= data_byte_reg[7];
10:uart_tx <= STOP_BIT;
default:uart_tx <= 1'b1;
endcase
end
end
//数据发送完成标志
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
Tx_Done <= 1'b0;
else if(bps_cnt >= 4'd11)
Tx_Done <= 1'b1;
else
Tx_Done <= 1'b0;
end
endmodule
由上图可知,uart发送先发低位再发高位(aa 10101010)

最低0.47元/天 解锁文章
&spm=1001.2101.3001.5002&articleId=137742055&d=1&t=3&u=1deffb26a1a445aaa7f4f246b57ada8d)
27万+

被折叠的 条评论
为什么被折叠?



