Verilog HDL 学习篇——UART自收自发

整个工程结构:

 

module UART
(
	input	CLK,
	input	RST,
	input	RX,
	output	TX
);

wire	[7:0]	wDATA;
wire			wReset;
wire			wRxEmpty,wTxEmpty;

RESET_MODULE	Rest
(
	.CLK_I(CLK),
	.RST_I(RST),
	.RST_O(wReset)
);

UART_TRANSMIT_MODULE	UartTransmit
(
	.wClock(CLK),		//输入时钟,所有操作由该时钟进行同步
	.wReset(wReset),	//复位
	.wEnable(1'B1),		//使能
	
	.wTxWE(wRxEmpty),
	.wTxEmpty(wTxEmpty),
	.wTxData(wDATA),
	
	.wTX(TX)
);

UART_RECEIVE_MODULE	UartReceive
(
	.wClock(CLK),		//输入时钟,所有操作由该时钟进行同步
	.wReset(wReset),	//复位
	.wEnable(1'B1),		//使能
	
	.wRxRE(wTxEmpty),
	.wRxEmpty(wRxEmpty),
	.wRxData(wDATA),
	
	.wRX(RX)
);

endmodule


 

复位模块:

//复位信号处理,异步复位同步化
module RESET_MODULE
#(
	parameter pClockCount=4	//检测周期数
)
(
	input	CLK_I,
	input	RST_I,
	output	RST_O
);
reg [pClockCount-1:0]	rReset;
//采样到pClockCount个周期的低电平则认为为有效复位
assign RST_O=|rReset;
always @(posedge CLK_I) rReset<={rReset[pClockCount-2:0],RST_I};

endmodule


时钟分频模块:

/*
时钟分频模块

InClockValue:输入时钟频率
Width		:计数位宽
K		:分频系数
K=F0*2^N/Fc Fo:输出频率,Fc:模块频率,N计数位宽			
*/
module CLOCK_DIVISION_MODULE
#(
	parameter pWidth=32			//计数位宽
)
//.......................................................................................................................
(
	input 	wClock,			//输入时钟
	input 	wReset,			//复位
	input	wEnable,		//使能
	input	wPOL,			//极性
	input	[pWidth-1:0]	wPK,	//系数
	output	wOutClock,		//分频输出
	output	wPosedge,		//上升沿
	output	wNegedge		//下降沿
);
//.......................................................................................................................
reg	[pWidth-1:0]	rCount;
reg	[1:0]		rOutClock;

assign wPosedge=~rOutClock[1]&rOutClock[0];
assign wNegedge=rOutClock[1]&~rOutClock[0];
assign wOutClock=rOutClock[1];
//.......................................................................................................................
always @ (posedge wClock or negedge wReset)
	if(!wReset) begin
		rCount		<={pWidth{1'B0}};
		rOutClock	<={2{wPOL}};
	end
	else if(!wEnable)begin
		rCount		<={pWidth{1'B0}};
		rOutClock	<={2{wPOL}};
	end
	else begin
		rCount<=rCount+wPK;
		if(rCount[pWidth-1]) rOutClock<={rOutClock[0],~wPOL};
		else rOutClock<={rOutClock[0],wPOL};
	end
//.......................................................................................................................
endmodule

 

UART发送模块

module UART_TRANSMIT_MODULE
(
	input		wClock,
	input		wReset,
	input		wEnable,
	output		wBusy,
	
	input		wTxClear,
	input		wTxWE,
	
	output		wTxFull,
	output		wTxEmpty,
	
	input	[7:0]	wTxData,
	
	output		wTX
);

//UART发送时钟控制
reg	rTxClockEnable;
wire	wTxClock;
wire	wPosedge,wNegedge;
CLOCK_DIVISION_MODULE TxClock
(
	.wClock(wClock),
	.wReset(wReset),
	.wPOL(1'B0),
	.wPK(9895605),
	.wEnable(rTxClockEnable),
	.wOutClock(wTxClock),
	.wPosedge(wPosedge),
	.wNegedge(wNegedge)
);
reg 		rTxRE;
wire [7:0]	wTxDataOut;
FAST_FIFO_MODULE FIFO_TX
(
	.wClock(wClock),
	.wReset(wReset),
	.wClear(wTxClear),
	.wWE(wTxWE),
	.wRE(rTxRE),
	.wFull(wTxFull),
	.wEmtpy(wTxEmpty),
	.wDataIn(wTxData),
	.wDataOut(wTxDataOut)
);

reg		rTX;
reg		rBusy;
reg	[8:0]	rTxData;
reg	[3:0]	rBitCount;
assign	wBusy=rBusy;
assign	wTX=rTX;
always @(posedge wClock or negedge wReset)
if(!wReset) begin
	rTX<=1'B1;
	rBusy<=1'B0;
	rTxRE<=1'B0;
	rTxClockEnable<=1'B0;
end
else if(wEnable) begin

	if(rTxRE) rTxRE<=1'B0;
	
	if(!wTxEmpty & !rBusy) begin
		rBusy<=1'B1;
		rTxClockEnable<=1'B1;
		rTxRE<=1'B1;
		rBitCount<=4'H0;
		{rTX,rTxData[8:0]}<={1'B0,wTxDataOut,1'B1};
	end
	
	//下降沿
	if(wNegedge) begin
		rBitCount<=rBitCount+1'B1;
		if(rBitCount==3'H9) begin
			if(!wTxEmpty) begin
				rBusy<=1'B1;
				rTxRE<=1'B1;
				{rTX,rTxData[8:0]}<={1'B0,wTxDataOut,1'B1};
			end
			else begin
				rBusy<=1'B0;
				rTxClockEnable<=1'B0;
			end
		end
		else {rTX,rTxData[8:1]}<=rTxData;
	end
end

endmodule


UART接受模块

module UART_RECEIVE_MODULE
(
	input		wClock,	//输入时钟,所有操作由该时钟进行同步
	input 		wReset,		//复位
	input		wEnable,	//使能
	
	input		wRxRE,
	input		wRxClear,
	output		wRxFull,
	output		wRxEmpty,
	output	[7:0]	wRxData,
	
	output		wRX
);
//......................................................................................................................
wire	wPosedge,wNegedge;
wire	wRxClock;		//Receive clock
CLOCK_DIVISION_MODULE RxClock
(
	.wClock(wClock),
	.wReset(wReset),
	.wPOL(1'B0),
	.wPK(158329674),
	.wEnable(wEnable),
	.wOutClock(wRxClock),
	.wPosedge(wPosedge),
	.wNegedge(wNegedge)
);
reg		rRxWE;
reg	[7:0]	rRxData;
FAST_FIFO_MODULE SPI_FIFO_RX
(
	.wClock(wClock),
	.wReset(wReset),
	.wClear(wRxClear),
	.wWE(rRxWE),
	.wRE(wRxRE),
	.wFull(wRxFull),
	.wEmtpy(wRxEmpty),
	.wDataIn(rRxData),
	.wDataOut(wRxData)
);

reg 		rStart;
reg	[7:0]	rSampleBitCount;	//采样计数
reg	[15:0]	rSignalSample;		//16倍采样数据
assign BitResut=((rSignalSample[9:7]==3'B111)||(rSignalSample[9:7]==3'B101)||(rSignalSample[9:7]==3'B011)||(rSignalSample[9:7]==3'B110));

always @(posedge wClock or negedge wReset)
if(!wReset) begin
	rSignalSample<=16'HFFFF;
	rStart<=1'B0;
	rRxWE<=1'B0;
end
else if(wEnable) begin
	if(rRxWE) rRxWE<=1'B0;
	
	if(wPosedge) begin
		rSignalSample <={rSignalSample[14:0],wRX};
		
		if({rStart,rSignalSample[12:9],rSignalSample[7],rSignalSample[5],rSignalSample[3:0]}==11'B01110000000)begin
			rSampleBitCount<=8'H0A;
			rStart<=1'B1;
		end
		
		if(rStart) begin
			rSampleBitCount<=rSampleBitCount+1'B1;
			if(rSampleBitCount[3:0]==4'HF) case(rSampleBitCount[7:4])
				4'H0:if(BitResut) rStart<=1'B0;
				4'H1,4'H2,4'H3,4'H4,4'H5,4'H6,4'H7,4'H8:rRxData<={BitResut,rRxData[7:1]};
				4'H9: begin
					rStart<=1'B0;
					rRxWE<=1'B1;
				end
				default;
			endcase
		end
	end
	
end

endmodule



 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Verilog HDL是一种硬件描述语言,用于设计数字电路。要实现UART(通用异步发传输)功能,可以使用Verilog HDL来描述相应的逻辑电路。 首先,需要定义UART的输入和输出端口。输入端口包括时钟信号、串行数据输入(Rx)和复位信号。输出端口包括串行数据输出(Tx)和数据有效标志位(valid)。可以用以下代码来定义输入输出端口: module uart( input wire clk, input wire reset, input wire rx, output wire tx, output wire valid ); 然后,定义一些必要的寄存器和辅助变量来实现UART的功能。例如,可以定义一个计数器来实现波特率的控制,一个状态机来处理接和发送的不同状态,以及一个FIFO(先进先出)缓冲区来存储接和发送的数据。通过定义这些寄存器和变量,可以实现UART的数据接和发送功能。 接下来,根据UART的工作原理,使用Verilog HDL来实现数据接和发送的逻辑。例如,在接数据时,需要根据时钟信号来采样串行输入数据,然后将采样的数据存储到FIFO缓冲区中,并根据接状态机的变化来更新接状态。在发送数据时,需要从FIFO缓冲区中读取数据,并根据发送状态机的变化来更新发送状态和输出串行数据。 最后,根据设计要求,通过组合逻辑和时序逻辑来实现上述功能。使用电路模块实例化,连接各个模块和寄存器,将所有组成部分整合在一起,最后生成一个完整的UART电路。最后,使用适当的测试向量对设计进行验证和仿真,确保UART功能的正确性。 总之,通过使用Verilog HDL,可以实现UART的功能。通过定义适当的输入输出端口、寄存器和变量,以及使用适当的逻辑和状态机,可以实现UART的数据接和发送功能。然后,通过整合所有组成部分,并进行验证和仿真,可以得到一个完整的UART电路。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值