串口接收端verilog代码分析

串口接收端verilog代码分析

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: chensimin
// 
// Create Date: 2018/05/23 16:14:30
// Design Name: 
// Module Name: uart_rx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module uart_rx(

    input  wire  clk,
    input  wire  rxd,
    output reg   [7:0]data_i,
    output wire  receive_ack

    );

    reg [7:0] data_i = 0;
    

    localparam     IDLE = 0,
                   RECEIVE = 1,
                   RECEIVE_END = 2;


    reg [3:0]cur_st = 0;
    reg [3:0]nxt_st = 0;
    always @(posedge clk)
    begin
        cur_st <= nxt_st;
    end


    always @(*)
    begin
        nxt_st = cur_st;

        case(cur_st)

           IDLE: 
           begin
                   if(!rxd)                  //当从接收端口上进来的数据开始为0时,即启动接收
                       nxt_st = RECEIVE;
           end

           RECEIVE: 
           begin
                   if(count == 7) 
                       nxt_st = RECEIVE_END;    
           end

           RECEIVE_END: 
           begin
                   nxt_st = IDLE;
           end

           default: 
           begin
                   nxt_st = IDLE;
           end

        endcase
    
    end


    reg [4:0]count = 0;
      always @(posedge clk)
      begin
        if(cur_st == RECEIVE)
            count <= count + 1;
          else if(cur_st == IDLE || cur_st == RECEIVE_END)
            count <= 0;
    end


    //当前状态为接收状态时,rxd 信号线上的数据存储在data_i的最高位
    //同时data_i 的数据总体右移一位
      always @(posedge clk)
      begin
          if(cur_st == RECEIVE)  
          begin
             data_i[6:0] <= data_i[7:1];
             data_i[7] <= rxd;            // rxd 传过来什么数据, data_i上立马显示什么数据,因为是从端口采集到的数据
          end

      end

    assign receive_ack = (cur_st == RECEIVE_END) ? 1: 0;

endmodule





/*

add_force {/uart_rx/clk} -radix hex {1 0ns} {0 50000ps} -repeat_every 100000ps
add_force {/uart_rx/rxd} -radix hex {1 0ns} {0 300ns} {1 400ns} {0 500ns} {1 600ns} {0 700ns} {1 800ns} {0 900ns} {1 1000ns}


*/

仿真结果:

 注意:

  分析寄存器的更新一定要结合时钟沿,然后寄存器在时钟沿前后的变化状态。

原文地址:https://www.cnblogs.com/chensimin1990/p/9086964.html