uart_dpram:搭建串口收发与存储双口RAM简易应用系统

搭建串口收发与存储双口RAM简易应用系统

实验目的: 以模块化设计为基础利用已编写的串口收发模块、按键模块以及RAM的IP模块来设计一个简易应用系统。通过串口发送数据到FPGA中,FPGA接收到数据后将数据存储在双口RAM的一段连续空间中,当需要时,按下按键0,则FPGA将RAM中存储的数据通过串口发送出去。

00.功能模块:

1.串口接收模块:uart_tybe_rx.v
2.按键消抖模块:key_fliter.v
3.RAM模块:dpram.v
4.串口发送模块:uart_tybe_tx.v
5.控制模块:ctrl.v

01.原理图

uart_dpram:搭建串口收发与存储双口RAM简易应用系统_第1张图片

02.控制模块ctrl.v

module ctrl(
	Clk			,
	Rst_n		,
	key_flag 	,
	key_state	,
	rx_done		,
	tx_done		,
	
	
	wren		,
	rdaddress	,
	wraddress	,
	send_en		
);
	input 				Clk			;
	input				Rst_n		;
	input 				key_flag 	;
	input 				key_state	;
	input 				rx_done		;
	input 				tx_done		;
	
	output				wren			;
	output	[7:0]		rdaddress		;
	output	[7:0]		wraddress		;
	output 				send_en			;
	reg 		[7:0]		rdaddress	;
	reg 		[7:0]		wraddress	;
	
	//控制ram的写地址
	assign wren = rx_done;
	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		wraddress <= 8'd0;
	else if(wren)
		wraddress <= wraddress + 1'b1;
	else 
		wraddress <= wraddress;
		
	//通过按键控制读操作
	reg do_send;
	wire tx_done;
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		do_send <= 1'd0;
	else if(key_flag && !key_state)
		do_send <= ~do_send;
		
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		rdaddress <= 8'd0;
	else if(do_send && tx_done)
		rdaddress <= rdaddress + 8'd1;
	else 
		rdaddress <= rdaddress;
		
	//将send_en信号延迟两拍输出
	reg r0_send_done,r1_send_done;
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		r0_send_done <= 1'b0;
		r1_send_done <= 1'b0;
	end
	else begin
		r0_send_done <= (do_send && tx_done);
		r1_send_done <= r0_send_done;
	end
	
	
	//send_en
	reg send_en;
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		send_en <= 1'b0;
	else if(key_flag && !key_state)
		send_en <= 1'b1;
	else if(r1_send_done)
			send_en <= 1'b1;
	else 
			send_en <= 1'b0;
			
endmodule

03.uart_dpram.v

module uart_dpram(
	Clk				,
	Rst_n			,
	key_in			,
	rs232_rx		,
	
	rs232_tx		
);
	input 				Clk					;
	input				Rst_n				;
	input 				key_in 				;
	input 				rs232_rx			;
	
	output				rs232_tx			;
	
	wire 				key_in				;
	wire 				key_flag			;
	wire 				key_state			;
	wire 				rx_done 			;
	wire 				wren				;
	wire [7:0]			rdaddress			;
	wire [7:0]			wraddress			;
	wire 				send_en				;
	
	wire baud_set = 3'b0;//9600波特率
	wire [7:0]		data_byte_rx	;
	wire [7:0]		data_byte_tx	;
	
	wire 		tx_state;
	wire		tx_done;
	
	
	//控制模块
	ctrl ctrl_inst(
		.Clk			(Clk		),
		.Rst_n			(Rst_n		),
		.key_flag 		(key_flag 	),
		.key_state		(key_state	),
		.rx_done		(rx_done	),
		.tx_done		(tx_done	),
		         
		.wren			(wren		),
		.rdaddress		(rdaddress	),
		.wraddress		(wraddress	),
		.send_en		(send_en	)			
	);
	
	//按键消抖模块
	key_filter key_filter_inst(
		.Clk			(Clk		),
		.Rst_n			(Rst_n		),
		.key_in			(key_in		),
		.key_flag		(key_flag	),
		.key_state		(key_state	)
	);
	
	//存储模块
	dpram dpram_inst(
		.clock			(Clk		 	),
		.data			(data_byte_rx	),
		.rdaddress		(rdaddress		),
		.wraddress		(wraddress		),
		.wren			(wren			),
			
		.q				(data_byte_tx	)	
	);
	
	//发送模块
	uart_byte_tx uart_byte_tx_inst(
		.Clk			(Clk		 	),//50M时钟
		.Rst_n			(Rst_n			),//复位信号
		.send_en		(send_en		),//发送使能信号
		.baud_set		(baud_set		),//波特率选项
		.data_byte		(data_byte_tx	),//要发送的单字节数据
		          
		.rs232_tx		(rs232_tx		),//要发送出去的单比特数据
		.tx_done		(tx_done		),//发送接收标志
		.tx_state		(tx_state		) //发送的状态

	);
	
	//接收模块
	uart_byte_rx uart_byte_rx_inst(
		.Clk			(Clk		 	),
		.Rst_n			(Rst_n			),
		.rs232_rx		(rs232_rx		),
		.baud_set		(baud_set		),
		      
		.data_byte		(data_byte_rx	),
		.rx_done		(rx_done		)	
	);
endmodule

04.uart_dpram_tb.v

`timescale 1ns/1ns

`define clock_period 20

module uart_dpram_tb;
	reg 				Clk				;
	reg 				Rst_n			;
	wire 				key_in 			;
	wire 				rs232_rx		;
	
	wire				rs232_tx		;
	reg					press			;
	
	reg [7:0] 			data_byte		;
	reg [2:0]			baud_set		;
	reg					send_en			;
	wire				tx_done			;
	wire				tx_state		;

	uart_dpram uart_dpram_inst(
		.Clk		(Clk		),
		.Rst_n		(Rst_n		),
		.key_in		(key_in		),
		.rs232_rx	(rs232_rx	),
		          
		.rs232_tx	(rs232_tx	)
	);

	uart_byte_tx uart_byte_tx_inst(
		.Clk			(Clk		 	),//50M时钟
		.Rst_n			(Rst_n			),//复位信号
		.send_en		(send_en		),//发送使能信号
		.baud_set		(baud_set		),//波特率选项
		.data_byte		(data_byte		),//要发送的单字节数据
		          
		.rs232_tx		(rs232_rx		),//要发送出去的单比特数据
		.tx_done		(tx_done		),//发送接收标志
		.tx_state		(tx_state		) //发送的状态

	);
	
	key_model key_model(
		.press(press),
		.key(key_in)
	);
	
	//产生时钟
	initial  Clk = 1'b1;
	always #(`clock_period/2) Clk = ~Clk;

	//产生激励信号
	initial begin
		Rst_n = 1'b0;
		press = 0;
		data_byte = 8'b0;
		send_en = 1'b0;
		baud_set = 3'd0;
		#(`clock_period*20 + 1);
		Rst_n = 1'b1;
		
		
		#(`clock_period*50);
		data_byte = 8'haa;
		send_en = 1'd1;
		#`clock_period;
		send_en = 1'd0;
		@(posedge tx_done);
		
		
		#(`clock_period*5000);
		data_byte = 8'h55;
		send_en = 1'd1;
		#`clock_period;
		send_en = 1'd0;
		@(posedge tx_done);
		
		
		#(`clock_period*5000);
		data_byte = 8'hdc;
		send_en = 1'd1;
		#`clock_period;
		send_en = 1'd0;
		@(posedge tx_done);
		
		#(`clock_period*5000);
		data_byte = 8'hcd;
		send_en = 1'd1;
		#`clock_period;
		send_en = 1'd0;
		@(posedge tx_done);
		
		#(`clock_period*5000);
		
		press = 1;
		#(`clock_period *3) 
		press = 0;
		
		$stop;	
	end
endmodule

04.功能仿真

uart_dpram:搭建串口收发与存储双口RAM简易应用系统_第2张图片

05.板级验证(闭环测试)

uart_dpram:搭建串口收发与存储双口RAM简易应用系统_第3张图片
这是板级验证的测试得到的,感觉有一拍的延迟。之前在验证串口接收模块时,也发现了一拍的延迟,也没有深究,此处就体现了。

你可能感兴趣的:(verilog,fpga,uart)