Verilog串口环回

串口发送

`timescale 1ns / 1ns



module uart_send
 #( parameter CLK_FREQ = 50000000,
    parameter BPS = 115200
  )
(sys_clk,
 reset_n,
 uart_data,
 tx_go,
 uart_tx,
 uart_tx_busy
    );
input sys_clk;
input reset_n;
input [7:0]uart_data;
input tx_go;
output reg uart_tx;
output uart_tx_busy;

localparam BPS_MAX = CLK_FREQ/BPS;

reg [1:0] tx_go_r;
reg tx_en;
reg [3:0] tx_cnt;
reg [15:0] bps_clk;

//检测tx_go的上升沿
always@(posedge sys_clk or negedge reset_n)
  begin
    if(!reset_n)
       tx_go_r<=0;
    else 
       begin
        tx_go_r[0]<=tx_go;
        tx_go_r[1]<=tx_go_r[0];
       end
  end

//tx_en使能控制
always@(posedge sys_clk or negedge reset_n)
  begin
    if(!reset_n)
      tx_en<=0;
    else if(tx_go_r==2'b01)
      tx_en<=1;
    else if(tx_cnt==9&&bps_clk==BPS_MAX-1)
      tx_en<=0;
    else tx_en<=tx_en;  
  end

//bps_clk分频
  always@(posedge sys_clk or negedge reset_n)
     begin
         if(!reset_n)
          bps_clk<=0;
         else if(tx_en)
           begin
             if(bps_clk==BPS_MAX-1)
               bps_clk<=0;
             else bps_clk<=bps_clk+1'b1;
           end
          else bps_clk<=0;
     end

//发送位计数
  always@(posedge sys_clk or negedge reset_n)
     begin
       if(!reset_n)
         tx_cnt<=0;
       else if (tx_en)
         begin
           if(tx_cnt==9&&bps_clk==BPS_MAX-1)
             tx_cnt<=0;
           else if(bps_clk==BPS_MAX-1)
             tx_cnt<=tx_cnt+1'b1;
           else tx_cnt<=tx_cnt;
         end
        else tx_cnt<=0;
     end

//发送控制
  always@(posedge sys_clk or negedge reset_n)
     begin
       if(!reset_n)
        uart_tx<=1;
       else if (tx_en)
       begin
        case(tx_cnt)
         0:uart_tx<=0;
         1:uart_tx<=uart_data[0];
         2:uart_tx<=uart_data[1];
         3:uart_tx<=uart_data[2];
         4:uart_tx<=uart_data[3];
         5:uart_tx<=uart_data[4];
         6:uart_tx<=uart_data[5];
         7:uart_tx<=uart_data[6];
         8:uart_tx<=uart_data[7];
         9:uart_tx<=1;
        endcase
       end
       else uart_tx<=1;
     end


assign uart_tx_busy = tx_en;


 
endmodule

串口接收

module uart_recv
 #( parameter CLK_FREQ = 50000000,
    parameter BPS = 115200
  )
  (
    sys_clk,
    reset_n,
    uart_tx,
    rx_data,
    rx_done
  );
  input sys_clk;
  input reset_n;
  input uart_tx;
  output reg [7:0] rx_data;
  output reg rx_done; 
  
  localparam BPS_MAX = CLK_FREQ/BPS;
  
  reg [15:0] bps_clk;
  reg [1:0] uart_tx_r;
  reg [3:0] rx_cnt;
  wire start_flag;
  reg uart_en;
  reg [7:0] uart_din;
  
  //uart_tx下降沿检测,检测到下降沿后,start_flag拉高一个周期
  always@(posedge sys_clk or negedge reset_n)
     begin
         if(!reset_n)
            uart_tx_r<=2'b00;
         else 
           begin
            uart_tx_r[0]<=uart_tx;
            uart_tx_r[1]<=uart_tx_r[0];
           end
     end

   assign start_flag = (uart_tx_r==2'b10)?1:0;
   
   //UART_EN使能信号控制
    always@(posedge sys_clk or negedge reset_n)
     begin
         if(!reset_n)
           uart_en<=0;
         else if(start_flag)
           uart_en<=1;
         else if(rx_cnt==9&&bps_clk==BPS_MAX/2-1)
           uart_en<=0;
         else uart_en<=uart_en;
     end
   
   //bps_clk 分频
     always@(posedge sys_clk or negedge reset_n)
     begin
         if(!reset_n)
          bps_clk<=0;
         else if(uart_en)
           begin
             if(bps_clk==BPS_MAX-1)
               bps_clk<=0;
             else bps_clk<=bps_clk+1'b1;
           end
          else bps_clk<=0;
     end
   
   //rx_cnt 计数
     always@(posedge sys_clk or negedge reset_n)
     begin
        if(!reset_n)
          rx_cnt<=0;
        else if(uart_en)
         begin
           if(rx_cnt==9&&bps_clk==BPS_MAX/2-1)
               rx_cnt<=0;
           else if(bps_clk==BPS_MAX-1)
             rx_cnt<=rx_cnt+1'b1;
           else
             rx_cnt<=rx_cnt;
         end
     end
     
     //数据接收
      always@(posedge sys_clk or negedge reset_n)
       begin 
         if(!reset_n) 
           uart_din<=0;
         else if(bps_clk==BPS_MAX/2-1)
           begin
             case(rx_cnt)
              0:uart_din<=0;
              1:uart_din[0]<=uart_tx;
              2:uart_din[1]<=uart_tx;
              3:uart_din[2]<=uart_tx;
              4:uart_din[3]<=uart_tx;
              5:uart_din[4]<=uart_tx;
              6:uart_din[5]<=uart_tx;
              7:uart_din[6]<=uart_tx;
              8:uart_din[7]<=uart_tx;
              default:uart_din<=uart_din;
             endcase
           end
           else uart_din<=uart_din;
       end
    
   //接受完成标志位
      always@(posedge sys_clk or negedge reset_n)
       begin 
         if(!reset_n) 
           rx_done<=0;
         else if(rx_cnt==9&&bps_clk==BPS_MAX/2-1)
           rx_done<=1;
         else 
           rx_done<=0;           
       end 
    
    //接受数据输出
        always@(posedge sys_clk or negedge reset_n)
          begin 
            if(!reset_n) 
            rx_data<=0;
            else if (rx_done)
            rx_data<=uart_din;
            else 
            rx_data<=rx_data;
            end
       
       
endmodule

环回:

module uart_loop
(
  recv_data,
  recv_done,
  sys_clk,
  reset_n,
  send_busy,
  send_data,
  send_en
    );
    
  input [7:0] recv_data;
  input recv_done;
  input sys_clk;
  input reset_n;
  input send_busy;
  output reg [7:0] send_data;
  output reg send_en;
  reg [1:0] recv_done_r;
  reg send_ready;
  //将recv_done寄存两拍,检测rx_done的上升沿    
   always@(posedge sys_clk or negedge reset_n)
    begin
      if(!reset_n)
       recv_done_r<=0;
      else 
       begin
         recv_done_r[0]<= recv_done;
         recv_done_r[1]<= recv_done_r[0];
       end
    end
//检测到 rx_done的上升沿后,发出准备信号   
    always@(posedge sys_clk or negedge reset_n)
      begin
        if(!reset_n)
          begin
            send_ready<=0;           
          end
        else if(recv_done_r==2'b01)
          begin
            send_ready<=1;
          end
        else if(!send_busy)
            send_ready<=0;           
      end 
      
  //  控制   
     always@(posedge sys_clk or negedge reset_n)
       begin
         if(!reset_n)
           begin
             send_data<=0;
             send_en<=0;
           end
         else if(send_ready==1&&!send_busy)
           begin
             send_data<=recv_data;
             send_en<=1;
           end
          else
           begin
             send_data<=send_data;
             send_en<=0;
           end
       end
endmodule

top:

module uart_top(
  sys_clk,
  reset_n,
  uart_rxd,
  uart_txd
    );
    
  input  sys_clk;
  input reset_n;
  input uart_rxd;
  output uart_txd;
  
  wire [7:0] recv_data;
  wire recv_done;
  wire [7:0] send_data;
  wire send_busy;
  wire send_en;
  parameter CLK_FREQ = 50000000;
  parameter BPS = 115200;
  
 uart_send 
 #( .CLK_FREQ(CLK_FREQ),
    .BPS(BPS)
  )
  u_uart_send
(.sys_clk(sys_clk),
 .reset_n(reset_n),
 .uart_data(send_data),
 .tx_go(send_en),
 .uart_tx(uart_txd),
 .uart_tx_busy(send_busy)
    );
    
  
 uart_recv
 #( .CLK_FREQ(CLK_FREQ),
    .BPS(BPS)
  )
 u_uart_recv
  (
    .sys_clk(sys_clk),
    .reset_n(reset_n),
    .uart_tx(uart_rxd),
    .rx_data(recv_data),
    .rx_done(recv_done)
  ); 
  
  uart_loop u_uart_loop
(
  .recv_data(recv_data),
  .recv_done(recv_done),
  .sys_clk(sys_clk),
  .reset_n(reset_n),
  .send_busy(send_busy),
  .send_data(send_data),
  .send_en(send_en)
    ); 
  
endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值