⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uart_out.v

📁 UART16550兼容的串行通讯控制器
💻 V
字号:
// synopsys translate_off
`include "timescale.v"
// synopsys translate_on

`include "uart_defines.v"

module uart_out
(
	clk,
	reset,
	enable,
	data_len, stop2, par_ena, par_even, par_stk,
	afc_cts, serial_out,
	tf_reset,
	tx_data_valid,
	tx_data,
	tx_empty,
	tf_pop
);

input			clk;
input			reset;
input			enable;

input [1:0]		data_len;			// data bits - 1
input			stop2, par_ena, par_even, par_stk;

input			afc_cts;
output			serial_out;
output			tx_empty;
output			tf_pop;

input			tf_reset;
input			tx_data_valid;
input [7:0]		tx_data;

wire			serial_out;
reg				tx_empty;
reg				tf_pop;

///////////////////////////////////

reg				data_parity;
reg				tx_parity;
reg [3:0]		bit_cnt;
reg [8:0]		tx_shift;
reg [7:0]		tx_shadow;
reg [1:0]		tx_state;

reg				tx_frame;
reg [3:0]		cnt16;
reg				bit_pulse, half_pulse;

parameter S_TX_IDLE		= 2'd0;
parameter S_TX_START	= 2'd1;
parameter S_TX_BYTE		= 2'd2;
parameter S_TX_STOP2	= 2'd3;

assign serial_out = tx_shift[0];

always @( data_len or tx_shadow )
	case ( data_len )
		2'b00 : data_parity = ^tx_shadow[4:0];
		2'b01 : data_parity = ^tx_shadow[5:0];
		2'b10 : data_parity = ^tx_shadow[6:0];
		2'b11 : data_parity = ^tx_shadow[7:0];
	endcase

always @( par_stk or par_even or data_parity )
	case ( { par_stk, par_even } )
		2'b00 : tx_parity = ~data_parity;	// odd parity
		2'b01 : tx_parity = data_parity;	// even parity
		2'b10 : tx_parity = 1'b1;			// '1'
		2'b11 : tx_parity = 1'b0;			// '0'
	endcase

always @( posedge clk or posedge reset )
begin
	if( reset )
	begin
		cnt16 <= #1 4'd13;
		bit_pulse <= #1 1'b0;
		half_pulse <= #1 1'b0;
	end
	else if( enable )
	begin
		if( !tx_frame )
		begin
			cnt16 <= #1 4'd13;
			bit_pulse <= #1 1'b0;
			half_pulse <= #1 1'b0;
		end
		else
		begin
			bit_pulse <= #1 (cnt16==4'd0);
			half_pulse <= #1 (cnt16==4'd8);
			cnt16 <= #1 cnt16 - 4'd1;
		end
	end
end

always @(posedge clk or posedge reset)
	begin
	if (reset)
	begin
		tx_empty	<= #1 1'b1;
		tx_state	<= #1 S_TX_IDLE;
		tf_pop		<= #1 1'b0;
		tx_frame	<= #1 1'b0;
		tx_shift	<= #1 9'b111111111;
	end
	else if (enable)
	begin
		case (tx_state)
		S_TX_IDLE:
			if ( tx_data_valid && !tf_reset )
			begin
				tx_empty <= #1 1'b0;
				if( afc_cts )
				begin
					tx_shadow <= #1 tx_data;
					tx_shift[0] <= #1 1'b0;
					tf_pop <= #1 1'b1;
					tx_state <= #1 S_TX_START;
				end
			end

		S_TX_START :
		begin
			tx_frame <= #1 1'b1;
			if (bit_pulse)
			begin
				case ( {par_ena, data_len} )
				3'b000 : begin bit_cnt <= #1 4'd5;	tx_shift <= #1 {4'b1111, tx_shadow[4:0]};	end	// 5+stop
				3'b001 : begin bit_cnt <= #1 4'd6;	tx_shift <= #1 {3'b111, tx_shadow[5:0]};	end	// 6+stop
				3'b010 : begin bit_cnt <= #1 4'd7;	tx_shift <= #1 {2'b11, tx_shadow[6:0]};	end	// 7+stop
				3'b011 : begin bit_cnt <= #1 4'd8;	tx_shift <= #1 {1'b1, tx_shadow[7:0]};	end	// 8+stop
				3'b100 : begin bit_cnt <= #1 4'd6;	tx_shift <= #1 {3'b111, tx_parity, tx_shadow[4:0]};	end	// 5+parity+stop
				3'b101 : begin bit_cnt <= #1 4'd7;	tx_shift <= #1 {2'b11, tx_parity, tx_shadow[5:0]};	end	// 6+parity+stop
				3'b110 : begin bit_cnt <= #1 4'd8;	tx_shift <= #1 {1'b1, tx_parity, tx_shadow[6:0]};		end	// 7+parity+stop
				3'b111 : begin bit_cnt <= #1 4'd9;	tx_shift <= #1 {tx_parity, tx_shadow[7:0]};		end	// 8+parity+stop
				endcase
				tx_state <= #1 S_TX_BYTE;
			end
		end

		S_TX_BYTE :
			if (bit_pulse)
			begin
				tx_shift[8:0] <= #1 {1'b1,tx_shift[8:1]};
				if( ~|bit_cnt )
				begin
					if( stop2 )
						tx_state <= #1 S_TX_STOP2;
					else if( !tx_data_valid || tf_reset || !afc_cts )
					begin
						tx_empty <= #1 !tx_data_valid | tf_reset;
						tx_frame <= #1 1'b0;
						tx_state <= #1 S_TX_IDLE;
					end
					else
					begin
						tx_shadow <= #1 tx_data;
						tf_pop <= #1 1'b1;
						tx_shift[0] <= #1 1'b0;
						tx_frame <= #1 1'b0;
						tx_state <= #1 S_TX_START;
					end
				end
				bit_cnt <= #1 bit_cnt - 1'b1;
			end

		S_TX_STOP2 :
			case( {data_len, half_pulse, bit_pulse} )
			4'b0010, 4'b0101, 4'b1001, 4'b1101 :
				if( !tx_data_valid || !afc_cts )
				begin
					tx_empty <= #1 !tx_data_valid | tf_reset;
					tx_frame <= #1 1'b0;
					tx_state <= #1 S_TX_IDLE;
				end
				else
				begin
					tx_shadow <= #1 tx_data;
					tf_pop <= #1 1'b1;
					tx_shift[0] <= #1 1'b0;
					tx_frame <= #1 1'b0;
					tx_state  <= #1 S_TX_START;
				end
			default:
				;
			endcase

		default : // should never get here
		begin
			tx_empty <= #1 1'b1;
			tx_frame <= #1 1'b0;
			tx_shift <= #1 9'b111111111;
			tx_state <= #1 S_TX_IDLE;
		end
		endcase
	end // end if enable
	else
		tf_pop <= #1 1'b0;  // tf_pop must be 1 cycle width
end // transmitter logic

endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -