【项目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
三、波形图



浙公网安备 33010602011771号