FPGA学习之七:UART串口发送

一、设计思路

模块框图:

 div_cnt:产生波特率时钟

bps_cnt:对波特率时钟进行计数


 二、设计目标 

实现8位数据的传输,数据由外部输入。

三、UART.v文件设计

module UART(
    send_en,
	data_byte,
	baud_set,
	clk,
	reset_n,
	uart_tx,
	tx_done,
	uart_state
    );
	input send_en;
	input [7:0]data_byte;
	input [2:0]baud_set;
	input clk;
	input reset_n;
	output reg uart_tx;
    output reg tx_done;
    output uart_state;	
	reg  [17:0]div_cnt;//定义一个基本计数器
	reg  [17:0]bps_DR;
	wire bps_clk;
	assign bps_clk =(div_cnt == 1);
	//根据不同的波特率设置基本计数器不同的最大值
	always@( posedge clk or negedge reset_n)begin
	if(!reset_n)
	     bps_DR <= 16'd5208;
	  else case(baud_set)
	    3'b000:bps_DR <= 16'd5208;
		3'b001:bps_DR <= 16'd2604;
		3'b010:bps_DR <= 16'd1302;
		3'b011:bps_DR <= 16'd868;
		3'b100:bps_DR <= 16'd434;
	        default:bps_DR <= 16'd5208;
	      endcase
		end
		
    //设置基本计数器,就是一个单元的计数器
	always@( posedge clk or negedge reset_n)begin
	if(!reset_n)
	   div_cnt <= 16'd0;
	   else if(send_en)begin
	               if(div_cnt == bps_DR-1)
	                    div_cnt <= 16'd0;
		            else 
		                div_cnt <= div_cnt+1'b1;
		end
        else
        	div_cnt <= 16'd0;	
	end
	   
	   reg [3:0]bps_cnt;
	   //相当于加入计数器2,当基本计数器满一次,bps_cnt开始计数一次,然后总共需要10个状态,因此需要四位
	   //(div_cnt == 1),之所以写成1,因为状态从0001开始变化,因此需要是0状态保持的时间短一点
	 always@( posedge clk or negedge reset_n)begin
	if(!reset_n)
	    bps_cnt <= 16'd0;
	else if(send_en)begin
		       if(div_cnt == 1)begin
		                if(bps_cnt == 4'b1011)
	                           bps_cnt <= 16'd0;
		                else
		                        bps_cnt <= bps_cnt+1'b1;
		                end
		            end
	else
		                 bps_cnt <= 16'd0;
		
	end
    //用bps_cnt的状态来对应输出,相当于多选一数据选择器
	always@( posedge clk or negedge reset_n)begin
	if(!reset_n)begin
	    uart_tx <= 1'b1;
	    tx_done <= 1'b0;
	    end
		else case(bps_cnt)
		4'b0001:begin uart_tx <= 1'b0; tx_done <= 1'b0;end
		4'b0010:uart_tx <= data_byte[0];
		4'b0011:uart_tx <= data_byte[1];
		4'b0100:uart_tx <= data_byte[2];
		4'b0101:uart_tx <= data_byte[3];
		4'b0110:uart_tx <= data_byte[4];
		4'b0111:uart_tx <= data_byte[5];
		4'b1000:uart_tx <= data_byte[6];
		4'b1001:uart_tx <= data_byte[7];
		4'b1010:uart_tx <= 1'b1;
		4'b1011:begin uart_tx <= 1'b1; tx_done <= 1'b1;end
		  default:uart_tx <= 1'b1;
		endcase	
	end
endmodule

四、UART_tb.v文件代码

`timescale 1ns / 1ns
module UART_tb;
     reg clk;
     reg send_en;
     reg [2:0]baud_set;
     reg reset_n;
     reg [7:0]data_byte;
     wire uart_tx;
     wire tx_done;
     wire uart_state;
     UART UART_tx(
    .send_en(send_en),
	.data_byte(data_byte),
	.baud_set(baud_set),
	.clk(clk),
	.reset_n(reset_n),
	.uart_tx(uart_tx),
	.tx_done(tx_done),
	.uart_state(uart_state)
    );
     initial clk=1;
	always #10 clk=~clk;
	initial begin
	 data_byte=0;
	 reset_n=0;
	 send_en=0;
	 baud_set=4'b0100;
	#201;
	#100;
	reset_n=~reset_n;
	data_byte=8'b1010_1101;
	send_en=1;
	#20;
	@(posedge tx_done);
	send_en=0;
	#20000;
	data_byte=8'b1110_1001;
	send_en=1;
	#20;
	@(posedge tx_done);
	send_en=0;
	#20000;
	$stop;
	end
endmodule



五、仿真波形

 由波形可知,数据从bps_cnt为1时开始传输,即开始传输起始位,此时send_en也为高电平,当停止位传输结束,send_en变成低电平,UART_tx此时在空闲状态变成高电平,同时波特率也对应设置的115200,传输数据正确。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值