目录
串口接收(RX)
`timescale 1ns / 1ps
module UART_RX(
input clk ,
input rst_n,
input rx ,
output rx_done ,
output [7:0] rx_data
);
//parameter hz=50_00;
//parameter bps = 96;
parameter hz=50_000_000;
parameter bps = 9600;
parameter delay = hz/bps;
wire rd_en;
reg en;
reg [31:0] cnt;
reg [5:0] cnt_bit;
reg [7:0] data_reg;
reg rx1;
reg rx2;
always @(posedge clk)
if(!rst_n)begin
rx1<=0;
rx2<=1;
end
else begin
rx1<=rx;
rx2<=rx1;
end
assign rd_en = (~rx1&&rx2) ?1:0; //当rx1为0 rx2为1时 rd_en == 1
//en用于判断是否在接收数据 en == 1时候为接收
always @(posedge clk)
if(!rst_n)
en<=0;
else if(rd_en)
en<=1;
else if(cnt_bit == 9 && cnt == delay/2-1)
en<=0;
else
en<=en;
always @(posedge clk)
if(!rst_n)begin
cnt<=0;
cnt_bit<=0;
end
else if(en)begin
if(cnt == delay -1 )begin
cnt <= 0;
cnt_bit <= cnt_bit +1;
end
else begin
cnt <=cnt +1;
cnt_bit <=cnt_bit;
end
end
else begin
cnt<=0;
cnt_bit <=0;
end
always @(posedge clk)
if(!rst_n)begin
data_reg<=0;
end
else if(cnt_bit >0 && cnt_bit <9 && cnt == delay/2-1)
data_reg [cnt_bit -1] = rx;
else begin
data_reg<=data_reg;
end
//更新数据
assign rx_data = (cnt_bit ==9) ?data_reg:rx_data;
//发送结束信号
assign rx_done = (cnt_bit ==9 && cnt == delay /2-1)?1:0;
endmodule
-
时钟和复位模块:
timescale 1ns / 1ps
:设置时间尺度为1纳秒/1皮秒。clk
:输入时钟信号。rst_n
:复位信号,低电平有效。rx
:输入的UART串行数据位。rx_done
:输出信号,表示接收到完整数据的标志。rx_data
:输出信号,表示接收到的数据。
-
参数模块:
hz
:时钟频率,默认为50 MHz。bps
:UART通信波特率,默认为9600。
-
时钟周期计算模块:
delay
:计算接收一个完整的串行数据位所需的时钟周期数,即时钟频率除以波特率。
-
数据接收模块:
rd_en
:判断是否开始接收数据的信号。当上一个时钟周期的接收数据为0,当前时钟周期的接收数据为1时,表示开始接收数据。en
:接收使能信号,当rd_en为1时,表示开始接收数据。cnt
:计数时钟周期的寄存器。cnt_bit
:计数接收到的数据位数的寄存器。data_reg
:存储接收到的数据的寄存器。rx1
和rx2
:存储上一个和当前时钟周期的接收数据。
-
接收状态控制模块:
- 通过时钟边沿触发的always块来控制接收状态的转换。
- 根据复位信号和rd_en信号的值,控制en信号的转换,判断是否开始接收数据或接收数据结束。
- 根据复位信号、en信号和计数寄存器的值,控制cnt和cnt_bit寄存器的转换,实现计数功能。
-
数据存储模块:
- 通过时钟边沿触发的always块来存储接收到的数据。
- 根据复位信号、计数寄存器和接收数据的值,将接收到的数据存储到data_reg寄存器的相应位置。
-
输出模块:
- 通过assign语句更新rx_data信号,根据计数寄存器的值判断是否接收到完整的一个字节的数据,并将data_reg的值赋给rx_data。
- 通过assign语句更新rx_done信号,根据计数寄存器和计算的delay值判断是否接收完成,当接收位数为9且计数值为delay/2-1时,将rx_done置为1,表示接收完成。
接收UART串行数据,并将接收到的数据存储在rx_data中,当接收完成时,将rx_done置为1。计数器和状态机的设计用于控制接收数据的时机和状态转换。
串口发送(TX)
`timescale 1ns / 1ps
module UART_TX(
input clk ,
input rst_n ,
input rx_done ,
input [7:0] rx_data , //并行接收数据
output reg tx , //数据输出
output tx_done //模块结束信号
);
//parameter HZ = 50_00; //1s时间
//parameter bps = 96; //波特率
parameter HZ = 50_000_000; //1s时间
parameter bps = 9600; //波特率
parameter delay = HZ/bps; //1bit 需要的时钟周期数
reg [31:0] cnt;
reg [5:0] cnt_bit;
reg en;
always @(posedge clk)
if(!rst_n)
en <= 0;
else if (rx_done)
en<=1;
else if(cnt == delay /2 -1 && cnt_bit == 9)
en<=0;
else
en<=en;
always @(posedge clk)
if(!rst_n) begin
cnt <= 0;
cnt_bit <= 0;
end
else if (en)begin
if(cnt == delay -1)begin
cnt <= 0;
cnt_bit <= cnt_bit +1;
end
else begin
cnt <= cnt +1;
cnt_bit <= cnt_bit;
end
end
else begin
cnt <= 0;
cnt_bit <= 0;
end
always @(posedge clk)
if(!rst_n) begin
tx <= 1;
end
else if (cnt_bit ==0 && en == 1 )begin
tx <=0;
end
else if (cnt_bit > 0 && cnt_bit <9)begin
tx <=rx_data[cnt_bit -1];
end
else begin
tx <= 1;
end
assign tx_done = (cnt_bit == 9 && cnt_bit == delay/2-1) ?1:0;
endmodule
-
时钟和复位模块:
timescale 1ns / 1ps
:设置时间尺度为1纳秒/1皮秒。clk
:输入时钟信号。rst_n
:复位信号,低电平有效。rx_done
:输入信号,表示接收完成的标志。rx_data
:输入信号,表示要发送的数据。
-
参数模块:
HZ
:时钟频率,默认为50 MHz。bps
:UART通信波特率,默认为9600。
-
时钟周期计算模块:
delay
:计算发送一个完整的串行数据位所需的时钟周期数,即时钟频率除以波特率。
-
发送状态控制模块:
en
:发送使能信号,根据接收完成信号rx_done的值判断是否开始发送数据。cnt
:计数时钟周期的寄存器。cnt_bit
:计数发送的数据位数的寄存器。
-
数据发送模块:
- 通过时钟边沿触发的always块来控制数据发送状态和时序。
- 根据复位信号和接收完成信号的值,控制en信号的转换,
串口通信模块
`timescale 1ns / 1ps
module uart_1(
input clk ,
input rst_n ,
input rx ,
output tx //数据输出
);
wire rx_done;
wire [7:0] rx_data;
wire tx_done;
UART_RX r(
. clk ( clk ),
. rst_n ( rst_n ) ,
. rx ( rx ),
. rx_done ( rx_done ),
. rx_data ( rx_data )
);
UART_TX t(
. clk ( clk ) ,
. rst_n ( rst_n ) ,
. rx_done ( rx_done ) ,
. rx_data ( rx_data ) , //并行接收数据
. tx ( tx ) , //数据输出
. tx_done ( tx_done ) //模块结束信号
);
endmodule
将串口接收和发送的信息进行互联,并传输接收到的信息。