基于fpga实现uart串口通信

设计一个数据发送器,以每100ms以115200的波特率发送一个数据,每次发送的数据比前一个数据大一(计数器发01234……)

顶层测试发送模块

`timescale 1ns / 1ns
module uart_tx_test(
   Clk,
   Reset_n,
   uart_tx
);

    input Clk;
    input Reset_n;
    output uart_tx;
    reg Send_Go;
    reg [7:0]Data;

    uart_byte_tx uart_byte_tx(
        .Clk(Clk),
        .Reset_n(Reset_n),
        .Data(Data),
        .Baud_set(3'd4),
        .uart_tx(uart_tx),
        .Tx_Done(Tx_Done),
        .Send_Go(Send_Go)
);

    reg [24:0]counter;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter <= 0;
    else if(counter == 4999999)//100ms
        counter <= 0;
    else
        counter <= counter + 1;
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        Send_Go <= 0; 
    else if(counter == 1)
        Send_Go <= 1;
    else 
        Send_Go <= 0; 
       
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)    
        Data <= 0;
    else if(Tx_Done)
        Data <= Data +1'b1;     
endmodule

调用发送数据模块

module uart_byte_tx(
    Clk,
    Reset_n,
    Data,
    Baud_set,
    uart_tx,
    Tx_Done,
    Send_Go
    );
    
    input [7:0]Data;
    input Clk;
    input Reset_n;
    input Send_Go;
    input [2:0]Baud_set;
    output reg uart_tx;
    output reg Tx_Done;
	 
	//Baud_set = 0 波特率 = 9600;
	//Baud_set = 1 波特率 = 19200;
	//Baud_set = 2 波特率 = 38400;
	//Baud_set = 3 波特率 = 57600;
	//Baud_set = 4 波特率 = 115200;
	reg [17:0]bps_DR;
	always@(*)
		case(Baud_set)
		0:bps_DR = 1000000000/9600/20;
		1:bps_DR = 1000000000/9600/20/2;
		2:bps_DR = 1000000000/9600/20/4;
		3:bps_DR = 1000000000/9600/20/6;
		4:bps_DR = 1000000000/9600/20/12;
		default:bps_DR = 1000000000/9600/20;
		endcase
		
	reg Send_en;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        Send_en <= 0; 
    else if(Send_Go)
        Send_en <= 1;
    else if(Tx_Done)
        Send_en <= 0; 
        
    reg [7:0]r_Data;
    always@(posedge Clk)
    if(Send_Go)
        r_Data <= Data;
    else
        r_Data <= r_Data;
        
    wire bps_clk;
    assign bps_clk = (dive_cnt == 1);//真正的波特率时钟,只在dive_cnt为1时为高电平
    
    reg [17:0]dive_cnt;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        dive_cnt <= 0;
	else if(Send_en)begin
		if(dive_cnt == bps_DR - 1)
			dive_cnt <= 0;
		else
			dive_cnt <= dive_cnt +1'b1;
	                end
	else
		dive_cnt <= 0;
	
		
    reg [3:0]bps_cnt;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        bps_cnt <= 0;
	else if(Send_en)begin
        if(bps_clk)begin
            if(bps_cnt == 11)
                bps_cnt <= 0;
            else
                bps_cnt <= bps_cnt +1'b1; 
                                  end
                    end
    else
        bps_cnt <= 0;     
        
	always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)begin
		uart_tx <= 1'b1;
		//Tx_Done <= 0;
		end
	else begin
		case(bps_cnt)

			1:uart_tx <= 0;
			2:uart_tx <= r_Data[0];
			3:uart_tx <= r_Data[1];
			4:uart_tx <= r_Data[2];
			5:uart_tx <= r_Data[3];
			6:uart_tx <= r_Data[4];
			7:uart_tx <= r_Data[5];
			8:uart_tx <= r_Data[6];
			9:uart_tx <= r_Data[7];
			10:uart_tx <= 1;
			11:uart_tx <= 1;
			default:uart_tx <= 1;
		endcase
	end
	
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
		Tx_Done <= 0;
    else if((bps_clk == 1) && (bps_cnt == 10))
		Tx_Done <= 1;   
	else 
	    Tx_Done <= 0;   
	
	
endmodule

测试模块仿真tb

`timescale 1ns / 1ns
module uart_tx_test_tb();
    reg Clk;
    reg Reset_n;
    wire uart_tx;    
    
    uart_tx_test uart_tx_test(
       .Clk(Clk),
       .Reset_n(Reset_n),
       .uart_tx(uart_tx)
);

    initial Clk = 1;
    always#10 Clk = ~Clk;    
    
    initial begin
        Reset_n = 0;
        #201;
        Reset_n = 1;
        #50000000;      
    end
    
endmodule

 

 串口助手显示

 

一开始串口助手接受的数据全是00,但是时序仿真没有问题,历经了调低波特率,调低数据位都没有用,最后偶然间看到串口发送模块的86行与106行最后一个always块中Tx_Done重复赋值,将86行的Tx_Done赋值语句删掉or注释掉之后能够实现串口发送。

PS:开发板使用的小梅哥AX720,文章仅用于分享记录学习过程。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值