Uart回环(不带FIFO)及Testbench

一、串口概念

串行通信分为两种方式:

  • 同步串行通信(I2C/SPI)
  • 异步串行通信(UART)

区别:

  • 同步串行通信需要通信双方在同一时钟的控制下,同步传输数据。
  • 异步串行通信是指通信双方使用各自的时钟控制数据的发送和接收过程。

二、UART协议

  UART(Universal Asynchronous Receiver-Transmitter),它在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行数据转换成并行数据。 UART串口通信需要两根信号线来实现,一根用于发送,另外一根接收。控制高低电平达到数据的传输功能,输入全双工通信。

三、协议格式

一帧数据由4部分组成:

  • 起始位(1bit)
  • 数据位(6\7\8 bit)
  • 奇偶校验位(1bit)
  • 停止位(1bit\1.5bit\2bit)

常用的波特率有9600、19200、38400、57600以及115200等。

在这里插入图片描述
接受模块

在这里插入图片描述
发送模块

在这里插入图片描述

四、实验架构图

在这里插入图片描述

五、设计规范

  设计uart的发送和接受模块,数据起始位1bit,数据位8bit, 停止位1bit,忽略奇偶检验位。

六、设计输入

uart_tx.v发送端模块文件

module uart_tx(
    input           clk        ,
    input           rst_n      ,
    input    [7:0]  tx_data    ,
    input           rx_vld     ,
    output          tx         
);
    
parameter  TIME_BAUD = 9'd434 ;
reg      [8:0]   tx_data_r   ;
reg              tx_flag     ;

reg       [8:0]    cnt_baud            ;
wire             add_cnt_baud          ;
wire             end_cnt_baud          ;

reg       [3:0]    cnt_bit            ;
wire             add_cnt_bit          ;
wire             end_cnt_bit          ;

reg             tx_r      ;
  always @(posedge clk or negedge rst_n) begin
       if (!rst_n) begin
          tx_data_r <= 9'h1ff ;
       end
       else if(rx_vld) begin
           tx_data_r <= {tx_data,1'b0};
       end
       else begin
           tx_data_r <= tx_data_r ;
       end
  end

  always @(posedge clk or negedge rst_n) begin
       if (!rst_n) begin
          tx_flag <= 1'b0 ;
       end
       else if(rx_vld)begin
          tx_flag <= 1'b1 ;
       end
       else if(end_cnt_bit)begin
          tx_flag <= 1'b0 ;
       end
       else begin
          tx_flag <= tx_flag ;
       end
  end

always @(posedge clk or negedge rst_n) begin
       if (!rst_n) begin
           cnt_baud <= 1'b0;
       end
       else if(add_cnt_baud)begin
             if(end_cnt_baud)
                cnt_baud <= 1'b0;
             else 
                cnt_baud <= cnt_baud + 1'b1;
       end
  end
   assign add_cnt_baud = tx_flag ;
   assign end_cnt_baud = add_cnt_baud && cnt_baud == (TIME_BAUD-1);

  always @(posedge clk or negedge rst_n) begin
       if (!rst_n) begin
           cnt_bit <= 1'b0;
       end
       else if(add_cnt_bit)begin
             if(end_cnt_bit)
                cnt_bit <= 1'b0;
             else 
                cnt_bit <= cnt_bit + 1'b1;
       end
  end
   assign add_cnt_bit = end_cnt_baud ;
   assign end_cnt_bit = add_cnt_bit && cnt_bit == 8;

  always @(posedge clk or negedge rst_n) begin
       if (!rst_n) begin
          tx_r <= 1'b1 ;
       end
       else if(cnt_baud==(TIME_BAUD>>1))begin
          tx_r <= tx_data_r[cnt_bit]  ;
       end
      else if(end_cnt_bit)begin
          tx_r <= 1'b1 ;
      end
  end

assign tx = tx_r ;

endmodule 

rx_uart.v接收端模块文件

module uart_rx(
    input         clk        ,
    input         rst_n      ,
    input         rx         ,
    output  [7:0]      rx_dout    ,
    output     reg        rx_vld
);
    
parameter  TIME_BAUD=9'd434 ;
reg       rx0     ;
reg       rx1     ;
wire      nedge   ;

reg       add_flag  ;

reg       [8:0]    cnt_baud            ;
wire             add_cnt_baud          ;
wire             end_cnt_baud          ;
 (*noprune*)reg     [9:0]   rx_data ;

reg       [3:0]    cnt_bit            ;
wire             add_cnt_bit          ;
wire             end_cnt_bit          ;
reg     [7:0]   rx_data1 ;

  always @(posedge clk or negedge rst_n) begin
       if (!rst_n) begin
           rx0 <= 1'b1 ;
           rx1 <= 1'b1 ;
       end
       else begin
           rx0 <= rx ;
           rx1 <= rx0;
       end
  end

  assign  nedge = ~rx0 & rx1 ;

  always @(posedge clk or negedge rst_n) begin
       if (!rst_n) begin
          add_flag <= 1'b0 ;
       end
       else if(nedge)begin
          add_flag <= 1'b1 ;
       end
       else if(end_cnt_bit)begin
          add_flag <= 1'b0 ;
       end
       else begin
          add_flag <= add_flag ;
       end
  end

  always @(posedge clk or negedge rst_n) begin
       if (!rst_n) begin
           cnt_baud <= 1'b0;
       end
       else if(add_cnt_baud)begin
             if(end_cnt_baud)
                cnt_baud <= 1'b0;
             else 
                cnt_baud <= cnt_baud + 1'b1;
       end
  end
   assign add_cnt_baud = add_flag ;
   assign end_cnt_baud = add_cnt_baud && cnt_baud == (TIME_BAUD-1);

  always @(posedge clk or negedge rst_n) begin
       if (!rst_n) begin
           cnt_bit <= 1'b0;
       end
       else if(end_cnt_bit&&end_cnt_baud)begin
           cnt_bit <= 1'b0 ;
       end
       else if(add_cnt_bit)begin
             if(end_cnt_bit)
                cnt_bit <= 1'b0;
             else 
                cnt_bit <= cnt_bit + 1'b1;
       end
  end
   assign add_cnt_bit = end_cnt_baud ;
   assign end_cnt_bit = add_cnt_bit && cnt_bit == 8;



  always @(posedge clk or negedge rst_n) begin
       if (!rst_n) begin
         rx_data <= 9'd0 ;
       end
       else if(add_flag&&(cnt_baud==(TIME_BAUD>>1)))begin
         rx_data <= {rx1,rx_data[8:1]};
       end
  end
  
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            rx_data1 <= 8'd0 ;
         end
         else if(end_cnt_bit)begin
            rx_data1 <= rx_data[8:1] ;
         end
    end
 assign  rx_dout = rx_data1 ;
  always @(posedge clk or negedge rst_n) begin
       if (!rst_n) begin
          rx_vld <= 1'b0 ;
       end
       else if(end_cnt_bit)begin
          rx_vld <= 1'b1 ;
       end
       else begin
          rx_vld <= 1'b0 ;
       end
  end

endmodule

uart.v顶层模块文件

module uart(
    input     clk      ,
    input     rst_n    ,
    input     rx      ,
    output    tx  
);

wire    [7:0]   data   ;
wire      rx_vld       ;

uart_rx u_rx(
   /*  input          */      .clk    (clk    )    ,
   /*  input          */      .rst_n  (rst_n  )    ,
   /*  input          */      .rx     (rx     )    ,
   /*  output  [7:0]  */      .rx_dout(data)    ,
   /*  output     reg */      .rx_vld (rx_vld ) 
);
uart_tx u_tx(
   /*  input          */  .clk     (clk    )   ,
   /*  input          */  .rst_n   (rst_n  )   ,
   /*  input    [7:0] */  .tx_data (data)   ,
   /*  input          */  .rx_vld  (rx_vld )   ,
   /*  output         */  .tx      (tx     )   
);

endmodule

七、引脚分配

元件管脚
rxM2
txG1
rst_nE15
clkE1

八、运行效果

在这里插入图片描述

九、Testbench文件

uart_tx_tb仿真文件

`timescale 1ns/1ns
module uart_tx_tb();
reg clk;
reg rst_n;
reg tx_req;
reg [7:0] 	tx_din;
wire        tx_dout;
wire       dout_vld;

always #(10) clk = ~clk;//每隔10ns翻转一次

initial begin//初始化信号
	clk 	= 1'b0     ;//时钟信号初始化为0
	rst_n   = 1'b0     ;//复位信号初始化为0
	#(10)         ;//等待10ns
	rst_n   = 1'b1     ;//复位信号拉高电平
    tx_req  = 1'b1;
    tx_din  = 8'b00001111;
    #(100_000);
    tx_req  = 1'b0;
	 $stop;
end 

uart_tx u_uart_tx_tb(
	.clk(clk)	,
	.rst_n(rst_n)	,
	.tx_req(tx_req),//发送请求
	.tx_din(tx_din),//并行数据输入
	
	.tx_dout(tx_dout),//串行数据输出
	.dout_vld(dout_vld)//并转串完成标志
	
);
endmodule

uart_rx_tb仿真文件

`timescale 1ns/1ns
module uart_rx_tb();
reg clk;
reg rst_n;
reg rx_din;
wire [7:0] 	rx_dout;
wire       dout_vld;

always #(10) clk = ~clk;//每隔10ns翻转一次

initial begin//初始化信号
	clk 	= 1'b0     ;//时钟信号初始化为0
	rst_n   = 1'b0     ;//复位信号初始化为0
	#(10)         ;//等待10ns
	rst_n   = 1'b1     ;//复位信号拉高电平
	rx_din  = 1'b0;
    #(8681);
	rx_din  = 1'b0;
    #(8681);
	rx_din  = 1'b0;
    #(8681);
	rx_din  = 1'b0;
    #(8681);
	rx_din  = 1'b0;
    #(8681);
	rx_din  = 1'b1;
    #(8681);
    rx_din  = 1'b1;
    #(8681);
	rx_din  = 1'b1;
    #(8681);
	rx_din  = 1'b1;
    #(8681);
	rx_din  = 1'b1;
	#(8681);
	 $stop;
end 

uart_rx u_uart_rx_tb(
	.clk(clk)	,
	.rst_n(rst_n)	,
	.rx_din(rx_din),
	.rx_dout(rx_dout),
	.dout_vld(dout_vld)
	
);
endmodule

十、仿真结果

uart_tx仿真结果
在这里插入图片描述

uart_rx仿真结果
在这里插入图片描述

  • 11
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值