------------以下串口发送部分
module uart_tx (clk,rst,tx_data,tx_data_valid,tx_data_ack,txd);
-----------敏感变量包括时钟/复位,发送数据,发送数据有效,发送数据响应,发送数据线
output txd; ----------数据发送线
input clk, rst; ---------系统时钟,复位
input [7:0] tx_data; ------数据发送
input tx_data_valid; -----数据发送使能
output tx_data_ack; ------数据发送响应
parameter BAUD_DIVISOR = 868; -----波特分频比
reg [15:0] sample_cntr; ----发送抽样计数器
reg [10:0] tx_shift; ------发送数据移位积存器“起始位+8个数据位+停止位”
reg sample_now; ------发送时钟
reg tx_data_ack; ------发送数据响应积存器
assign txd = tx_shift[0]; -----开始发送数据
always @(posedge clk) begin -----检测时钟上升沿
if (rst) begin ------高复位
sample_cntr <= 0; ------寄存器清0
sample_now <= 1'b0; ------ 清0
end
else if (sample_cntr == (BAUD_DIVISOR-1)) begin
sample_cntr <= 0;
sample_now <= 1'b1;
end
else begin
sample_now <= 1'b0;
sample_cntr <= sample_cntr + 1'b1;
end
end
reg ready;
always @(posedge clk) begin -----检测上升沿
if (rst) begin
tx_shift <= {11'b00000000001}; ----发送移位初试化
ready <= 1'b1; ----发送准备
end
else begin
if (!ready & sample_now) begin ----发送时钟上升沿且发送未完成
tx_shift <= {1'b0,tx_shift[10:1]};
tx_data_ack <= 1'b0;
ready <= ~|tx_shift[10:1];----- ready 置高, 确保tx_shift 初始化
end
else if (ready & tx_data_valid) begin
tx_shift[10:1] <= {1'b1,tx_data,1'b0};
tx_data_ack <= 1'b1; -----开始发送数据
ready <= 1'b0; -----发送数据标志
end
else begin
tx_data_ack <= 1'b0;
ready <= ~|tx_shift[10:1]; ---发送数据,ready 置高!!!!!!!!!!!!
end
end
end
endmodule
////////////////////////////////////////////////////////////////////
module uart_rx (clk,rst,rx_data,rx_data_fresh,rxd); -----敏感信号时钟,复位,接收数据,接收数据更新,接收数据线
input clk, rst, rxd;
output [7:0] rx_data; ----接收数据
output rx_data_fresh; -----接收数据更新
parameter BAUD_DIVISOR = 868; ----波特率分频比
reg [15:0] sample_cntr; ----分频计数器
reg [7:0] rx_shift; ----接收移位寄存器
reg sample_now; -----接收分频时钟信号
reg [7:0] rx_data; -----接收数据
reg rx_data_fresh; -----接收数据更新
reg last_rxd; -----接收缓冲
always @(posedge clk) begin
last_rxd <= rxd;
end
wire slew = rxd ^ last_rxd;
always @(posedge clk) begin
if (rst) begin
sample_cntr <= 0;
sample_now <= 1'b0;
end
else if (sample_cntr == (BAUD_DIVISOR-1) || slew) begin
sample_cntr <= 0;
end
else if (sample_cntr == (BAUD_DIVISOR/2)) begin
sample_now <= 1'b1;
sample_cntr <= sample_cntr + 1'b1;
end
else begin
sample_now <= 1'b0; -----接收时钟占空比1
sample_cntr <= sample_cntr + 1'b1;
end
end
reg [1:0] state;
reg [3:0] held_bits;
parameter WAITING = 2'b00, READING = 2'b01, STOP = 2'b10, RECOVER = 2'b11;
always @(posedge clk) begin
if (rst) begin
state <= WAITING;
held_bits <= 0;
rx_shift <= 0;
rx_data_fresh <= 1'b0;
rx_data <= 0;
end
else begin
rx_data_fresh <= 1'b0;
case (state)
WAITING : begin
// wait for a start bit (0)
if (!slew & sample_now && !last_rxd) begin -----下降沿,接收时钟,起始位
state <= READING;
held_bits <= 0;
end
end
READING : begin
// gather data bits
if (sample_now) begin
rx_shift <= {last_rxd,rx_shift[7:1]};
held_bits <= held_bits + 1'b1;
if (held_bits == 4'h7) state <= STOP;
end
end
STOP : begin
// verify stop bit (1)
if (sample_now) begin
if (last_rxd) begin
rx_data <= rx_shift;
rx_data_fresh <= 1'b1;
state <= WAITING;
end
else begin
// there was a framing error -
// discard the byte and work on resync
state <= RECOVER;
end
end
end
RECOVER : begin
// wait for an idle (1) then resume
if (sample_now) begin
if (last_rxd) state <= WAITING;
end
end
endcase
end
end
endmodule
////////////////////////////////////////////////////////////////////
module uart (clk,rst,
tx_data,tx_data_valid,tx_data_ack,txd,
rx_data,rx_data_fresh,rxd);
parameter CLK_HZ = 50_000_000;
parameter BAUD = 115200;
parameter BAUD_DIVISOR = CLK_HZ / BAUD;
initial begin
if (BAUD_DIVISOR > 16'hffff) begin
// This rate is too slow for the TX and RX sample
// counter resolution
$display ("Error - Increase the size of the sample counters");
$stop();
end
end
output txd;
input clk, rst, rxd;
input [7:0] tx_data;
input tx_data_valid;
output tx_data_ack;
output [7:0] rx_data;
output rx_data_fresh;
uart_tx utx (
.clk(clk),.rst(rst),
.tx_data(tx_data),
.tx_data_valid(tx_data_valid),
.tx_data_ack(tx_data_ack),
.txd(txd));
defparam utx .BAUD_DIVISOR = BAUD_DIVISOR;
uart_rx urx (
.clk(clk),.rst(rst),
.rx_data(rx_data),
.rx_data_fresh(rx_data_fresh),
.rxd(rxd));
defparam urx .BAUD_DIVISOR = BAUD_DIVISOR;
endmodule
不错,但是不知道可靠性整么样。串口数据接收最大的问题就是可靠性问题。因为串口帧协议简单,不能保证数据可靠传递。经常出现各种各样的错误!让人防不胜防!