Verilog之UART串口通信

//UART串行异步通信
module shiyan1(
input clk,
input reset,
input uart_rx,
output uart_tx);
parameter CLK_FRE = 50;
parameter BAUD_RATE = 115200;
localparam IDLE = 2'd1;
localparam WAIT = 2'd2;
wire rx_data_valid, tx_data_ready;
reg tx_data_valid;
wire [7 : 0] rx_data_out;
reg [1 : 0] s;
reg [7 : 0] tx_data_in;
reg [8 : 0] wait_cnt;
always @(posedge clk or negedge reset)
  begin
      if(!reset)
          begin
              wait_cnt <= 9'b0;
              s <= IDLE;
              tx_data_valid <= 1'b0;
              tx_data_in <= 8'b0;
            end
        else
          begin
              case(s)
                  IDLE :
                      s <= WAIT;
                    WAIT :
                      begin
                          if(rx_data_valid == 1'b1)
                              begin
                                  tx_data_valid = 1'b1;
                                    tx_data_in <= rx_data_out;
                                end
                            else if(tx_data_valid == 1'b1 && tx_data_ready == 1'b1)
                              tx_data_valid <= 1'b0;
                            else
                              wait_cnt <= wait_cnt + 1;
                                if(wait_cnt >= CLK_FRE * 1000000)
                                  begin
                                      s <= IDLE;
                                        wait_cnt <= 9'b0;
                                    end
                        end
                    default :
                      s <= IDLE;
                endcase
            end
    end
uart_rx #(.CLK_FRE(CLK_FRE), .UART_BPS(BAUD_RATE)) U1 (.clk(clk), .reset(reset), .rx_in(uart_rx), .rx_out(rx_data_out), .rx_data_valid(rx_data_valid));
uart_tx #(.CLK_FRE(CLK_FRE), .UART_BPS(BAUD_RATE)) U2 (.clk(clk), .reset(reset), .tx_data_in(tx_data_in), .tx_data_valid(tx_data_valid), .tx_data_out(tx_data_out), .tx_data_ready(tx_data_ready));
endmodule
module uart_rx #(parameter CLK_FRE = 50, parameter UART_BPS = 115200)
(input clk,
input reset,
input rx_in,
output reg [7 : 0] rx_out,
output reg rx_data_valid);
localparam CYCLE = CLK_FRE * 1000000;
localparam IDLE = 3'd1;
localparam START = 3'd2;
localparam REC_BYTE = 3'd3;
localparam STOP = 3'd4;
wire rx_negedge;
reg rx_in_1, rx_in_2;
reg [2 : 0] s, ns;
reg [3 : 0] bit_i;
reg [7 : 0] rx_bits;
reg [8 : 0] cycle_i;
always @(posedge clk or negedge reset)
  begin
      if(!reset)
          s <= IDLE;
        else
          s <= ns;
    end
always @(posedge clk or negedge reset)
  begin
      if(!reset)
          begin
              rx_in_1 <= 0;
                rx_in_2 <= 0;
            end
        else
          begin
              rx_in_1 <= rx_in;
                rx_in_2 <= rx_in_1;
            end
    end
assign rx_negedge = rx_in_2 && (~ rx_in_1);
always @(*)
  begin
      case(s)
          IDLE :
              begin
                  if(rx_negedge)
                      ns = START;
                    else
                      ns = IDLE;
                end
            START :
              begin
                  if(cycle_i == CYCLE - 1)
                      ns = REC_BYTE;
                    else
                      ns = START;
                end
            REC_BYTE :
              begin
                  if(cycle_i == CYCLE - 1 && bit_i == 3'd7)
                      ns = STOP;
                    else
                      ns = REC_BYTE;
                end
            STOP :
              begin
                  if(cycle_i == (CYCLE >> 1) - 1)
                      ns = IDLE;
                    else
                      ns = STOP;
                end
            default :
              ns = STOP;
        endcase
    end
always @(posedge clk or negedge reset)
  begin
      if(!reset)
          cycle_i <= 9'b0;
        else if(s != ns || (s == REC_BYTE && cycle_i == CYCLE - 1))
          cycle_i <= 9'b0;
        else
          cycle_i <= cycle_i + 9'b1;
    end
always @(posedge clk or negedge reset)
  begin
      if(!reset)
          bit_i <= 3'b0;
        else if(s == REC_BYTE)
          begin
              if(cycle_i == CYCLE - 1)
                  bit_i <= bit_i + 3'b1;
                else
                  bit_i <= bit_i;
            end
        else
          bit_i <= 3'b0;
    end
always @(posedge clk or negedge reset)
  begin
      if(!reset)
          rx_bits <= 8'b0;
        else if(s == REC_BYTE && cycle_i == (CYCLE >> 1) - 1)
          rx_bits[bit_i] <= rx_in;
        else
          rx_bits <= rx_bits;
    end
always @(posedge clk or negedge reset)
  begin
      if(!reset)
        rx_out <= 8'b0;
        else if(s == STOP && ns != s)
          rx_out <= rx_bits;
    end
always @(posedge clk or negedge reset)
  begin
      if(!reset)
          rx_data_valid <= 1'b0;
        else if(s == STOP && s != ns)
          rx_data_valid <= 1'b1;
        else
          rx_data_valid <= 1'b0;
    end
endmodule
module uart_tx #(parameter CLK_FRE = 50, parameter UART_BPS = 115200)
(input clk,
input reset,
input tx_data_valid,
input [7 : 0] tx_data_in,
output tx_data_out,
output reg tx_data_ready
);
localparam CYCLE = CLK_FRE * 1000000;
localparam IDLE = 3'd1;
localparam START = 3'd2;
localparam SEND_BYTE = 3'd3;
localparam STOP = 3'd4;
reg tx_data_reg;
reg [2 : 0] s, ns;
reg [3 : 0] bit_i;
reg [7 : 0] tx_data_latch;
reg [8 : 0] cycle_i;
always @(posedge clk or negedge reset)
  begin
      if(!reset)
          s <= IDLE;
        else
          s <= ns;
    end
always @(*)
  begin
      case(s)
          IDLE :
              begin
                  if(tx_data_valid == 1'b1)
                      ns = START;
                    else
                      ns = IDLE;
                end
            START :
              begin
                  if(cycle_i == CYCLE - 1)
                      ns = SEND_BYTE;
                    else
                      ns = START;
                end
            SEND_BYTE :
              begin
                  if(bit_i == 3'd7 && cycle_i == CYCLE - 1)
                      ns = STOP;
                    else
                      ns = SEND_BYTE;
                end
            STOP :
              begin
                  if(cycle_i == CYCLE - 1)
                      ns = IDLE;
                    else
                      ns = STOP;
                end
            default :
              ns = IDLE;
        endcase
    end
always @(posedge clk or negedge reset)
  begin
        if(!reset)
            cycle_i <= 9'b0;
        else if(s != ns || (s == SEND_BYTE && cycle_i == CYCLE - 1))
            cycle_i <= 9'b0;
        else
            cycle_i <= cycle_i + 9'b1;
    end
always @(posedge clk or negedge reset)
  begin
        if(!reset)
            bit_i <= 9'b0;
        else if(s == SEND_BYTE)
          begin
              if(cycle_i == CYCLE - 1)
                bit_i <= bit_i + 3'b1;
                else
                  bit_i <= bit_i;
            end
        else
            bit_i <= 3'b0;
    end
always @(posedge clk or negedge reset)
  begin
      if(!reset)
        tx_data_latch <= 8'b0;
        else if(s == IDLE && tx_data_valid == 1'b1)
          tx_data_latch <= tx_data_in;
    end
always @(posedge clk or negedge reset)
  begin
      if(!reset)
          tx_data_reg <= 1'b1;
        else
          begin
              case(s)
                  IDLE, STOP :
                      tx_data_reg <= 1'b1;
                    START :
                      tx_data_reg <= 1'b0;
                    SEND_BYTE :
                    tx_data_reg    <= tx_data_latch[bit_i];
                    default :
                      tx_data_reg <= 1'b1;
                endcase
            end
    end
assign tx_data_out = tx_data_reg;
always @(posedge clk or negedge reset)
  begin
    if(!reset)
          tx_data_ready <= 1'b0;
        else if(s == STOP && cycle_i == CYCLE - 1)
          tx_data_ready <= 1'b1;
        else if(s == IDLE)
          if(tx_data_valid == 1)
              tx_data_ready <= 1'b0;
            else
              tx_data_ready <= 1'b1;
    end
endmodule

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值