基于FPGA实现uart串口模块(Verilog)--------发送模块及整合

基于FPGA实现uart串口模块(Verilog)--------发送模块及整合

当接收模块接收到数据后,需要重新发送形成回环验证模块正确性。思路和结束模块有一点点的小差异。接收模块最终输出的是一个并行的八位数据,所以只有在最后输出保证输出结果正确就可以,而发送模块必须按照波特率时钟发送每一位的数据。具体代码实现如下

代码实现

module uart_tx(
	//-----------input 
	clk,rst_n,pi_data,pi_flag,
	//-----------output 
	tx_data
    );
input clk;
input rst_n;
input [7:0] pi_data;
input pi_flag;
output tx_data;
parameter 	idle  = 2'd0,
			start = 2'd1,
			work  = 2'd2,
			stop  = 2'd3;
//------------------------------
localparam baud_cnt_end = 5207						;
localparam baud_cnt_m 	= (baud_cnt_end + 1) / 2 - 1;
//------------------------------
//------------------------------
reg pi_flag1;
reg pi_flag2;
reg tx_flag;
reg [12:0] baud_cnt;
reg [3:0] bit_cnt;
reg tx_data;
reg [1:0] current_state;
reg [1:0] next_state;
always@(posedge clk )
begin
	pi_flag1 <= pi_flag;
	pi_flag2 <= pi_flag1;
end
//------------------------------
//第一个进程,同步时序always块,形式固定
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		current_state <= idle;
	else 
		current_state <= next_state;
end
//第二个always,组合逻辑模块,描述状态迁移条件判断
always@(*)
begin
	case(current_state)
	idle:
		begin
			tx_flag = 1'b0;
			begin
				if(pi_flag2)
					next_state = start;
				else
					next_state = idle;
			end
		end
    start:
    	begin
    		tx_flag = 1'b1;
			begin
				if(bit_cnt == 4'd1)
					next_state = work;
				else
					next_state = start;
			end
    	end
	work:
		begin
			tx_flag = 1'b1;
			begin
				if(bit_cnt == 4'd9)
					next_state = stop;
				else
					next_state = work;
			end
		end
	stop:
		begin
			tx_flag = 1'b1;
			begin
				if(bit_cnt == 4'd10)
					next_state = idle;
				else
					next_state = stop;
			end
		end
	default:
		begin
			next_state = idle;
		end
	endcase
end
//第三个进程,描述输出,同步时序always块
//reg [3:0] bit_cnt;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		bit_cnt <= 4'd0;
	else 
		if(!tx_flag)
			bit_cnt <= 4'd0;
		else 
			if(baud_cnt == baud_cnt_end)
				bit_cnt <= bit_cnt + 1'b1;
end
//reg [12:0] baud_cnt;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		baud_cnt <= 13'd0;	
	else 
		if(baud_cnt == baud_cnt_end)
			baud_cnt <= 13'd0;
		else 
			if(tx_flag)
				baud_cnt <= baud_cnt + 1'b1;
			else 
				baud_cnt <= 13'd0;
end
reg [7:0] pi_data_r;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		pi_data_r <= 8'd0;
	else 
		if(pi_flag)
			pi_data_r <= pi_data;
		else 
			pi_data_r <= pi_data_r;
end 
//define tx_data
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		tx_data <= 1'b1;
	else 
		if(tx_flag)
			case(bit_cnt)
				4'd0 : tx_data <= 1'b0			;
				4'd1 : tx_data <= pi_data_r[0]	;
				4'd2 : tx_data <= pi_data_r[1]	;
				4'd3 : tx_data <= pi_data_r[2]	;
				4'd4 : tx_data <= pi_data_r[3]	;
				4'd5 : tx_data <= pi_data_r[4]	;
				4'd6 : tx_data <= pi_data_r[5]	;
				4'd7 : tx_data <= pi_data_r[6]	;
				4'd8 : tx_data <= pi_data_r[7]	;
				4'd9 : tx_data <= 1'b1			;
				default:;
			endcase
		else 
			tx_data <= 1'b1;
end

endmodule

顶层文件(模块整合)

module top_uart(
	input 	clk		,
	input 	rst_n	,
	input 	rx_data	,
	output 	tx_data
    );
wire [7:0] data;
wire flag;
uart_tx A(
	.clk				(clk	),
	.rst_n				(rst_n	),
	.pi_data 			(data   ),
	.pi_flag			(flag   ),
	.tx_data			(tx_data)
    );
uart_rx B(
	.clk				(clk	),
	.rst_n				(rst_n	),
	.rx_data			(rx_data),
	.po_data			(data   ),
	.po_flag			(flag   )
    );
endmodule

仿真代码

module tb_fsm;

	// Inputs
	reg clk;
	reg rst_n;
	reg rx_data;

	// Outputs
	wire tx_data;

	// Instantiate the Unit Under Test (UUT)
	top_uart uut (
		.clk(clk), 
		.rst_n(rst_n), 
		.rx_data(rx_data), 
		.tx_data(tx_data)
	);
always #10 clk = ~clk;
	initial begin
		// Initialize Inputs
		clk = 0;
		rst_n = 0;
		rx_data = 1;

		// Wait 100 ns for global reset to finish
		#100;
        rst_n = 1;
        #104140;
        rx_data = 1;
        #104140;
        rx_data = 1;
        #104140;
        rx_data = 1;
        #104140;
        rx_data = 1;
        #104140;
        rx_data = 1;
        #104140;
        rx_data = 0;//start
        #104140;
        rx_data = 0;//1
        #104140;
        rx_data = 1;//2
        #104140;
        rx_data = 0;//3
        #104140;
        rx_data = 1;//4
        #104140;
        rx_data = 0;//5
        #104140;
        rx_data = 1;//6
        #104140;
        rx_data = 0;//7
        #104140;
        rx_data = 1;//8
        #104140;
        rx_data = 1;
        #104140;
        rx_data = 1;
        #104140;
        rx_data = 1;
        #104140;
        rx_data = 1;
        #104140;
        rx_data = 1;
        #104140;
        rx_data = 0;
        #104140;
        rx_data = 1;//1
        #104140;
        rx_data = 0;
        #104140;
        rx_data = 1;
        #104140;
        rx_data = 0;//4
        #104140;
        rx_data = 1;
        #104140;
        rx_data = 0;
        #104140;
        rx_data = 1;
        #104140;
        rx_data = 0;//8
        #104140;
        rx_data = 1;
        #104140;
        rx_data = 1;
        #104140;
        rx_data = 1;
       
		// Add stimulus here

	end
      
endmodule

反思小结

对于uart,发送和接收应该是人机交互的一个方式,通过发送的字符控制内部等等其他东西。对于模块不理解的可以回头看看仿真图,对图中的各个时序进行理解。

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值