- module uart_tx(
- rst,
- clk,
- baud_set, //波特率設置
- din, //欲發送的數據
- tx, //發送數據
- done //發送結束時done為1
- );
- input rst,clk;
- input [7:0] din;
- input [2:0] baud_set;
- output tx;
- output done;
- reg [12:0] div_cnt;
- reg [3:0] bps_cnt;
- reg [7:0] reg0_din;
- reg [7:0] reg1_din;
- reg tx;
- reg en;
- reg [12:0] bps_DR; //分频计数最大值
- //=============================================
- // 狀態機
- //=============================================
- parameter trans = 1'b0, //發送數據
- finish = 1'b1; //發送結束
- reg present_state, next_state;
- always@(posedge clk or negedge rst)
- begin
- if(!rst) present_state <= trans;
- else present_state <= next_state;
- end
- always@(bps_cnt or div_cnt or present_state)
- begin
- case(present_state)
- trans : if(div_cnt == 13'd5207 && bps_cnt == 4'd11)
- next_state = finish;
- else
- next_state = trans;
- finish : next_state = finish;
- endcase
- end
- always@(posedge clk or negedge rst)
- begin
- if(!rst) en <= 1'b0;
- else
- begin
- case(present_state)
- trans : en <= 1'b1;
- finish : en <= 1'b0;
- endcase
- end
- end
- //=============================================
- // 分频設置
- //=============================================
- always@(posedge clk or negedge rst)
- if(!rst)
- bps_DR <= 13'd5207;
- else
- begin
- case(baud_set)
- 0 : bps_DR <= 13'd5207; //9600 bps
- 1 : bps_DR <= 13'd2603; //19200 bps
- 2 : bps_DR <= 13'd1301; //38400 bps
- 3 : bps_DR <= 13'd867; //57600 bps
- 4 : bps_DR <= 13'd433; //115200 bps
- default : bps_DR <= 13'd5207;
- endcase
- end
- //=============================================
- //為求信號穩定消除亞穩態加兩級寄存器
- //=============================================
- always@(posedge clk)
- begin
- reg0_din <= din;
- reg1_din <= reg0_din;
- end
- //=============================================
- // 分頻計數器
- //=============================================
- always@(posedge clk or negedge rst)
- begin
- if(!rst) div_cnt <= 13'd0;
- else if(en)
- begin
- if(div_cnt == bps_DR) div_cnt <= 13'd0;
- else div_cnt <= div_cnt + 13'd1;
- end
- else div_cnt <= div_cnt;
- end
- always@(posedge clk or negedge rst)
- begin
- if(!rst) bps_cnt <= 4'd0;
- else if(div_cnt == bps_DR)
- begin
- if(bps_cnt == 4'd11) bps_cnt <= 4'd0;
- else bps_cnt <= bps_cnt + 4'd1;
- end
- else bps_cnt <= bps_cnt;
- end
- //=============================================
- // 用多工器將數據發送出去
- //=============================================
- always@(posedge clk or negedge rst)
- begin
- if(!rst)
- tx <= 1'b1;
- else
- begin
- case(bps_cnt)
- 0 : tx <= 1'b1;
- 1 : tx <= 1'b0; //起始位
- 2 : tx <= reg1_din[0];
- 3 : tx <= reg1_din[1];
- 4 : tx <= reg1_din[2];
- 5 : tx <= reg1_din[3];
- 6 : tx <= reg1_din[4];
- 7 : tx <= reg1_din[5];
- 8 : tx <= reg1_din[6];
- 9 : tx <= reg1_din[7];
- 10: tx <= 1'b1; //停止位
- default: tx <= 1'b1;
- endcase
- end
- end
- //=============================================
- //傳輸結束時done為1
- //=============================================
- assign done = (bps_cnt == 4'd11) ? 1'b1 : 1'b0;
- //=============================================
- endmodule
- //仿真testbench
- `timescale 1ns/100ps
- module uart_tx_test1;
- reg rst,clk;
- reg [7:0] din;
- reg [2:0] baud_set;
- wire tx;
- wire done;
- uart_tx uart_tx(
- .rst(rst),
- .clk(clk),
- .din(din),
- .baud_set(baud_set),
- .tx(tx),
- .done(done)
- );
- initial
- begin
- clk = 1'b1;
- forever #10 clk = ~clk; //頻率為50M Hz
- end
- initial
- begin
- #0
- rst = 1'b0;
- baud_set = 3'd0; // 波特率為9600 bps
- din = 8'b01010101;
- #1
- rst = 1'b1;
- #200000
- $stop;
- #10
- $finish;
- end
- endmodule