FPGA串口收发(三):接收数据,再转发出去

FPGA串口收发(三):接收数据,再转发出去

功能:测试串口接收数据,再将数据从串口发出

// 模拟串口信号线,串行接收数据 1101_1000 ,转换为并行数据, 并显示 D8

// 把并行数据 D8 传给串口输出模块,串行输出数据 1101 1000

时钟40MHz,波特率115200

1、源文件

uart_rx.v

uart_tx.v

2、仿真文件 testbench

tb_uart_rx_tx.v

`timescale 1ns / 1ps
//
// Company: Myminieye
// Engineer: Nill
//
// Create Date:
// Design Name:
// Module Name:
// Project Name:
// Target Devices:
// Tool Versions:
// Description: 测试串口接收数据,再将数据从串口发出
// 模拟串口信号线,串行接收数据 1101_1000 ,转换为并行数据, 并显示 D8
// 把并行数据 D8 传给串口输出模块,串行输出数据 1101 1000
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
`define UD #1

module tb_uart_rx_tx();

//==========================================================================
//wire and reg 定义:信号与参数
//==========================================================================
	reg       sim_clk;		//模拟时钟信号
	//reg     tx_pulse;     // active posedge
	reg 	  sim_rst_n;
	
	// input to rx module
	reg       uart_rx;		//串口发送信号线
	//output from rx module
	wire [7:0] rx_data;		//送入串口发送模块,准备发送的数据
	wire       rx_finish;   //串口接收数据有效,接收完成拉高1个BPS
	
	// input to tx module
	reg       tx_pulse;     // active posedge
	reg [7:0] tx_data;		//送入串口发送模块,准备发送的数据
	//output from tx module
	wire      uart_tx;		//串口发送信号线
	wire      tx_busy;		//串口发送模块状态
	
	//时钟参数
	parameter SYS_CLK_FRE = 40_000_000;     //系统频率40MHz  40_000_000
	parameter SYS_CLK_PERIOD = 1_000_000_000/SYS_CLK_FRE;  //周期25ns
	parameter RST_CYCLE = 5;                //复位持续时间,clk时钟周期数
	parameter RST_TIME = RST_CYCLE * SYS_CLK_PERIOD;    //复位时间:5个时钟周期

	//波特率参数
  	parameter BAUD_RATE = 115200; 	//串口波特率
	parameter BAUD_RATE_PERIOD	= 1_000_000_000/BAUD_RATE;
	//波特率周期,0.104ms = 104us,1/9600 s = 1^9 /9600 ns = 4167 sim_clk
	//波特率周期, 1/115200 = 8680 ns  =  8.7us = 347 sim_clk

	//波特率+时钟参数
    parameter [15:0]  BPS_NUM = SYS_CLK_FRE / BAUD_RATE; //时钟/波特率,用时钟周期构造波特率周期
	//  BPS_NUM = 40_000_000/115200 = 347.22 = 16'd347
    //  1 bit位宽所需时钟周期的个数。最长的波特率计数,10417,二进制有14位,取16位
	//  parameter BPS_4800: 40MHz set 8333 ; 50MHz set 10417
	//  parameter BPS_9600: 40MHz set 4167 ; 50MHz set 5208
	//  parameter BPS_115200: 40MHz set 347; 50MHz set 434

//==========================================================================
//模拟:信号的输入,显示输出结果
//==========================================================================
	//模拟系统时钟:40MHz,25ns
	always #((SYS_CLK_PERIOD+1)/2-1) sim_clk = ~sim_clk; //延时,电平翻转
	
	initial	begin
		//模拟复位信号:拉低一次
		#0;
			sim_clk = 1'b0;
			sim_rst_n = 1'b0;      //复位拉低,有效,
			
			uart_rx  = 1'b1;		//串口线,默认高,起始拉低
			//rx_data <= `UD 8'h00;		//rx_data 初始化,在 uart_rx中完成
			tx_pulse = 1'b0;		//触发发送,高有效,先拉低
			tx_data  = 8'h00;		//数据默认为0		
			
		//#RST_TIME;			   //延时:保持足够长时间(至少5个clk)
		#BAUD_RATE_PERIOD;		   //5个clk时间轴太短,仿真改为1个BPS,更明显
			sim_rst_n = 1'b1;      //解除复位
		
		//==========================================================================
		//模拟串口接收:串行信号输入,转化成并行数据,并显示
		//==========================================================================
			uart_rx = 1'b1;	   //串口发送线,默认拉高
		repeat( BPS_NUM*1 ) @(posedge sim_clk);	    //循环347个时钟周期,即一个波特率周期
		//#BAUD_RATE_PERIOD; 						//直接延时,一个波特率周期
		
		$display("Initialization complete. BAUD_RATE is %d",BAUD_RATE); //命令行显示初始化完成,输出BAUD_RATE
		
		//串口:起始位
			uart_rx = 1'b0;	
		#BAUD_RATE_PERIOD;					

		//串行数据,一位一位送入接收信号线:***从位0到位7***,依次发送
		//测试数据为8'hD8=8'b1101_1000
			uart_rx = 1'b0;		
		#BAUD_RATE_PERIOD; 
			uart_rx = 1'b0;		
		#BAUD_RATE_PERIOD; 
			uart_rx = 1'b0;		
		#BAUD_RATE_PERIOD; 		
			uart_rx = 1'b1;		
		#BAUD_RATE_PERIOD; 
			uart_rx = 1'b1;		
		#BAUD_RATE_PERIOD; 
			uart_rx = 1'b0;		
		#BAUD_RATE_PERIOD; 
			uart_rx = 1'b1;		
		#BAUD_RATE_PERIOD; 
			uart_rx = 1'b1;		
		#BAUD_RATE_PERIOD; 		
		$display("The uart_rx 8'hD8 = 8'b1101_1000 has been sent.");  //命令行显示:串口信号线数据已发送

		//串口:结束位
			uart_rx = 1'b1;	
		#BAUD_RATE_PERIOD;
			$display("The uart_rx has received. rx_data = 8'h%h",rx_data);  
		//命令行显示:串口信号线接收已结束,显示接收到的数据
		
		//==========================================================================
		//模拟串口发送:并行数据,串行输出
		//==========================================================================		
		//***串口接收模块收到的数据,传递给串口输出模块***
		
		repeat( BPS_NUM*1 ) @(posedge sim_clk);	  //循环347个时钟周期,即一个波特率周期
		//#BAUD_RATE_PERIOD; 		//直接延时,一个波特率周期		
		
		//传递 第一组数据:8位并行数据,一次性送入串口发送模块
		 tx_data = rx_data;	//串口接收数据,传给串口发送
		#BAUD_RATE_PERIOD;
		
		//开启触发信号:串口发送
		//tx_pulse = 1;				//用 rx_en 代替 模拟tx_pulse,直接触发
		#BAUD_RATE_PERIOD;			//rx_en 串口接收数据有效,接收完成拉高1个BPS
		
		//结束触发:串口发送
		//tx_pulse = 0;
		#BAUD_RATE_PERIOD;
		
		repeat( BPS_NUM*9 ) @(posedge sim_clk);	//发送数据,等待8个波特率周期
			$display("The first tx_data 8'h%h has been sent.",tx_data);  //命令行显示:第1组数据发送完
		
		#BAUD_RATE_PERIOD;	
			$stop;		//结束仿真
		
	end

//==========================================================================
//调用top模块
//==========================================================================
    //串口发送
    uart_rx #(
         //.CLK_SYS   (  SYS_CLK_FRE), //系统时钟
         .BPS_NUM (  BPS_NUM  )  // 时钟/波特率,1 bit位宽所需时钟周期的个数
     )
     u_uart_rx(
        .clk      (  sim_clk  ),// input       clk,
		//.rst_n	  (  sim_rst_n ),// input 
		.uart_rx  (  uart_rx  ),// input reg  串口接收信号线
		
        .rx_data  (  rx_data  ),// output  接收到的数据
        .rx_finish(  rx_finish)// output  串口接收数据有效,接收完成拉高1个BPS
        //.rx_end   (  rx_end   ) // output  //接收到停止位,拉高1个clk,没啥用
    );
	
	//串口发送
    uart_tx #(
         //.CLK_SYS   (  SYS_CLK_FRE), //系统时钟
         .BPS_NUM (  BPS_NUM  )  // 时钟/波特率,用时钟周期构造波特率周期
     )
     u_uart_tx(
        .clk      (  sim_clk  ),// input       clk,
        .tx_data  (  tx_data  ),// input [7:0] tx_data,
        .tx_pulse (  rx_finish),// input       外部输入,开始产生数据->开启串口发送状态

        .uart_tx  (  uart_tx  ),// output reg  uart_tx,
        .tx_busy  (  tx_busy  ),  // output      输出,串口接收忙状态
		.tx_finish(  tx_finish) // output      //串口发送数据结束标志,8位数据发完,拉高一个BPS
    );

endmodule

3、仿真结果

ModelSim波形
[外链图片转存中...(img-RJwbdc2Q-1592206711752)]

命令行显示
[外链图片转存中...(img-Phr8ckGc-1592206711759)]

增加 tx_finish 和 rx_finish
[外链图片转存中...(img-9MiYxW4g-1592206711764)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值