欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【verilog】verilog实现串口传输UART

程序员文章站 2022-07-09 12:48:40
...

1.接收模块
【verilog】verilog实现串口传输UART
代码:

//****************uart receive module******************//
//********************************************************//
`define SIM
module uart_rx#(
	parameter DATAWIDTH 		= 8,
	parameter BAUD_CNT_WIDTH 	= 12,
	parameter BIT_CNT_WIDTH 	= 4
)
(
	input 								CLK,
	input 								RSTn,
	input 								rs232_rx,//input data
	output reg 	[ DATAWIDTH - 1 : 0 ] 	rx_data,//receive data
	output reg 							po_flag //finish sig
);
`ifndef SIM
localparam BAUD_END = 5207;//simulate time too long,change to 56(560)
`else
localparam BAUD_END = 56;
`endif
localparam BAUD_M 	= BAUD_END / 2 - 1;
localparam BIT_END 	= 8;
 
reg 							rx_r1;
reg 							rx_r2;
reg 							rx_r3;
reg 							rx_flag;
reg [ BAUD_CNT_WIDTH - 1 : 0 ] 	baud_cnt;
reg 							bit_flag;
reg [ BIT_CNT_WIDTH - 1 : 0 ] 	bit_cnt;
wire 							rx_neg;//rx negedge

assign rx_neg = ~rx_r2 & rx_r3;

always @(posedge CLK or negedge RSTn) begin
	rx_r1 <= 0;
	rx_r2 <= 0;
	rx_r3 <= 0;
end

always @(posedge CLK) begin
	rx_r1 <= rs232_rx;
	rx_r2 <= rx_r1;
	rx_r3 <= rx_r2;
end

//rx_flag
always @(posedge CLK or negedge RSTn) begin
	if (!RSTn) begin
		// reset
		rx_flag <= 0;
	end
	else if (rx_neg) begin
		rx_flag <= 1;
	end
	else if (bit_cnt == 0 && baud_cnt == BAUD_END) begin
		rx_flag <= 0;
	end
end

//baud_cnt
always @(posedge CLK or  negedge RSTn) begin
	if (!RSTn) begin
		// reset
		baud_cnt <= 0;
	end
	else if (baud_cnt == BAUD_END) begin
		baud_cnt <= 0;
	end
	else if (rx_flag) begin
		baud_cnt <= baud_cnt + 1;
	end
	else begin
		baud_cnt <= 0;
	end
end

//bit_flag
always @(posedge CLK or negedge RSTn) begin
	if (!RSTn) begin
		// reset
		bit_flag <= 0;
	end
	else if (baud_cnt == BAUD_M ) begin
		bit_flag <= 1;
	end
	else begin
		bit_flag <= 0;
	end
end

//bit_cnt
always @(posedge CLK or negedge RSTn) begin
	if (!RSTn) begin
		// reset
		bit_cnt <= 0;
	end
	else if (bit_flag == 1 && bit_cnt == BIT_END) begin
		bit_cnt <= 0;
	end
	else if (bit_flag) begin
		bit_cnt <= bit_cnt + 1;
	end
end

//rx_data
always @(posedge CLK or negedge RSTn) begin
	if (!RSTn) begin
		// reset
		rx_data <= 0;
	end
	else if (bit_flag == 1 && bit_cnt >= 1) begin
		rx_data <= { rx_r2, rx_data [ DATAWIDTH - 1 : 1 ] };
	end
end

//po_flag
always @(posedge CLK or negedge RSTn) begin
	if (!RSTn) begin
		// reset
		po_flag <= 0;
	end
	else if (bit_cnt == BIT_END && bit_flag == 1) begin
		po_flag <= 1;
	end
	else begin
		po_flag <= 0;
	end
end
endmodule

testbench:

module uart_rx_tb;
	reg 			CLK;
	reg 			RSTn;
	reg 			rs232_tx;

	wire 			po_flag;
	wire [7:0] 		rx_data;

	reg  [7:0] 		mem [4:0];

initial $readmemh ("D:/Project/verilog_pro/project_module/sdram_controller/src/tx_data.txt",mem);

initial 
 	begin
		CLK = 1;
		forever #5 CLK = ~CLK;
	end

initial
 	begin
		RSTn = 0;
		rs232_tx <= 1;
		#100
		RSTn = 1;
		#100
		tx_byte();
	end

task tx_byte();
	integer i;
	for (i = 0; i < 5;i=i+1 )
		begin
			tx_bit(mem[i]);
		end
endtask

task tx_bit(
	input [7:0] data
);
	integer i;
	for (i = 0; i < 10;i=i+1 )
		begin
			case(i)
				0:	rs232_tx <= 1'b0;
				1:	rs232_tx <= data [0];
				2:	rs232_tx <= data [1];
				3:	rs232_tx <= data [2];
				4:	rs232_tx <= data [3];
				5:	rs232_tx <= data [4];
				6:	rs232_tx <= data [5];
				7:	rs232_tx <= data [6];
				8:	rs232_tx <= data [7];
				9:	rs232_tx <= 1'b1;
			endcase
			#560;
		end

endtask

uart_rx uart_rx_inst(.CLK		(CLK		),
					 .RSTn		(RSTn		),
					 .rs232_rx	(rs232_tx	),
					 .rx_data	(rx_data	),
					 .po_flag	(po_flag	));

endmodule

txt文件:
【verilog】verilog实现串口传输UART
【verilog】verilog实现串口传输UART
2.发送模块
【verilog】verilog实现串口传输UART
代码:

//******************uart transfer module******************//
//***********************************************************//
`define SIM
module uart_tx#(
	parameter DATAWIDTH 		= 8,
	parameter BAUD_CNT_WIDTH 	= 32,
	parameter BIT_CNT_WIDTH 	= 4

)
(
	input 								CLK,
	input 								RSTn,
	input 		[ DATAWIDTH - 1 : 0 ] 	tx_data,//data
	input 								tx_trig,//transfer sig
	output  reg							rs232_tx//transfer data
);
`ifndef SIM
localparam BAUD_END = 5207;//simulate time too long,change to 56(560)
`else
localparam BAUD_END = 56;
`endif
localparam BAUD_M 	= BAUD_END / 2 - 1;
localparam BIT_END 	= 8;

reg [ DATAWIDTH - 1 : 0 	 ] 	tx_data_r;
reg 							tx_flag;
reg [ BAUD_CNT_WIDTH - 1 : 0 ] 	baud_cnt;
reg 							bit_flag;
reg [ BIT_CNT_WIDTH - 1 : 0  ] 	bit_cnt;
//reg                             rs232_tx_t;

//tx_data_r
always @(posedge CLK or  negedge RSTn) begin
	if (!RSTn) begin
		// reset
		tx_data_r <= 0;
	end
	else if (tx_trig == 1 && tx_flag == 0) begin
		tx_data_r <= tx_data;
	end
end


//tx_flag
always @(posedge CLK or negedge RSTn) begin
	if (!RSTn) begin
		// reset
		tx_flag <= 0;
	end
	else if (tx_trig == 1 && tx_flag == 0) begin
		tx_flag <= 1;
	end
	else if (bit_cnt == BIT_END && bit_flag == 1) begin
		tx_flag <= 0;
	end
end
//baud_cnt
always @(posedge CLK or  negedge RSTn) begin
	if (!RSTn) begin
		// reset
		baud_cnt <= 0;
	end
	else if (baud_cnt == BAUD_END) begin
		baud_cnt <= 0;
	end
	else if (tx_flag) begin
		baud_cnt <= baud_cnt + 1;
	end
	else begin
		baud_cnt <= 0;
	end

end
//bit_flag
always @(posedge CLK or  negedge RSTn) begin
	if (!RSTn) begin
		// reset
		bit_flag <= 0;
	end
	else if (baud_cnt == BAUD_END) begin
		bit_flag <= 1;
	end
	else begin
		bit_flag <= 0;
	end
end
//bit_cnt
always @(posedge CLK or negedge RSTn) begin
	if (!RSTn) begin
		// reset
		bit_cnt <= 0;
	end
	else if (bit_flag == 1 && bit_cnt == BIT_END) begin
		bit_cnt <= 0;
	end
	else if (bit_flag) begin
		bit_cnt <= bit_cnt + 1;
	end
end
//rs232_tx
always @(posedge CLK or negedge RSTn) begin
	if (!RSTn) begin
		// reset
		rs232_tx <= 1;
	end
	else if (tx_flag) begin
		case(bit_cnt)
		0:		rs232_tx <= 0;
		1:		rs232_tx <= tx_data_r[0];
		2:		rs232_tx <= tx_data_r[1];
		3:		rs232_tx <= tx_data_r[2];
		4:		rs232_tx <= tx_data_r[3];
		5:		rs232_tx <= tx_data_r[4];
		6:		rs232_tx <= tx_data_r[5];
		7:		rs232_tx <= tx_data_r[6];
		8:		rs232_tx <= tx_data_r[7];
		default:rs232_tx <= 1;

		endcase
	end
	else begin
		rs232_tx <= 1;
	end
end

//assign rs232_tx = rs232_tx_t;
endmodule

testbench:

module uart_tx_tb;
	reg CLK;
	reg RSTn;
	reg tx_trig;
	reg [7:0] tx_data;

	wire rs232_tx;

initial
 	begin
		CLK = 1;
		forever #5 CLK = ~CLK;
	end

initial 
 	begin
		RSTn = 0;
		#100
		RSTn = 1;
	end

initial 
 	begin
		tx_data <= 0;
		tx_trig <= 0;
		#200
		tx_trig <= 1;
		tx_data <= 8'h55;
		#10
		tx_trig <= 0;
	end

uart_tx uart_tx_inst(.CLK(CLK),
					 .RSTn(RSTn),
					 .tx_data(tx_data),
					 .tx_trig(tx_trig),
					 .rs232_tx(rs232_tx)
	);

endmodule

【verilog】verilog实现串口传输UART
3.顶层

module uart_top(
	input 		CLK,
	input 		RSTn,
	input 		rs232_rx,
	output    	rs232_tx
);

//***************Main Code*************//
wire [7:0] rx_data;
wire tx_trig;
//reg  rs232_tx_t;

uart_rx uart_rx_inst(.CLK		(CLK		),
					 .RSTn		(RSTn		),
					 .rs232_rx	(rs232_rx	),
					 .rx_data	(rx_data	),
					 .po_flag	(tx_trig	));

uart_tx uart_tx_inst(.CLK		(CLK		),
					 .RSTn		(RSTn		),
					 .tx_data	(rx_data	),
					 .tx_trig	(tx_trig	),
					 .rs232_tx	(rs232_tx 	));

endmodule

testbench:

module uart_tb;
	reg CLK;
	reg RSTn;
	reg rs232_rx;
	wire rs232_tx;

	reg  [7:0] 		mem [4:0];

initial $readmemh ("D:/Project/verilog_pro/project_module/sdram_controller/src/tx_data.txt",mem);

initial
 	begin
		RSTn = 0;
		//rs232_tx = 1;
		#100
		RSTn = 1;
		#100
		tx_byte();
	end


initial 
 	begin
		CLK = 0;
		forever #5 CLK = ~CLK;
	end
task tx_byte();
	integer i;
	for (i = 0; i < 5;i=i+1 )
		begin
			tx_bit(mem[i]);
		end
endtask

task tx_bit(
	input [7:0] data
);
	integer i;
	for (i = 0; i < 10;i=i+1 )
		begin
			case(i)
				0:	rs232_rx <= 1'b0;
				1:	rs232_rx <= data [0];
				2:	rs232_rx <= data [1];
				3:	rs232_rx <= data [2];
				4:	rs232_rx <= data [3];
				5:	rs232_rx <= data [4];
				6:	rs232_rx <= data [5];
				7:	rs232_rx <= data [6];
				8:	rs232_rx <= data [7];
				9:	rs232_rx <= 1'b1;
			endcase
			#560;
		end

endtask

uart_top uart_inst(.CLK			(CLK),
					.RSTn		(RSTn),
					.rs232_rx	(rs232_rx),
					.rs232_tx	(rs232_tx));
endmodule

【verilog】verilog实现串口传输UART

相关标签: verilog