当前位置:   article > 正文

FPGA串口收发(四):接收数据并转发,间隔时间发送_fpga串口发送字符串

fpga串口发送字符串

FPGA串口收发(四):接收数据并转发,间隔时间发送

// Description: 串口收发:串口接收数据,内部生成数据,串口间隔特定时间发送数据

// 串口接收数据:串行信号线 1101_1000 ,转为并行数据,取反截取低4位 传递给led,再传递给data_gen,

// 发送数据: 0.1ms生成/发送一位数据,发送字符串"==HELLO WORLD=" (对应ASCII码),以及led值

1、源文件

uart_rx.v

uart_tx.v

uart_data_gen.v

uart_top.v

uart_data_gen.v

`timescale 1ns / 1ps
//
// Company: Myminieye
// Engineer: Nill
//
// Create Date: 2019-08-20 14:36
// Design Name:
// Module Name: uart_data_gen
// Project Name:
// Target Devices:
// Tool Versions:
// Description: 产生的数据,用于串口发送
// 字符串"====HELLO WORLD==="
// 每秒1s产生一个字符,有可能再加上串口接收的数据( write_max_num 比8'h14 大时)
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
`define UD #1

module uart_data_gen #(
    parameter CLK_CNT_1S = 26'h0FA0    //定义参数,计数次数
    //晶振40MHz,1s需要计数的 40M次 = 40*10^6 = 0x2625A00
    //parameter clk_cnt = 26'h2625A00;
)
(
    input               clk,
    input               rst_n,
    input      [7:0]    read_data,
    input               tx_busy,
    input      [7:0]    write_max_num,  //字符串长度,发送的最大字符数 8'h14(20个)

    output reg [7:0]    write_data,		//生成的数据,传出给到串口发送模块 uart_tx
    output reg          write_en		//开始生成数据,传递给uart_tx模块,开启串口发送状态tx_en
);

//==========================================================================
//wire and reg  定义:信号与参数
//==========================================================================

    reg [25:0] time_cnt=0;  //计数次数,记到26'h2625A00
    reg [ 7:0] data_num;    //8位数字,位数

    // 设置串口发射工作区间
    reg  work_en=0;
    reg  work_en_1d=0;

//==========================================================================
//内部信号触发,生成数据使能 work_en :1s计时, 每秒产生一个字符
//==========================================================================

    //计数递增,与计数截止的if分开
    always @(posedge clk)
    begin
        time_cnt <= `UD time_cnt + 26'd1;
    end

	//============ work_en使能,开始生成数据:内部计时1s, ============
    //计数时间到,work_en生成数据使能,一个字符串/每秒
    always @(posedge clk)
    begin
        if(time_cnt == CLK_CNT_1S)    //计数到1s
        //if(time_cnt == 5'd2048)
            work_en <= `UD 1'b1;    //开始生成数据
        else if(data_num == write_max_num-1'b1)//第19个字符
            work_en <= `UD 1'b0;    //生成数据结束
    end

	//生成数据使能,打一拍:work_en_1d比work_en,慢一拍
    //计时刚到1s,work_en为1,work_en_1d为0
    always @(posedge clk)
    begin
        work_en_1d <= `UD work_en;
    end

//==========================================================================
//外部信号触发:串口发送模块接触忙碌,获取tx_busy的下降沿
//==========================================================================	
	
	//===========发送寄存器,输入状态 tx_busy_f :忙->空闲============
    //获取tx_busy的下降沿,从忙变成不忙:1变成0
    reg tx_busy_reg = 0;
    wire tx_busy_f;
    //发送忙状态,打一拍
    always @ (posedge clk)
        tx_busy_reg <= `UD tx_busy;
    //tx_busy_f,下降沿fall
    assign tx_busy_f = (!tx_busy) && (tx_busy_reg);

//==========================================================================
//内部信号和外部信号,综合触发
//1、内部状态,触发产生数据动作:write_pluse 高有效,每秒产生一个字符
//2、外部状态,write_pluse -> write_en -> 输出,触发串口发送
//==========================================================================	
	
	//===============触发信号:产生数据 &  发送数据==================
	/* 
		@功能1:   计时刚到1s,可以发送,字符串的下一个数据,给出触发信号
				 (若发送状态机没走完,还是忙,等走完再发送)
		@数据流1: work_en + work_en_1d -> write_pulse(data_gen) -> write_en(data_gen) -> tx_en(top) -> tx_pulse(uart_tx)
		@功能2:  (计时1s多)解除忙状态,执行发送,字符串的下一个数据,给出触发信号
		@数据流2: tx_busy -> tx_busy_f -> write_pulse(data_gen) -> write_en(data_gen) -> tx_en(top) -> tx_pulse(uart_tx)
		@功能3:    1s刚到,此时发送也解除了忙,执行发送,给出触发信号
	*/
    //========1、 触发产生数据动作:write_pluse 高有效=======
	
    reg write_pluse;
    always @ (posedge clk)
    begin
        if(!rst_n)
            write_pluse <= `UD 1'b0;
        else if(work_en)  //此时,计时到了1s
        begin
            if(~work_en_1d || tx_busy_f)
             //1、work_en_1d=0,刚到1s(上一刻还没计数完,还是0),每1s发送
             //2、tx_busy_f=1,早就到了1s,而且刚解除发送忙(下降沿)。 -> 相当于发送模块这8位发完了,传出tx_busy不忙,进入data_gen,又返回发送模块,触发下一组8位发送
                write_pluse <= `UD 1'b1;
            else
                write_pluse <= `UD 1'b0;
            /*// 把 或关系||拆开,换个写法
            if(~work_en_1d)
                write_pluse <= `UD 1'b1;
            else if ( tx_busy_f)
                write_pluse <= `UD 1'b1;
            else
                write_pluse <= `UD 1'b0;
             */
        end
        else
            write_pluse <= `UD 1'b0;
    end

    //==========2、开始生成数据状态 write_en,高有效,输出 ========
    //打一拍,作为发送触发,反馈给输出模块
    always @(posedge clk)
    begin
        write_en <= `UD write_pluse;	//write_en比 write_pluse 慢一拍
    end

	//=================产生数据1:数据位递增======================
    // 
    always @ (posedge clk)
    begin
        if 		( !rst_n )
            data_num    <= `UD 8'h0;
        else if ( ~work_en & tx_busy_f )
        //从0开始发送新的字符串:字符串(20个字符)发完了,并且发送状态刚解除忙(下降沿)
            data_num   <= 8'h0;  //源代码为 7'h0?
        else if ( write_pluse )
        //此字符串,发送下一个字符:计时刚到1s,或者1s多了解除了发送忙状态
            data_num   <= data_num + 8'h1;
    end

	//================== 产生数据2:向外送出字符串   "====HELLO WORLD==="
    //  字符的对应ASCII码
    // H:0x48      E:0x45     L:0x4C    O:0x4F   W:0x57    R:0x52    D:0x44
    always @ (posedge clk)
    begin
        case(data_num)
            8'h0  ,
            8'h1  ,
            8'h2  ,
            8'h3  : write_data <= `UD 8'h3D;// ASCII code is =
            8'h4  : write_data <= `UD 8'h48;// ASCII code is H
            8'h5  : write_data <= `UD 8'h45;// ASCII code is E
            8'h6  : write_data <= `UD 8'h4C;// ASCII code is L
            8'h7  : write_data <= `UD 8'h4C;// ASCII code is L
            8'h8  : write_data <= `UD 8'h4F;// ASCII code is 0
            8'h9  : write_data <= `UD 8'h20;// ASCII code is 
            8'ha  : write_data <= `UD 8'h57;// ASCII code is W
            8'hb  : write_data <= `UD 8'h4F;// ASCII code is O
            8'hc  : write_data <= `UD 8'h52;// ASCII code is R
            8'hd  : write_data <= `UD 8'h4C;// ASCII code is L
            8'he  : write_data <= `UD 8'h44;// ASCII code is D
            8'hf  ,
            8'h10 ,
            8'h11 : write_data <= `UD 8'h3D;// ASCII code is =
            8'h12 : write_data <= `UD 8'h0d;//回车
            8'h13 : write_data <= `UD 8'h0a;//换行
            default: write_data <= `UD  read_data;//默认态,数字保持不变,输入数据转发出去
            //在top模块中修改 write_max_num,比8'h14 大时,可以把串口接收的数据(给到led)再发出去
        endcase
    end

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188

uart_top.v

`timescale 1ns / 1ps
//
// Company: Myminieye
// Engineer: Nill
//
// Create Date: 2019-08-20 14:36
// Design Name:
// Module Name: uart
// Project Name:
// Target Devices:
// Tool Versions:
// Description: 串口收发数据
// 串口接收的数据,取反,点亮LED灯:
//                高电平点亮, 发送数据为 0xF0 或者 11110000
// 串口发送的数据,由data_gen生成,发送字符串"====HELLO WORLD===",每秒发一个字符,加换行回车共计19个
//                若 write_max_num比8'h14大,可以把串口接收的数据(给到led)再发出去
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//


`define UD #1

module uart_top #(
   parameter   BPS_NUM =  16'd347,  	// 时钟/波特率,1 bit位宽所需时钟周期的个数
                CLK_CNT_1S = 16'h0FA0	//1s发一次,40M次 = 40*10^6 = 0x2625A00
                //0.1ms一次, 40M*10^(-4) = 40*10^6*10^(-4) = 40*100=4000
				
	//  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
)
(
    //input ports
    input clk,
	input rst_n,
    input uart_rx,

    //output ports
    output  [3:0] led,
	output	uart_tx,
	
	//仿真追加:传递以下变量
	output [7:0]    rx_data,	//串口接收的数据
	output			rx_finish,  //串口接收数据有效,接收完成拉高1个BPS
	output [7:0]    tx_data,	//产生的数据(含接收的数据)
	output 			tx_finish  //串口发送数据结束标志,8位数据发完,拉高一个BPS

);

//LED指示灯:BK12_W15,17,14,16 -> led[0],1,2,3(变量命名)-> LED4,3,2,1 (丝印从下到上)

//==========================================================================
//wire and reg 定义:信号与参数
//==========================================================================
    wire   tx_busy;         //transmitter is free.
    wire   tx_en;           //开启串口发送,整个发送周期都拉高
	
	wire [7:0]  write_data;
	assign tx_data = write_data;
	
    reg [7:0]   write_max_num = 8'h15;//发送字符串位数,20位
    //在top模块中修改 write_max_num,比8'h14 大时,可以把串口接收的数据(给到led)再发出去

    reg [7:0] receive_data;

    always @(posedge clk)
        receive_data <= led ;

//==========================================================================
//调用top模块
//==========================================================================
	//产生数据,1s一个
    uart_data_gen #(
        .CLK_CNT_1S  (  CLK_CNT_1S  )
    )
    u_uart_data_gen(
        .clk          (  clk          ),//input             clk,
        .rst_n        (  rst_n        ),//input             rst_n,
        .read_data    (  receive_data ),//input      [7:0]  read_data,
        .tx_busy      (  tx_busy      ),//input             输入,串口发送忙状态
        .write_max_num(  write_max_num),//input      [7:0]  write_max_num,
		
        .write_data   (  write_data      ),//output reg [7:0]  生成的数据
        .write_en     (  tx_en        ) //output reg        输出,当前为生成数据状态
    );

    //串口发送
    uart_tx #(
         //.CLK_SYS   (  SYS_CLK_FRE), //系统时钟
         .BPS_NUM (  BPS_NUM  )  // 时钟/波特率,1 bit位宽所需时钟周期的个数
     )
     u_uart_tx(
        .clk      (  clk      ),// input       clk,
        .tx_data  (  tx_data  ),// input [7:0] tx_data,
        .tx_pulse (  tx_en    ),// input       外部输入,开始产生数据->开启串口发送状态 
		
        .uart_tx  (  uart_tx  ),// output reg  uart_tx,
        .tx_busy  (  tx_busy  ), // output      输出,串口接收忙状态
		.tx_finish(  tx_finish) // output      //串口发送数据结束标志,8位数据发完,拉高一个BPS
    );

    //串口接收
    uart_rx #(
         //.CLK_SYS   (  SYS_CLK_FRE), //系统时钟
         .BPS_NUM (  BPS_NUM  )  // 时钟/波特率,1 bit位宽所需时钟周期的个数
     )
     u_uart_rx (
        .clk       (  clk         ),// input             clk,
        .uart_rx   (  uart_rx     ),// input             uart_rx,
		
        .rx_data   (  rx_data     ),// output reg [7:0]  rx_data,
        .rx_finish (  rx_finish   ) // output  串口接收数据有效,接收完成拉高1个BPS
        //.rx_end   (  rx_end     ) // output  //接收到停止位,拉高1个clk,没啥用
    );

    assign led = ~rx_data;//8位数据截断高4位,只剩下低4位

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123

2、仿真文件 testbench

tb_uart_top.v

`timescale 1ns / 1ps

//SimulationCode:Test Bench/
// Company:
// Engineer:
//
// Create Date: 2020/05/21
// Design Name:
// Module Name: tb_uart_top
// Project Name: 串口收发的测试文件
// Target Devices:
// Tool Versions:
// Description: 串口收发:串口接收数据,内部生成数据,串口间隔特定时间发送数据
// 串口接收数据:串行信号线 1101_1000 ,转为并行数据,取反截取低4位 传递给led,再传递给data_gen,
// 发送数据: 0.1ms生成/发送一位数据,发送字符串"====HELLO WORLD===" (对应ASCII码),以及led值 
// Dependencies:
//  仿真周期 run 3ms
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
`define UD #1

module uart_top_tb;

//==========================================================================
//定义:信号与参数
//==========================================================================

	reg        sim_clk;		    //模拟时钟信号
	//reg      tx_pulse;        // active posedge
	reg 	   sim_rst_n;
	
	// input to rx module
	reg        sim_uart_rx;		//串口发送信号线
	//output from rx module
	wire [3:0] sim_led;		    //接收数据,取反,取低4位,传给led
	wire       sim_uart_tx;     //串口接收数据有效,接收完成拉高1个BPS
	
	//================================
	//仿真追加:将以下变量从下级模块中传出来
	// uart_rx/tx -> uart_top -> uart_top_tb
	//================================
	wire 	    rx_finish ;		//串口接收数据结束,接收完成拉高1个BPS
	reg			rx_finish_reg;
    wire    	tx_finish ;		//串口发送数据结束,8位数据发完,拉高一个BPS
	reg			tx_finish_reg;
	
	wire [7:0]  rx_data	 ;		//串口接收的数据(8位)
	wire [7:0]  tx_data	 ;		//串口发送的数据(生成的字符串 + 接收的8位数据)     

	
	//时钟参数
	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
	
	//串口发送数据的周期
	parameter CLK_CNT_1S = 16'h0FA0; //仿真改为:0.1ms一次, 40M*10^(-4) = 40*10^6*10^(-4) =4000 = 0xFA0
	//实际:1s发一次,40M次 = 40*10^6 = 0x2625A00 //CLK_CNT_1S = 26'h2625A00

//==========================================================================
//logic:逻辑信号初始化与判断
//==========================================================================
	//模拟系统时钟:40MHz,25ns
	always #((SYS_CLK_PERIOD+1)/2-1) sim_clk = ~sim_clk; //延时,电平翻转

	//若以rx_finish/tx_finish 触发,则rx_data/tx_data还是上一刻的数据
	//打一拍,延迟,rx_data/tx_data数值已改变
	always @(posedge sim_clk) begin		
		rx_finish_reg <= `UD rx_finish;
		tx_finish_reg <= `UD tx_finish;
	end
	
	always @(posedge rx_finish_reg) 
		$display("Note 2 :The rx_data 8'h%h has received.",rx_data); //命令行显示:rx_data

	always @(posedge tx_finish_reg) 
		$display("Note 4 :The rx_data 8'h%h has received.",tx_data); //命令行显示:tx_data

/*		
	always @(posedge sim_clk) begin
		if(tx_finish_reg && ~tx_finish) begin	//接收数据完成(触发1次)
			sim_tx_data <= `UD tx_data;
			$display("Note 4 :The tx_data 8'h%h has been sent.",sim_tx_data);  //命令行显示:tx_data
		end
	end
*/

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

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

		//串口:结束位
			sim_uart_rx = 1'b1;	
		#BAUD_RATE_PERIOD;
			$display("Note 3 :*** The led data 8'h%h has received.",sim_led);  //命令行显示:sim_led
		//命令行显示:串口信号线接收已结束,显示接收到的数据

		//==========================================================================
		//模拟串口发送:并行数据,串行输出
		//==========================================================================		
		//*** data_gen模块生成字符串,以及串口接收的数据,依次从串口输出***
		
		repeat( BPS_NUM*1 ) @(posedge sim_clk);	  //循环347个时钟周期,即一个波特率周期
		//#BAUD_RATE_PERIOD; 		//直接延时,一个波特率周期	

		//传递 第一组数据:8位并行数据,一次性送入串口发送模块
		//sim_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;
		
		//0.1ms发一次数据,20位有2ms = 250个 BPS
		repeat( BPS_NUM*250 ) @(posedge sim_clk);//等待发送数据完成(触发20次)
			$stop;		//结束仿真		
	end
	//initial
	
//==========================================================================
//调用top模块
//==========================================================================
	uart_top #(
		.BPS_NUM (  BPS_NUM  ),			// 时钟/波特率,1 bit位宽所需时钟周期的个数
		.CLK_CNT_1S	( CLK_CNT_1S   ) 	//串口发送数据的周期
	)
	sim_uart_top(
		.clk	 (sim_clk),
		.rst_n	 (sim_rst_n),
		.uart_rx (sim_uart_rx),
		.led	 (sim_led),
		.uart_tx (sim_uart_tx),
		
		//仿真追加:将以下变量从下级模块中传出来
		// uart_rx/tx -> uart_top -> uart_top_tb
		.rx_data  (rx_data  ),
		.rx_finish(rx_finish),
		.tx_data  (tx_data  ),
		.tx_finish(tx_finish)		
	);

endmodule
//module uart_top_tb

//循环移位发送数据
/*
	parameter uart_rx_data = 
	
		initial begin
		//模拟复位信号:一次,低电平5个clk
		#0;
			sim_clk = 1'b0;
			sim_rst_n = 1'b0;      //复位拉低,有效,
			sim_uart_rx = 1'b1;	   //串口发送线,默认拉高
		#RST_TIME;			  	   //延时:保持足够长时间(5个clk)
			sim_rst_n = 1'b1;      //解除复位

		repeat( 10 ) begin
			//串口起始信号:高电平到低电平(下降沿)
			#BAUD_RATE_PERIOD;
				sim_uart_rx  = 1'b1;	//时间延迟BPS_CNT ns, 检查`timescale 1 ns/ 1 ps
			#BAUD_RATE_PERIOD;
				sim_uart_rx  = 1'b0;

			repeat(12560) @(posedge sim_clk);
		end
	end
	
	//串口数据信号:从第0位到第7位, 第8位停止位
	always @(posedge data_clk) begin
		if( cnt == 4'h8 ) begin
			cnt <= 1'b0;
			sim_uart_rx  = 1'b1;      //第8位后,停止位也为1
			$display("Running testbench:Pass");  //在命令行显示pass这串字符。
		end
		else begin
			cnt <= cnt +1'b1;
			sim_uart_rx <= uart_rx_data[cnt];
		end
	end
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249

3、仿真结果

ModelSim波形

[外链图片转存中...(img-s4eK7rrm-1592207036203)]

忘了标记,接收数据取反,截取,最后一位 07,也输出了

命令行:

[外链图片转存中...(img-OS2wotHY-1592207036236)]

生成数据代码对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nE8iHg67-1592207036244)(file:///C:\Users\Nomil\AppData\Local\Temp\msohtmlclip1\01\clip_image003.png)]

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/516592
推荐阅读
相关标签
  

闽ICP备14008679号