天天看點

(二)verilog uart tx 序列槽發送一個位元組資料

`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