//----------------------------------------------------//----------------------------------------------------
`timescale1ns/1ps
modulemy_uart_top(
clk,rst_n,
rs232_rx,rs232_tx
);
inputclk; //50MHz主时钟
inputrst_n; //低电平复位信号
inputrs232_rx; //RS232接收数据信号
outputrs232_tx; // RS232发送数据信号
wirebps_start1,bps_start2; //接收到数据后,波特率时钟启动信号置位
wirebps_clk1,bps_clk2; //bps_clk_r高电平为接收数据位的中间采样点,同时也作为发送数据的数据改变点
wire[7:0]rx_data; //接收数据寄存器,保存直至下一个数据来到
wirerx_int; //接收数据中断信号,接收到数据期间始终为高电平
//----------------------------------------------------
//下面的四个模块中,speed_rx和speed_tx是两个完全独立的硬件模块,可称之为逻辑复制
//(不是资源共享,和软件中的同一个子程序调用不能混为一谈)
speed_select speed_rx(
.clk(clk), //波特率选择模块
.rst_n(rst_n),
.bps_start(bps_start1),
.bps_clk(bps_clk1)
);
my_uart_rx my_uart_rx(
.clk(clk), //接收数据模块
.rst_n(rst_n),
.rs232_rx(rs232_rx),
.rx_data(rx_data),
.rx_int(rx_int),
.bps_clk(bps_clk1),
.bps_start(bps_start1)
);
///////////////////////////////////////////
speed_select speed_tx(
.clk(clk), //波特率选择模块
.rst_n(rst_n),
.bps_start(bps_start2),
.bps_clk(bps_clk2)
);
my_uart_tx my_uart_tx(
.clk(clk), //发送数据模块
.rst_n(rst_n),
.rx_data(rx_data),
.rx_int(rx_int),
.rs232_tx(rs232_tx),
.bps_clk(bps_clk2),
.bps_start(bps_start2)
);
endmodule
//----------------------------------------------------//----------------------------------------------------
`timescale1ns/1ps
`define BPS 5207
`define BPS_2 2603
modulespeed_select(
clk,rst_n,bps_start,
bps_clk
);
input clk;
input rst_n;
input bps_start;
output bps_clk;//高电平时为接收或者发送数据位的中间采样点
reg[12:0] cnt;
reg bps_clk_r;
always@(posedgeclkornegedgerst_n)
if(!rst_n) cnt<=13'd0;
elseif(cnt==`BPS||!bps_start)
cnt<=13'd0;
else cnt<=cnt+1'b1;
always@(posedgeclkornegedgerst_n)
if(!rst_n) bps_clk_r<=1'b0;
elseif(cnt==`BPS_2)
bps_clk_r<=1'b1;
elsebps_clk_r<=1'b0;
assign bps_clk =bps_clk_r;
endmodule
/*
parameter bps9600 =5207, //波特率为9600bps
bps19200 =2603, //波特率为19200bps
bps38400 =1301, //波特率为38400bps
bps57600 =867, //波特率为57600bps
bps115200 =433; //波特率为115200bps
parameter bps9600_2 =2603,
bps19200_2 =1301,
bps38400_2 =650,
bps57600_2 =433,
bps115200_2=216;
*/
//----------------------------------------------------//----------------------------------------------------
`timescale1ns/1ps
modulemy_uart_rx(
clk,rst_n,
rs232_rx,bps_clk,
bps_start,rx_data,rx_int
);
input clk;
input rst_n;
input rs232_rx;//RS232接收数据信号
input bps_clk;//bps_clk的高电平为接收或者发送数据位的中间采样点
output bps_start;//clk_bps的高电平为接收或者发送数据位的中间采样点
output rx_int;//接收数据中断信号,接收到数据期间始终为高电平
output[7:0]rx_data;//接收数据寄存器,保存直至下一个数据来到
wireneg_rs232_rx;//表示数据线接收到下降沿
reg rs232_rx0,rs232_rx1,rs232_rx2,rs232_rx3;//接收数据寄存器,滤波用
always@(posedgeclkornegedgerst_n) begin
if(!rst_n) begin
rs232_rx0<=1'b0;
rs232_rx1<=1'b0;
rs232_rx2<=1'b0;
rs232_rx3<=1'b0;
end
else begin
rs232_rx0<=rs232_rx;
rs232_rx1<=rs232_rx0;
rs232_rx2<=rs232_rx1;
rs232_rx3<=rs232_rx2;
end
end
//下面的下降沿检测可以滤掉<20ns-40ns的毛刺(包括高脉冲和低脉冲毛刺),
//这里就是用资源换稳定(前提是我们对时间要求不是那么苛刻,因为输入信号打了好几拍)
//(当然我们的有效低脉冲信号肯定是远远大于40ns的)
assign neg_rs232_rx =rs232_rx3&rs232_rx2&~rs232_rx1&~rs232_rx0;
reg bps_start_r;
reg[3:0]num;//移位次数
regrx_int;////接收数据中断信号,接收到数据期间始终为高电平
always@(posedgeclkornegedgerst_n)
if(!rst_n) begin
bps_start_r<=1'bz;
rx_int<=1'b0;
end
elseif(neg_rs232_rx) begin//接收到串口接收线rs232_rx的下降沿信号
bps_start_r<=1'b1;//启动串口准备数据接收
rx_int<=1'b1; //接收数据中断使能信号
end
elseif(num==4'd12) begin//接收完有用数据信息
bps_start_r<=1'b0;//数据接收完,释放波特率启动信号
rx_int<=1'b0;//接收数据中断信号关闭
end
assignbps_start=bps_start_r;
//----------------------------------------------------------------
reg[7:0]rx_data_r; //串口接收数据寄存器,保存直至下一个数据来到
//----------------------------------------------------------------
reg[7:0]rx_temp_data; //当前接收数据寄存器
always@(posedgeclkornegedgerst_n)
if(!rst_n) begin
rx_temp_data<=8'd0;
num<=4'd0;
rx_data_r<=8'd0;
end
elseif(rx_int) begin
if(bps_clk) begin
num<=num+1'b1;
case(num)
4'd1:rx_temp_data[0]<=rs232_rx;//锁存第0bit
4'd2:rx_temp_data[1]<=rs232_rx;//锁存第1bit
4'd3:rx_temp_data[2]<=rs232_rx;//锁存第2bit
4'd4:rx_temp_data[3]<=rs232_rx;//锁存第3bit
4'd5:rx_temp_data[4]<=rs232_rx;//锁存第4bit
4'd6:rx_temp_data[5]<=rs232_rx;//锁存第5bit
4'd7:rx_temp_data[6]<=rs232_rx;//锁存第6bit
4'd8:rx_temp_data[7]<=rs232_rx;//锁存第7bit
default:;
endcase
end
elseif(num==4'd12) begin
//我们的标准接收模式下只有1+8+1(2)=11bit的有效数据
num<=4'd0; //接收到STOP位后结束,num清零
rx_data_r<=rx_temp_data; //把数据锁存到数据寄存器rx_data中
end
end
assign rx_data=rx_data_r;
endmodule
//----------------------------------------------------//---------------------------------------------------