這次設計一個多位元組(8-256位)且波特率可更改(通過修改例化模塊的參數)的串口發送模塊。 1、狀態機的設定 狀態機的設定有空閑、發送、和數據移位三個狀態,其中空閑狀態為等待多位元組發送的信號; 發送狀態為給8位串口發送模塊傳輸待發送8位的數據同時判斷是否發送完數據回到空閑狀態; 數據移位狀態為等到前 ...
這次設計一個多位元組(8-256位)且波特率可更改(通過修改例化模塊的參數)的串口發送模塊。
1、狀態機的設定
- 狀態機的設定有空閑、發送、和數據移位三個狀態,其中空閑狀態為等待多位元組發送的信號;
- 發送狀態為給8位串口發送模塊傳輸待發送8位的數據同時判斷是否發送完數據回到空閑狀態;
- 數據移位狀態為等到前面8位位元組數據發送完後,將接下來待發送的8位數據移動到數據寄存器的低8位中。若數據在發送中則會進行等待;
2、需要的模塊
(1)8位串口發送模塊
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Lclone
//
// Create Date: 2022/12/10 00:21:40
// Design Name: uart_byte_tx
// Module Name: uart_byte_tx
// Project Name: uart_byte_tx
// Description: 8位串口發送模塊,波特率可通過參數設置。
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module uart_byte_tx
#(
parameter TX_BAUD = 9600,
parameter CLK_FQC = 50_000_000,
parameter BAUD_CNT = CLK_FQC/TX_BAUD)
(
input [7:0] Data,
input Send_en,
input Clk,
input Rst_n,
output reg Uart_Tx,
output reg Tx_done
);
reg [15:0] baud_cnt;
reg [ 3:0] bit_cnt;
reg Send_en_r;
reg Send_en_rr;
reg Tx_flag;
always @(posedge Clk) begin
Send_en_r <= Send_en;
Send_en_rr <= Send_en_r;
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
Tx_flag <= 0;
else if(~Send_en_rr & Send_en_r)
Tx_flag <= 1'b1;
else if(bit_cnt == 10 - 1 & baud_cnt == BAUD_CNT - 1)
Tx_flag <= 1'b0;
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
baud_cnt <= 0;
else if(baud_cnt == BAUD_CNT - 1)
baud_cnt <= 0;
else if(Tx_flag)
baud_cnt <= baud_cnt + 1'b1;
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
bit_cnt <= 0;
else if(bit_cnt == 10 - 1 & baud_cnt == BAUD_CNT - 1)
bit_cnt <= 0;
else if(baud_cnt == BAUD_CNT - 1)
bit_cnt <= bit_cnt + 1'b1;
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
Uart_Tx <= 1'b1;
else if(Tx_flag == 0)
Uart_Tx <= 1'b1;
else case(bit_cnt)
0: Uart_Tx <= 1'b0;
1: Uart_Tx <= Data[0];
2: Uart_Tx <= Data[1];
3: Uart_Tx <= Data[2];
4: Uart_Tx <= Data[3];
5: Uart_Tx <= Data[4];
6: Uart_Tx <= Data[5];
7: Uart_Tx <= Data[6];
8: Uart_Tx <= Data[7];
9: Uart_Tx <= 1'b1;
default: Uart_Tx <= 1'b1;
endcase
end
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
Tx_done <= 1'b0;
else if(bit_cnt == 9 & baud_cnt == BAUD_CNT - 1)
Tx_done <= 1'b1;
else
Tx_done <= 1'b0;
end
endmodule
3、設計的模塊代碼
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/12/12 19:14:03
// Design Name: uart_bytes_tx
// Module Name: uart_bytes_tx_3
// Project Name: uart_bytes_tx
// Target Devices: xc7z020clg400-1
// Tool Versions: 2018.3
// Description: 多位元組(8-256位)且波特率可更改(通過修改例化模塊的參數)的串口發送模塊。
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module uart_bytes_tx_3
#( parameter DATA_WIDTH = 40, //待發送的數據位寬
parameter ROUNDS = DATA_WIDTH/8) //數據發送的次數(例化時不需要設置)
(
input Clk, //時鐘信號
input Rst_n, //複位信號
input [DATA_WIDTH-1:0] Bytes_data, //多位元組數據埠
input Send_bytes_en, //多位元組發送使能
output reg Tx_bytes_done, //多位元組發送結束
output wire Uart_Tx //串口發送埠
);
reg [ 2:0] state; //狀態寄存器
reg [DATA_WIDTH-1:0] bytes_data_reg; //多位元組數據寄存器
reg [ 7:0] data_reg; //待發送的8位數據寄存器
reg send_en; //8位數據的發送使能
wire tx_done; //8位數據的發送結束
reg [ 4:0] rounds; //需要發送的次數
uart_byte_tx //串口8位發送模塊
# ( .TX_BAUD (9600), //波特率
.CLK_FQC (50_000_000)) //模塊的時鐘頻率
uart_byte_tx_inst
(
.Data (data_reg),
.Send_en (send_en),
.Clk (Clk),
.Rst_n (Rst_n),
.Uart_Tx (Uart_Tx),
.Tx_done (tx_done)
);
always @(posedge Clk or negedge Rst_n) begin //數據寄存
if(Rst_n == 0)
bytes_data_reg <= 0;
else if(Send_bytes_en)
bytes_data_reg <= Bytes_data;
else
bytes_data_reg <= bytes_data_reg;
end
always @(posedge Clk or negedge Rst_n) begin //狀態機
if(Rst_n == 0) begin
state <= 0;
data_reg <= 0;
send_en <= 0;
Tx_bytes_done <= 0;
end
else case(state)
0: begin
if(Send_bytes_en)
state <= 3'b1;
else begin
state <= 0;
data_reg <= 0;
send_en <= 0;
Tx_bytes_done <= 0;
end
end
1: begin
if(rounds == ROUNDS) begin
Tx_bytes_done <= 1'b1;
state <= 0;
end
else begin
data_reg <= bytes_data_reg[7:0];
send_en <= 1'b1;
state <= 3'd2;
end
end
2: begin
send_en <= 0;
if(tx_done) begin
bytes_data_reg <= bytes_data_reg >> 8;
state <= 3'd1;
end
else
state <= 3'd2;
end
endcase
end
always @(posedge Clk or negedge Rst_n) begin //發送次數計數
if(Rst_n == 0)
rounds <= 0;
else if(rounds == ROUNDS & state == 1)
rounds <= 0;
else if(tx_done)
rounds <= rounds + 1'b1;
end
endmodule
4、模擬驗證
(1)模擬激勵
`timescale 1ns / 1ps
module uart_bytes_tx_tb();
reg Clk;
reg Rst_n;
reg Send_bytes_en;
reg [63:0]Bytes_data;
wire Tx_bytes_done;
wire Uart_Tx;
uart_bytes_tx_3
# ( .DATA_WIDTH (64))
uart_bytes_tx_inst
(
.Clk (Clk),
.Rst_n (Rst_n),
.Bytes_data (Bytes_data),
.Send_bytes_en (Send_bytes_en),
.Tx_bytes_done (Tx_bytes_done),
.Uart_Tx (Uart_Tx)
);
defparam uart_bytes_tx_inst.uart_byte_tx_inst.BAUD_CNT = 10;
initial Clk <= 1'b1;
always #10 Clk <= ~Clk;
initial begin
Rst_n <= 0;
Bytes_data <= 0;
Send_bytes_en <= 0;
#200
Rst_n <= 1'b1;
#20
Bytes_data <= 64'h0123456789abcdef;
Send_bytes_en <= 1'b1;
#20
Send_bytes_en <= 0;
#20000
Bytes_data <= 64'hfedcba9876543210;
Send_bytes_en <= 1'b1;
#20
Send_bytes_en <= 0;
@(posedge Tx_bytes_done)
#100
$stop;
end
endmodule
(2)模擬波形
第一輪發送:
兩輪發送: