1.
module speed_setting(
input clk,
input rst_n,
input bps_start,
output clk_bps
);
`define BPS_9600
`define CLK_PERIOD 40 // 时钟周期为40ns(25MHZ)
`define BPS_SET 96
`define BPS_PA (10_000_000/`CLK_PERIOD/`BPS_SET) //10_000_000/`CLK_PERIORD/96; //波特率为9600时的分频计数值
// 1s=1000_000_000ns 上下同时约去个100就变成250000/96
`define BPS_PA_2 (`BPS_PA/2) //BPS分频计数的1/2
reg [12:0] cnt;
reg clk_bps_r;
always@(posedge clk or negedge rst_n)begin
if(!rst_n) cnt <= 13'd0;
else if(cnt == `BPS_PA || !bps_start) cnt <= 13'd0;
else cnt <= cnt + 1'b1;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n) clk_bps_r <= 1'b0;
else if(cnt == `BPS_PA_2) clk_bps_r <= 1'b1;
else clk_bps_r <= 1'b0;
end
assign clk_bps = clk_bps_r;
endmodule
2.
//拿到一个多位数据 即并行数据 通过uart_tx端口串行输出
module my_uart_tx(
input clk,
input rst_n,
input clk_bps,//等同于clk_div
input rx_int,//对方的接收反馈,接收过程中正常高电平,结束或者异常低电平
output reg bps_start,//波特率的复位
input [7:0] rx_data,//拿到的并行数据
output uart_tx//串行输出端口
);
//----------------------------------
//对rx_int的滤波
reg rx_int0,rx_int1,rx_int2;
always@(posedge clk or negedge rst_n)begin
if(!rst_n) begin
rx_int0 <= 1'b0;
rx_int1 <= 1'b0;
rx_int2 <= 1'b0;
end
else begin
rx_int0 <= rx_int;
rx_int1 <= rx_int0;
rx_int2 <= rx_int1;
end
end
wire nege_edge = rx_int2 & ~rx_int1; //当对方把数据发送完,捕捉其标志位的下降沿
//----------------------------------------------------
//设置相关使能,将接收到的并行数据存储用于下一步 串行发出
reg tx_en;
reg [7:0] tx_data;
reg [3:0] num;
always@(posedge clk or negedge rst_n)begin
if(!rst_n) begin
tx_en <= 1'b0;
tx_data <= 8'd0;
bps_start <= 1'b0;
end
else if(nege_edge)begin
tx_en <= 1'b1;
tx_data <= rx_data;
bps_start <= 1'b1;
end
else if(num == 4'd10)begin
tx_en <= 1'b0;
bps_start <= 1'b0;
end
end
//-------------------------------------------------------
//把并行的数据拆开一拍发一位
reg uart_tx_r;
always@(posedge clk or negedge rst_n)begin
if(!rst_n) begin
uart_tx_r <= 1'b0;
num <= 1'b0;
end
else if(tx_en)begin
if(clk_bps)begin
num <= num + 1'b1;
case(num)
4'd0: uart_tx_r <= 1'b0; //发送起始位
4'd1: uart_tx_r <= tx_data[0]; //发送bit0
4'd2: uart_tx_r <= tx_data[1]; //发送bit1
4'd3: uart_tx_r <= tx_data[2]; //发送bit2
4'd4: uart_tx_r <= tx_data[3]; //发送bit3
4'd5: uart_tx_r <= tx_data[4]; //发送bit4
4'd6: uart_tx_r <= tx_data[5]; //发送bit5
4'd7: uart_tx_r <= tx_data[6]; //发送bit6
4'd8: uart_tx_r <= tx_data[7]; //发送bit7
4'd9: uart_tx_r <= 1'b1; //发送结束位
default: uart_tx_r <= 1'b1;
endcase
end
end
else if(num == 4'd10)begin
num <= 4'd0;
end
end
assign uart_tx = uart_tx_r;
endmodule
3.
//接收到一个串行端口传来的数据,存下来 存够约定的位数后一次输出 即串行变并行
module my_uart_rx(
input clk,
input rst_n,
input uart_rx,
input clk_bps,
output reg bps_start, //波特率启动和复位高 电平有效
output [7:0] rx_data,
output reg rx_int // 标志位 用来表示正在接收数据 高电平 接收中断或结束为低电平
);
//----------------------------------------------------------------------
//本部分将 uart_rx 接收进来的信号进行滤波
reg uart_rx0,uart_rx1,uart_rx2,uart_rx3; //用来滤波
always@(posedge clk or negedge rst_n)begin
if(!rst_n) begin
uart_rx0 <= 1'b0;
uart_rx1 <= 1'b0;
uart_rx2 <= 1'b0;
uart_rx3 <= 1'b0;
end
else begin
uart_rx0 <= uart_rx;
uart_rx1 <= uart_rx0;
uart_rx2 <= uart_rx1;
uart_rx3 <= uart_rx2;
end
end
wire nege_edge = uart_rx3 & uart_rx2 & ~uart_rx1 & ~uart_rx0;
//----------------------------------------------------------------
//bps_start 和 rx_int的控制
reg[3:0] num;
always@(posedge clk or negedge rst_n)begin
if(!rst_n) begin
bps_start <= 1'b0;
rx_int <= 1'b0;
end
else if(nege_edge)begin
bps_start <= 1'b1;
rx_int <= 1'b1;
end
else if(num == 4'd9)begin
bps_start <= 1'b0;
rx_int <= 1'b0;
end
end
//--------------------------------------------------------
//把串行的uart_rx进来的数据变成并行
//其实就是把uart_rx一拍一拍进来的存进寄存器中
//然后以输出8位
reg[7:0] rx_temp_data,rx_data_r;
always@(posedge clk or negedge rst_n)begin
if(!rst_n) begin
rx_temp_data <= 8'd0;
rx_data_r <= 8'd0;
num <= 4'd0;
end
else if(rx_int)begin
if(clk_bps)begin
num <= num + 1'b1;
case(num)
4'd1: rx_temp_data[0] <= uart_rx; //锁存第0bit
4'd2: rx_temp_data[1] <= uart_rx; //锁存第1bit
4'd3: rx_temp_data[2] <= uart_rx; //锁存第2bit
4'd4: rx_temp_data[3] <= uart_rx; //锁存第3bit
4'd5: rx_temp_data[4] <= uart_rx; //锁存第4bit
4'd6: rx_temp_data[5] <= uart_rx; //锁存第5bit
4'd7: rx_temp_data[6] <= uart_rx; //锁存第6bit
4'd8: rx_temp_data[7] <= uart_rx; //锁存第7bit
default: ;
endcase
end
end
else if(num == 4'd9) begin
rx_data_r <= rx_temp_data;
num <= 4'd0;
end
end
assign rx_data = rx_data_r;
endmodule
4.
module cy4ex12_uart(
input clk_25m, //外部输入25MHz时钟信号
input ext_rst_n, //外部输入复位信号,低电平有效
input uart_rx, // UART接收数据信号
output uart_tx // UART发送数据信号
);
//-------------------------------------
//下面的四个模块中,speed_rx和speed_tx是两个完全独立的硬件模块,可称之为逻辑复制
//(不是资源共享)
wire bps_start1,bps_start2; //接收到数据后,波特率时钟启动信号置位
wire clk_bps1,clk_bps2; // clk_bps_r高电平为接收数据位的中间采样点,同时也作为发送数据的数据改变点
wire[7:0] rx_data; //接收数据寄存器,保存直至下一个数据来到
wire rx_int; //接收数据中断信号,接收到数据期间始终为高电平
//UART接收信号波特率设置
speed_setting speed_rx(
.clk(clk_25m), //波特率选择模块
.rst_n(ext_rst_n),
.bps_start(bps_start1),
.clk_bps(clk_bps1)
);
//UART接收数据处理
my_uart_rx my_uart_rx(
.clk(clk_25m), //接收数据模块
.rst_n(ext_rst_n),
.uart_rx(uart_rx),
.clk_bps(clk_bps1),
.bps_start(bps_start1),
.rx_data(rx_data),
.rx_int(rx_int)
);
//-------------------------------------
//UART发送信号波特率设置
speed_setting speed_tx(
.clk(clk_25m), //波特率选择模块
.rst_n(ext_rst_n),
.bps_start(bps_start2),
.clk_bps(clk_bps2)
);
//UART发送数据处理
my_uart_tx my_uart_tx(
.clk(clk_25m), //发送数据模块
.rst_n(ext_rst_n),
.clk_bps(clk_bps2),
.rx_int(rx_int),
.bps_start(bps_start2),
.rx_data(rx_data),
.uart_tx(uart_tx)
);
endmodule