1. 程式人生 > 其它 >【專案1:uart_fam_led】— 第二部分

【專案1:uart_fam_led】— 第二部分

這部分加了接收模組,將接收和傳送模組一起進行模擬驗證

一、設計檔案

module uart_rx
#(
    parameter CLK_FRE = 50,      //clock frequency(Mhz)
    parameter BAUD_RATE = 115200 //serial baud rate ??????為什麼是序列波特率
)
(
    input                        clk,              //clock input
    input                        rst_n,            //asynchronous reset input, low active 
output reg[7:0] rx_8bit, //received serial data output reg rx_done, //received serial data is valid input rx_en, //data receiver module ready input rx_1bit //serial data input ); //calculates the clock cycle for baud rate
localparam CYCLE = CLK_FRE * 1000000 / BAUD_RATE; //state machine code localparam S_IDLE = 1; localparam S_START = 2; //start bit localparam S_REC_BYTE = 3; //data bits localparam S_STOP = 4
; //stop bit localparam S_DATA = 5; reg[2:0] state; reg[2:0] next_state; reg rx_d0; //delay 1 clock for rx_1bit reg rx_d1; //delay 1 clock for rx_d0 wire rx_negedge; //negedge of rx_1bit reg[7:0] rx_bits; //temporary storage of received data reg[15:0] cycle_cnt; //baud counter reg[2:0] bit_cnt; //bit counter // 邊沿檢測 assign rx_negedge = rx_d1 && ~rx_d0; // 非同步串列埠通訊:這裡需要將輸入訊號打2拍 // 目的:將輸入訊號與系統時鐘同步,防止出現亞穩態 always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) begin rx_d0 <= 1'b0; rx_d1 <= 1'b0; end else begin rx_d0 <= rx_1bit; rx_d1 <= rx_d0; end end //第一段:同步時序,描述狀態轉移 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(rx_negedge) next_state <= S_START; else next_state <= S_IDLE; S_START: if(cycle_cnt == CYCLE - 1)//one data cycle next_state <= S_REC_BYTE; else next_state <= S_START; S_REC_BYTE: if(cycle_cnt == CYCLE - 1 && bit_cnt == 3'd7) //receive 8bit data next_state <= S_STOP; else next_state <= S_REC_BYTE; S_STOP: if(cycle_cnt == CYCLE/2 - 1)//half bit cycle,to avoid missing the next byte receiver next_state <= S_DATA; else next_state <= S_STOP; S_DATA: if(rx_en) //data receive complete next_state <= S_IDLE; else next_state <= S_DATA; default: next_state <= S_IDLE; endcase end always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) rx_done <= 1'b0; else if(state == S_STOP && next_state != state) rx_done <= 1'b1; else if(state == S_DATA && rx_en) rx_done <= 1'b0; end //第三段:同步時序,描述每個狀態的輸出 always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) rx_8bit <= 8'd0; else if(state == S_STOP && next_state != state) rx_8bit <= rx_bits;//latch received data end // 接收的資料計數位 always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) begin bit_cnt <= 3'd0; end else if(state == S_REC_BYTE) if(cycle_cnt == CYCLE - 1) bit_cnt <= bit_cnt + 3'd1; else bit_cnt <= bit_cnt; else bit_cnt <= 3'd0; end // 波特率計數器 always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) cycle_cnt <= 16'd0; else if((state == S_REC_BYTE && cycle_cnt == CYCLE - 1) || next_state != state)//next_state != state:狀態發生跳轉 cycle_cnt <= 16'd0; else cycle_cnt <= cycle_cnt + 16'd1; end //receive serial data bit data always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) rx_bits <= 8'd0; else if(state == S_REC_BYTE && cycle_cnt == CYCLE/2 - 1) rx_bits[bit_cnt] <= rx_1bit;//串並轉換 else rx_bits <= rx_bits; end endmodule

二、測試檔案

`timescale 1ns/1ns

// 第二步:測試接收模組能否將序列資料轉成並行資料

module tb_step_02;

reg clk;
reg rst_n;

// tx輸入
reg [7:0] tx_8bit ;
reg tx_en ;

// tx輸出
wire tx_1bit;
wire tx_done;

//// rx輸入
reg rx_1bit;
reg rx_en;

// rx輸出
wire [7:0]rx_8bit;
wire rx_done;

initial begin
clk = 1'b0;
rst_n = 1'b0;
#12;
rst_n = 1'b1;
begin 

tx_8bit = 8'd0;
tx_en = 1'b0;

// 產生輸入資料
# 1000;//延遲50個時鐘週期
tx_8bit = 8'b0100_1111;
tx_en = 1'b1;//tx_en拉高,傳送端開始接收資料,當tx_en拉高1000ns後將其拉低,等資料傳完後,等著tx_done拉高,就完成一個H的傳送
#1000;
tx_en = 1'b0;
@(posedge tx_done)

tx_8bit = 8'b0110_0101;
tx_en = 1'b1;
# 100000;
tx_en = 1'b0;

end

end

always #10 clk = ~ clk;


// 呼叫傳送模組
uart_tx uart_tx_inst
(
.clk(clk),              //clock input
.rst_n(rst_n),            //asynchronous reset input, low active 
.tx_8bit(tx_8bit),          //data to send
.tx_en(tx_en),    //data to be sent is valid

.tx_done(tx_done),    //send ready
.tx_1bit(tx_1bit)            //serial data output
);

uart_rx uart_rx_inst
(
    .clk(clk),              //clock input
    .rst_n(rst_n),            //asynchronous reset input, low active
    
    .rx_8bit(rx_8bit),          //received serial data
    .rx_done(rx_done),    //received serial data is valid
    
    .rx_en(tx_done),    //data receiver module ready
    .rx_1bit(tx_1bit)            //serial data input
);
endmodule 

三、波形圖