【项目1:uart_fsm_led】- 第二部分-tx-rx

这部分加了接收模块,将接收和发送模块一起进行仿真验证

一、设计文件

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 

三、波形图

 

posted @ 2022-04-12 16:26  刘小颜  阅读(98)  评论(0)    收藏  举报