Слияние кода завершено, страница обновится автоматически
`timescale 1ns / 1ps
// ********************************************************************
// FileName : Uart_Bus.v
// Author :hpy
// Email :yuan_hp@qq.com
// Date :2020年08月09日
// Description :uart模块 默认使用12MHz,波特率9600
// --------------------------------------------------------------------
// ****************************
// 波特率模块
// ****************************
module Baud #
(
parameter BPS_PARA = 1250 //当使用12MHz时钟时波特率参数选择1250对应9600的波特率
)
(
input clk_in, //系统时钟
input rst_n_in, //系统复位,低有效
input bps_en, //接收或发送时钟使能
output reg bps_clk //接收或发送时钟输出
);
reg [12:0] cnt;
//计数器计数满足波特率时钟要求
always @ (posedge clk_in or negedge rst_n_in) begin
if(!rst_n_in)
cnt <= 1'b0;
else if((cnt >= BPS_PARA-1)||(!bps_en)) //当时钟信号不使能(bps_en为低电平)时,计数器清零并停止计数
cnt <= 1'b0; //当时钟信号使能时,计数器对系统时钟计数,周期为BPS_PARA个系统时钟周期
else
cnt <= cnt + 1'b1;
end
//产生相应波特率的时钟节拍,接收模块将以此节拍进行UART数据接收
always @ (posedge clk_in or negedge rst_n_in)
begin
if(!rst_n_in)
bps_clk <= 1'b0;
else if(cnt == (BPS_PARA>>1)) //BPS_PARA右移一位等于除2,因计数器终值BPS_PARA为数据更替时间点,所以计数器中值时为数据最稳定时间点
bps_clk <= 1'b1;
else
bps_clk <= 1'b0;
end
endmodule
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ****************************
// 接收数据模块
// ****************************
module Uart_Rx
(
input clk_in, //系统时钟
input rst_n_in, //系统复位,低有效
output reg bps_en, //接收时钟使能
input bps_clk, //接收时钟输入
input rs232_rx, //UART接收输入
output reg [7:0] rx_data //接收到的数据
);
reg rs232_rx0,rs232_rx1,rs232_rx2;
//多级延时锁存去除亚稳态
always @ (posedge clk_in or negedge rst_n_in) begin
if(!rst_n_in) begin
rs232_rx0 <= 1'b0;
rs232_rx1 <= 1'b0;
rs232_rx2 <= 1'b0;
end else begin
rs232_rx0 <= rs232_rx;
rs232_rx1 <= rs232_rx0;
rs232_rx2 <= rs232_rx1;
end
end
//检测UART接收输入信号的下降沿
wire neg_rs232_rx = rs232_rx2 & rs232_rx1 & (~rs232_rx0) & (~rs232_rx);
reg [3:0] num;
//接收时钟使能信号的控制
always @ (posedge clk_in or negedge rst_n_in) begin
if(!rst_n_in)
bps_en <= 1'b0;
else if(neg_rs232_rx && (!bps_en)) //当空闲状态(bps_en为低电平)时检测到UART接收信号下降沿,进入工作状态(bps_en为高电平),控制时钟模块产生接收时钟
bps_en <= 1'b1;
else if(num==4'd9) //当完成一次UART接收操作后,退出工作状态,恢复空闲状态
bps_en <= 1'b0;
end
reg [7:0] rx_data_r;
//当处于工作状态中时,按照接收时钟的节拍获取数据
always @ (posedge clk_in or negedge rst_n_in) begin
if(!rst_n_in) begin
num <= 4'd0;
rx_data <= 8'd0;
rx_data_r <= 8'd0;
end else if(bps_en) begin
if(bps_clk) begin
num <= num+1'b1;
if(num<=4'd8)
rx_data_r[num-1]<=rs232_rx; //先接受低位再接收高位,8位有效数据
end else if(num == 4'd9) begin //完成一次UART接收操作后,将获取的数据输出
num <= 4'd0;
rx_data <= rx_data_r;
end
end
end
endmodule
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ****************************
// 发送数据模块
// ****************************
module Uart_Tx
(
input clk_in, //系统时钟
input rst_n_in, //系统复位,低有效
output reg bps_en, //发送时钟使能
input bps_clk, //发送时钟输入
input rx_bps_en, //因需要自收自发,使用接收时钟使能判定:接收到新的数据,需要发送
input [7:0] tx_data, //需要发出的数据
output reg rs232_tx //UART发送输出
);
reg rx_bps_en_r;
//延时锁存接收时钟使能信号
always @ (posedge clk_in or negedge rst_n_in) begin
if(!rst_n_in) rx_bps_en_r <= 1'b0;
else rx_bps_en_r <= rx_bps_en;
end
//检测接收时钟使能信号的下降沿,因为下降沿代表接收数据的完成,以此作为发送信号的激励
wire neg_rx_bps_en = rx_bps_en_r & (~rx_bps_en);
reg [3:0] num;
reg [9:0] tx_data_r;
//根据接收数据的完成,驱动发送数据操作
always @ (posedge clk_in or negedge rst_n_in) begin
if(!rst_n_in) begin
bps_en <= 1'b0;
tx_data_r <= 8'd0;
end else if(neg_rx_bps_en)begin
bps_en <= 1'b1; //当检测到接收时钟使能信号的下降沿,表明接收完成,需要发送数据,使能发送时钟使能信号
tx_data_r <= {1'b1,tx_data,1'b0};
end else if(num==4'd10) begin
bps_en <= 1'b0; //一次UART发送需要10个时钟信号,然后结束
end
end
//当处于工作状态中时,按照发送时钟的节拍发送数据
always @ (posedge clk_in or negedge rst_n_in) begin
if(!rst_n_in) begin
num <= 1'b0;
rs232_tx <= 1'b1;
end else if(bps_en) begin
if(bps_clk) begin
num <= num + 1'b1;
rs232_tx <= tx_data_r[num];
end else if(num>=4'd10)
num <= 4'd0;
end
end
endmodule
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//串口顶层模块
module Uart_Bus #
(
parameter BPS_PARA = 1250 //当使用12MHz时钟时波特率参数选择1250对应9600的波特率
)
(
input clk_in, //系统时钟
input rst_n_in, //系统复位,低有效
input rs232_rx, //FPGA中UART接收端,分配给UART模块中的发送端TXD
output rs232_tx, //FPGA中UART发送端,分配给UART模块中的接收端RXD
output [7:0] rx_data, //读到的数据
input [7:0] tx_data //发送的数据
);
/////////////////////////////////UART接收功能模块例化////////////////////////////////////
wire bps_en_rx,bps_clk_rx;
//wire [7:0] rx_data;
//UART接收波特率时钟控制模块 例化
Baud #
(
.BPS_PARA (BPS_PARA )
)
Baud_rx
(
.clk_in (clk_in ), //系统时钟
.rst_n_in (rst_n_in ), //系统复位,低有效
.bps_en (bps_en_rx ), //接收时钟使能
.bps_clk (bps_clk_rx ) //接收时钟输出
);
//UART接收数据模块 例化
Uart_Rx Uart_Rx_uut
(
.clk_in (clk_in ), //系统时钟
.rst_n_in (rst_n_in ), //系统复位,低有效
.bps_en (bps_en_rx ), //接收时钟使能
.bps_clk (bps_clk_rx ), //接收时钟输入
.rs232_rx (rs232_rx ), //UART接收输入
.rx_data (rx_data ) //接收到的数据
);
/////////////////////////////////UART发送功能模块例化////////////////////////////////////
wire bps_en_tx,bps_clk_tx;
//UART发送波特率时钟控制模块 例化
Baud #
(
.BPS_PARA (BPS_PARA )
)
Baud_tx
(
.clk_in (clk_in ), //系统时钟
.rst_n_in (rst_n_in ), //系统复位,低有效
.bps_en (bps_en_tx ), //发送时钟使能
.bps_clk (bps_clk_tx ) //发送时钟输出
);
//UART发送数据模块 例化
Uart_Tx Uart_Tx_uut
(
.clk_in (clk_in ), //系统时钟
.rst_n_in (rst_n_in ), //系统复位,低有效
.bps_en (bps_en_tx ), //发送时钟使能
.bps_clk (bps_clk_tx ), //发送时钟输入
.rx_bps_en (bps_en_rx ), //因需要自收自发,使用接收时钟使能判定:接收到新的数据,需要发送
.tx_data (tx_data ), //需要发出的数据
.rs232_tx (rs232_tx ) //UART发送输出
);
endmodule
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )