串口接收和发送两个独立模块的代码,接收到的信号连接到发送的模块信号,实现回环。
顶层:
module uart_eco(
input wire rst,
(*mark_debug="true"*)input wire clk,
(*mark_debug="true"*)input wire rxd,
(*mark_debug="true"*)output wire txd
);
(*mark_debug="true"*)wire [7:0] uart_data_wire_tx;
(*mark_debug="true"*)wire rx_flag;
usart_rx usart_rx_inst(
.clock(clk),
.rxd(rxd),
.rst_n(rst),
.rx_data_byte(uart_data_wire_tx),
.rx_valid_wire(rx_flag)
);
usart_tx usart_tx_inst(
.clock(clk),
.txd(txd),
.rst_n(rst),
.tx_data_byte(uart_data_wire_tx),
.tx_triger_flag(rx_flag)
);
endmodule
发送部分代码
发送代码比接收简单。就是需要发送的数据,当发送触发为1,则触发发送。波特率计数器开始计数,先产生一个bit起始拉低信号,然后依次将8bit数据移位发送出去,最后回到空闲状态。
module usart_tx(
input wire clock,
output wire txd, //TXD发送数据线
input wire rst_n,
input wire [7:0] tx_data_byte, //要发的数据
input wire tx_triger_flag //发送触发,至少一个周期
);
parameter CLOCK_FRQ = 50_000_000;
parameter BADRATE = 115_200;
parameter UART_COUTER_MAX = CLOCK_FRQ / BADRATE;
parameter UART_BIT = 8;
reg [7:0] tx_bit_cnt_reg;
reg [19:0] tx_counter;
reg [19:0] baud_counter;
reg txd_reg;
reg tx_start_flag;
assign txd = txd_reg;
//要发送的BIT选择
always @(posedge clock) begin
if(tx_start_flag == 1) begin
case (tx_bit_cnt_reg)
0: txd_reg <= 0;
1: txd_reg <= tx_data_byte[0];
2: txd_reg <= tx_data_byte[1];
3: txd_reg <= tx_data_byte[2];
4: txd_reg <= tx_data_byte[3];
5: txd_reg <= tx_data_byte[4];
6: txd_reg <= tx_data_byte[5];
7: txd_reg <= tx_data_byte[6];
8: txd_reg <= tx_data_byte[7];
9: txd_reg <= 1;
default: txd_reg <= 1;
endcase
end else
txd_reg <= 1;
end
//发送开始和结束逻辑
always @(posedge tx_triger_flag or posedge clock) begin
if(tx_triger_flag == 1)
tx_start_flag <= 1;
else begin
if(tx_bit_cnt_reg == UART_BIT + 1)
tx_start_flag <= 0;
end
end
//发送波特率计数逻辑
always @(posedge clock or negedge rst_n) begin
if(rst_n == 0) begin
tx_counter <= 0;
end
else begin
if(tx_start_flag == 1) begin
if(tx_counter < UART_COUTER_MAX)
tx_counter <= tx_counter + 1;
else begin
tx_counter <= 0;
end
end
end
end
//发送bit计数
always @(posedge clock or negedge rst_n) begin
if(rst_n == 0) begin
tx_bit_cnt_reg <= 0;
end
else begin
if(tx_counter == UART_COUTER_MAX) begin
if(tx_bit_cnt_reg < UART_BIT + 1)
tx_bit_cnt_reg <= tx_bit_cnt_reg + 1;
end
else begin
if(tx_bit_cnt_reg == UART_BIT + 1)
tx_bit_cnt_reg <= 0;
end
end
end
endmodule
接收模块代码
首先,串口平时空闲,RX信号一直为高。当有数据来临,信号拉低,持续一个波特率的周期为低,这个比特是起始位。我们的一个字节接收rx_start_flag标志在这个时候就置为1表示正在接收这个字节了。然后,这个标志位1的时候,我们BIT接收计数器就开始计数,从0计数到一个波特率周期最大值,然后清零,再次计数。计数到最大值的一半,即为采样时刻,这个时候我们就把RX值读过来,放到一个8BIT移位接收寄存器。接收8bit数据需要有9次计数周期,为什么是9?因为有起始位也算一个比特。起始比特不会把数据读来放到接收移位寄存器,所以数据开始接收存储到移位寄存器是从第二位开始的。
/* 代码包含模块输入时钟,接收信号线,复位信号,以及接收到的字节数据,以及接收有效标志。
当接收完一个字节,接收字节数据就有效,并且,接受有效信
号会拉高至少一个时钟周期 */
module usart_rx(
input wire clock,
input wire rxd,
input wire rst_n,
output wire [7:0] rx_data_byte,
output wire rx_valid_wire
);
parameter CLOCK_FRQ = 50_000_000; //模块输入时钟 50M
parameter BADRATE = 115_200; //串口波特率 115200
parameter UART_COUTER_MAX = CLOCK_FRQ / BADRATE; //接收的比特计数器最大值
parameter UART_BIT = 8; //串口比特数,我们用8BIT
reg [7:0]rx_data_byte_reg;
reg rx_start_flag;
reg [19:0]rx_counter;
reg [19:0]baud_counter;
reg baud_rat_clk;
reg rxd_reg1;
reg rxd_reg2;
reg rxd_reg3;
wire rxd_negedge;
reg [7:0]rx_bit_cnt;
reg [7:0]rx_data;
reg rx_valid_flag_pre1;
reg rx_valid_flag_pre2;
wire rx_valid_flag;
assign rx_valid_wire = rx_valid_flag_pre2;
assign rx_valid_flag = (rx_bit_cnt==9) ? 1 : 0;
assign rxd_negedge = ~rxd_reg2 & rxd_reg3;
assign rx_data_byte = rx_data_byte_reg;
assign clk_badrate = baud_rat_clk;
always @(posedge clock) begin
rxd_reg1 <= rxd;
rxd_reg2 <= rxd_reg1;
rxd_reg3 <= rxd_reg2;
end
//波特率产生波特率时钟翻转逻辑
always @(posedge clock or negedge rst_n) begin
if(rst_n == 0) begin
baud_counter <= 0;
baud_rat_clk = 0;
end
else begin
rx_valid_flag_pre2 <= rx_valid_flag_pre1;
rx_valid_flag_pre1 = rx_valid_flag;
baud_counter <= baud_counter + 1;
if(baud_counter == UART_COUTER_MAX) begin
baud_counter <= 0;
baud_rat_clk <= ~baud_rat_clk;
end
end
end
//波特率生成的分频计数
always @(posedge clock or negedge rst_n) begin
if(rst_n == 0)
rx_counter <= 0;
else begin
if(rx_start_flag == 1) begin
rx_counter <= rx_counter + 1;
if(rx_counter == UART_COUTER_MAX)
rx_counter <= 0;
end
end
end
//接收过程的BIT计数
always @(posedge clock or negedge rst_n) begin
if(rst_n == 0)
rx_bit_cnt <= 0;
else begin
if(rx_counter == UART_COUTER_MAX) begin
rx_bit_cnt <= rx_bit_cnt + 1;
end
if(rx_bit_cnt == UART_BIT + 1)
rx_bit_cnt <= 0;
if(rx_bit_cnt == UART_BIT + 1)
rx_data_byte_reg <= rx_data;
end
end
//接收到一个比特,接收的字节寄存器每一个比特往前移位,采样点为BIT计数的一半点
always @(posedge clock or negedge rst_n) begin
if(rst_n == 0) begin
rx_data <= 0;
end
else begin
if(rx_counter == UART_COUTER_MAX / 2) begin
if((rx_bit_cnt >= 1) && (rx_bit_cnt < UART_BIT + 1)) begin
rx_data <= {rxd,rx_data[7:1]};
end
end
end
end
//接收起始条件模块,下降沿出发开始接收数据
always @(posedge clock or negedge rst_n) begin
if(rst_n == 0) begin
rx_start_flag <= 0;
end
else begin
if(rxd_negedge == 1)
rx_start_flag <= 1;
else if(rx_bit_cnt == UART_BIT + 1)
rx_start_flag <= 0;
end
end
endmodule