`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 18:57:31 06/18/2019
// Design Name:
// Module Name: uart_tx
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module uart_tx
#(
parameter CLK_FRE = 50,
parameter BAUD_RATE = 115200
)
(
input clk,
input rst_n,
input[7:0] tx_data,
input tx_data_valid,
output reg tx_data_ready,
output tx_pin
);
localparam CYCLE = CLK_FRE*1000000/BAUD_RATE;
localparam S_IDLE =1;
localparam S_START =2;
localparam S_SEND_BYTE =3;
localparam S_STOP =4;
reg[2:0] state;
reg[2:0] next_state;
reg[15:0] cycle_cnt;
reg[2:0] bit_cnt;
reg[7:0] tx_data_latch;
reg tx_reg;
//對發送引腳指派
assign tx_pin = tx_reg;
//切換發送資料狀态
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
state <= S_IDLE;
else
state <= next_state;
end
//發送資料狀态切換
always @(*)
begin
case(state)
S_IDLE:
if(tx_data_valid == 1'b1)
next_state <= S_START;
else
next_state <= S_IDLE;
S_START:
if(cycle_cnt == CYCLE - 1)
next_state <= S_SEND_BYTE;
else
next_state <= S_START;
S_SEND_BYTE:
if(cycle_cnt == CYCLE - 1 && bit_cnt == 3'd7)
next_state <= S_STOP;
else
next_state <= S_SEND_BYTE;
S_STOP:
if(cycle_cnt == CYCLE - 1)
next_state <= S_IDLE;
else
next_state <= S_STOP;
default:
next_state <= S_IDLE;
endcase
end
//發送資料計數
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
bit_cnt <= 3'd0;
end
else if(state == S_SEND_BYTE)
if(cycle_cnt == CYCLE-1)
bit_cnt <= bit_cnt + 3'd1;
else
bit_cnt <= bit_cnt;
else
bit_cnt <= 3'd0;
end
//擷取想要發送的8位資料
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
tx_data_latch <= 8'd0;
else if(state == S_START && tx_data_valid == 1'b1)
tx_data_latch <= tx_data;
end
//判斷發送資料是否完成
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
tx_data_ready <= 1'b0;
end
else if(state == S_IDLE )
if(tx_data_valid == 1'b1)
tx_data_ready <= 1'b0;
else
tx_data_ready <= 1'b1;
else if(state == S_STOP && cycle_cnt == CYCLE-1 )
tx_data_ready <= 1'b1;
end
//計算發送一位資料的時鐘
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
cycle_cnt <= 16'd0;
else if((state == S_SEND_BYTE && cycle_cnt == CYCLE-1)||next_state != state)
cycle_cnt <= 16'd0;
else
cycle_cnt <= cycle_cnt + 16'd1;
end
//擷取要發送的一位資料
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
tx_reg <= 1'd1;
else
case(state)
S_START:
tx_reg <= 1'd0;
S_SEND_BYTE:
tx_reg <= tx_data_latch[bit_cnt];
S_STOP:
tx_reg <= 1'd1;
default :
tx_reg <= 1'd1;
endcase
end
endmodule