------------以下串口发送部分
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
|