基于zedboard编写verilog配置ESP8266 wifi模块参考设计

首先说说自己写这篇博客的目的,由于本人是做FPGA的,在实际项目过程中,需要用到wifi模块来传输fpga内的数据,所以考虑在自己的fpga板子(zedboard)上加上一个WiFi模块,查阅了相关资料,找到了这款口碑还不的wifi模块ESP8266。

ESP8266简介

ESP8266 WIFI芯片作为一款价格低廉,功能完备的wifi通信模块,用户利用它可以快速的搭建自己wifi热点,实现数据传输。该模块在某宝上有售,有兴趣的朋友可以买来开发调试。

基于zedboard编写verilog配置ESP8266 wifi模块参考设计_第1张图片

                                                                                         ESP8266 实物图

FPGA&wifi模块的硬件连接

要想正确的配置首先就得将该wifi模块与zedboard正确连接。下图是ESP8266的硬件接口示意图和功能列表。

基于zedboard编写verilog配置ESP8266 wifi模块参考设计_第2张图片

                                                                                        模块管脚排列图                                                                           

PIN Function Description
1 URXD
  1. UART_RXD,接收;
  2. General Purpose Input/Output:GPIO3;
2 UTXD
  1. UART_TXD,发送;
  2. General Purpose Input/Output:GPIO1;
  3. 开机时禁止下拉;
5 RESET(GPIO 16)      外部Reset信号,低电平复位,高电平工作(默认高);
6 GND      GND
8 VCC      3.3V,模块供电;
9 ANT     WiFi Antenna
11 GPIO0
  1. 默认WiFi Status:WiFi工作状态指示灯控制信号;
  2. 工作模式选择:

    悬空:Flash Boot,工作模式;

    下拉:UART Download,下载模式;

12 ADC     ADC,输入范围:0V-1V;
13 GPIO15     下拉:工作模式;
14 CH_PD
  1. 高电平工作;
  2. 低电平模块供电关掉;
15 GPIO2
  1. 开机上电时必须为高电平,禁止硬件下拉;
  2. 内部默认已拉高

                                                                                           pin脚定义

主要需要连接的是URXD,UTXD,CH_PD,VCC,GND这几个接口。CH_PD和VCC一起连接到zedboard上3.3v的电压端口,GND接到zedboard上的GND端口,URXD和UTXD分别连接到zedboard上任选的通用GPIO口,无特定要求。这些连接可以通过杜邦线完成。

当完成硬件连接后,给zedboard上电,可以看到WiFi模块电源指示灯亮,这是用手机或电脑搜寻附近的WiFi信号,可以搜到该WiFi模块发出的开放式的WiFi热点。

接下来进行WiFi模块的配置工作。

WiFi模块配置

关于该WiFi模块的配置,官方给了两种方式,第一种是用AT指令去配置,第二种是用他们公司内嵌的AI-CLOUD 的8266 SDK 来配置。作者使用的是第一种方式,对第二种方式不太了解,有兴趣的朋友可以看下这个链接,里面详细介绍了第二种配置方式。

关于AT指令的配置方式,官方给的方式是,将WiFi通过TTL转USB接口连接到电脑上的usb接口,并通过电脑上的串口调试助手,给WiFi模块发送AT配置指令。关于这种方式,已经有很多前辈做了相应的实验教程,可以看ESP8266 AT 指令这个链接学习。关于ESP8266全面的AT指令集,可以去它官网链接下载相关资料了解。

在看本人下面写的fpga配置WiFi模块教程之前,希望大家已经跟着上面前辈的教程至少配置过一遍。

利用FPGA配置WiFi模块

其实用FPGA配置WiFi是基于用AT指令配置WiFi演变而来的,如果仔细做了之前的教程,应该能够理解,所谓使用AT指令配置WiFi,其实就是用电脑上的串口调试助手向WiFi模块发送AT指令,从而完成配置。现在需要用FPGA配置WiFi模块,即需要通过FPGA以串口通信的方式给WiFi模块发送配置指令。所以设计的关键就是要在FPGA内实现串口通信协议,同时要将自己需要的AT指令写在FPGA内的寄存器里。这里有几个注意点:

①AT指令需要转成(八位十六进制)ASCII码,每一个字符被转成一个八位十六进制的ASCII码,可以用转码链接实现转码

每条AT指令末尾需要加上回车键的ASCII码,不然wifi模块无法正确识别配置指令这一点很容易被忽视,另外在windows操作系统下,回车键的ASCII码是0d和0a,注意用上面的转码链接将回车转成的ascII码只是0a,所以这里需要手动修改。

③AT指令被存在自己定义在FPGA内部的寄存器组中。以一个个字符按指令的顺序存储。

④关于串口通信(UART)我之后会给出我写的verilog代码,还不太懂串口通信原理的朋友也可以点击串口通信原理链接查看学习。另外这里要提醒一下,串口通信会设置波特率大小,ESP8266对配置它的串口波特率有硬性要求,必须为115200。这在乐鑫原厂硬件资料里可以查到。

在我的设计中,ESP8266工作模式被设置为TCP server 透传模式,IP地址为 192.168.4.2 侦听端口为 8084

由于这是一个项目中的小工程,我需要发送的数据是4094个fft数据,每个是八位16进制的形式,大家可以随机生成4094个模拟数据发送,如果数据足够多,满速WiFi传输速度大概为11.2kb/s,速率相对较慢,由于串口速率的限制影响了它本身的传输速率。

接下来我给出本设计全部的verliog源码,开发环境是vivado 2017.2,使用的FPGA板是xilinx公司的zedboard。

测试方法:将WIFI模块的发送端通过TTL转USB接口连到电脑上,然后zedboard上电,WiFi开启,电脑连接上WiFi信号,ip地址必须为192.168.4.2。若WiFi模块配置成功,则会通过他自身的发送端发出一些信息供查看,所以实现打开电脑的串口调试助手即可查看这些信息,串口调试助手的设置如下,具体的com编号因人而异。

这里我给出一个网盘链接供大家下载测试工具:https://pan.baidu.com/s/158qe4mcq5A6hvLvOTBK6vw 密码:5hxb

基于zedboard编写verilog配置ESP8266 wifi模块参考设计_第3张图片

                                                                           串口调试助手设置图

配置完成后开始传输数据,电脑事先需要打开网络调试助手,设置如下

基于zedboard编写verilog配置ESP8266 wifi模块参考设计_第4张图片

                                                                               网络调试助手配置图

这是top顶层文件代码

module ad9364_top(

    input clk_100m,
    output txdata,
    input  rxdata

)


clk_wiz clk_wiz_xst

   (

    // Clock out ports

    .clk_40m(clk_40m),     // output clk_40m

    .clk_1p8432(clk_1p8432),

   // Clock in ports

    .clk_in(clk_100m));      // input clk_in



rst_generator rst_xst(

	.clk_in(clk_40m),

	.rst_n(rst_n)

);


fftdata fft_data_xst(

	.clk(clk_1p8432),

    .clkfftd(clk_40m),

    .flag1(tx_rdy),

    .fftdata(tx_data),

    .reset(uart_rst),

    .write(uart_wt),

    .tx_data(uart_data),

    .writebegin(writebegin)

);



uart uart_xst(

	.mclkx16(clk_1p8432), 

	.reset(uart_rst), 

	.read(), 

	.write(uart_wt), 

	.data(), 

	.txdata(uart_data),

	.sin(), 

	.sout(uart_sout), 

	.rxrdy(), 

	.txrdy(), 

	.parity_error(), 

	.framing_error(), 

	.overrun()

		

);

这是AT指令存储以及控制uart的模块代码

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// 
// editor: loving_Qi
// 
// Create Date: 2018/05/31 10:34:12
// Design Name: 
// Module Name: control_udp
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
module fftdata(input clk,
              input clkfftd,
              input flag1,
              input [7:0]fftdata,
			  input rst_n,
              output reset,
              output write,
              output[7:0] tx_data,
			  output writebegin
              
    );
reg reset=0;
reg write;
reg writebegin=0;
reg flag=0;
reg readover=0;
reg [31:0] j=0;
reg [31:0] count=0;
reg [31:0] count1=0;
reg [7:0]  tx_data;
reg [31:0] count_w=0;
reg [31:0] count_d=0;
reg [31:0] count_s=0;
reg [7:0] memo[4178:0];
//reg [7:0] memo1[2499999:0];
always@(posedge clkfftd )
begin
//if(!rst_n)
//begin
//	j <= 0;
//	flag <= 0;
//end
//else
//begin
 memo[0]<=8'h41;    
memo[1]<=8'h54;    
memo[2]<=8'h2b;
memo[3]<=8'h52;
memo[4]<=8'h53;
memo[5]<=8'h54;
memo[6]<=8'h0d;
memo[7]<=8'h0a;
memo[8]<=8'h41;
memo[9]<=8'h54;
memo[10]<=8'h2b;
memo[11]<=8'h43;
memo[12]<=8'h57;
memo[13]<=8'h4d;
memo[14]<=8'h4f;
memo[15]<=8'h44;
memo[16]<=8'h45;
memo[17]<=8'h3d;
memo[18]<=8'h33;
memo[19]<=8'h0d;
memo[20]<=8'h0a;
memo[21]<=8'h41;    
memo[22]<=8'h54;    
memo[23]<=8'h2b;
memo[24]<=8'h43;
memo[25]<=8'h49;
memo[26]<=8'h50;
memo[27]<=8'h53;
memo[28]<=8'h54;
memo[29]<=8'h41;
memo[30]<=8'h52;
memo[31]<=8'h54;
memo[32]<=8'h3d;
memo[33]<=8'h22;
memo[34]<=8'h54;
memo[35]<=8'h43;
memo[36]<=8'h50;
memo[37]<=8'h22;
memo[38]<=8'h2c;
memo[39]<=8'h22;
memo[40]<=8'h31;
memo[41]<=8'h39;
memo[42]<=8'h32;
memo[43]<=8'h2e;
memo[44]<=8'h31;
memo[45]<=8'h36;
memo[46]<=8'h38;
memo[47]<=8'h2e;
memo[48]<=8'h34;
memo[49]<=8'h2e;
memo[50]<=8'h32;
memo[51]<=8'h22;
memo[52]<=8'h2c;
memo[53]<=8'h38;
memo[54]<=8'h30;
memo[55]<=8'h38;
memo[56]<=8'h34;
memo[57]<=8'h0d;
memo[58]<=8'h0a;
memo[59]<=8'h41;
memo[60]<=8'h54;
memo[61]<=8'h2b;
memo[62]<=8'h43;   
memo[63]<=8'h49;
memo[64]<=8'h50;
memo[65]<=8'h4d;
memo[66]<=8'h4f;
memo[67]<=8'h44;
memo[68]<=8'h45;
memo[69]<=8'h3d;
memo[70]<=8'h31;
memo[71]<=8'h0d;
memo[72]<=8'h0a;
memo[73]<=8'h41;
memo[74]<=8'h54;
memo[75]<=8'h2b;
memo[76]<=8'h43;
memo[77]<=8'h49;
memo[78]<=8'h50;
memo[79]<=8'h53;
memo[80]<=8'h45;
memo[81]<=8'h4e;
memo[82]<=8'h44;
memo[83]<=8'h0d;
memo[84]<=8'h0a;
if(flag1==1)
    begin
        
        if(j<4094)
            begin 
                memo[j+85]<=fftdata;
                 j<=j+1;
                flag<=0;
            end
        else
            begin
                j<=0;
                flag<=1;
            end
    end
else
	begin
    j<=0;
	flag<=1;	
	end
end
//end
always@(posedge clk )
begin
//if(!rst_n)
//	begin
//	count1 <= 0;
//	reset <=0;
//	end
//else
//	begin
		if(count1>5&&count1<11)
		begin
			reset<=1;
			count1<=count1+1;
		end
		else if(count1<6)
		count1<=count1+1; 
		else
		reset<=0;
	end
//end
always@(posedge clk )
begin
//if(!rst_n)
//begin
//	readover <= 0;
//	count_w <= 0;
//	count_d <= 0;
//	count_s <= 0;
//	write <= 1;
//	writebegin <= 0;
//end
//else
//begin
    if(flag==0)
        begin
        readover<=0;
        count_w<=0;
        end
	else
	begin
      if(count_w<=7&&readover==0)
        begin
            write<=1'b1; 
            if(count_w==7)
                begin
//                    tx_data<=(count_d<92)?memo[count_d]:memo1[count_d-1125];   
               tx_data<=memo[count_d];     
                    if(count_d<86&&memo[count_d-1]==8'h0a && count_s<8000000)
                        begin
                        count_s<=count_s+1;
                        write<=1'b1;
                        end
					else if(count_d==84)
						begin
						writebegin<=1;
						count_d<=count_d+1;
						count_w<=count_w+1;
						end
                    else
                        begin
                        count_d<=count_d+1;
                        count_w<=count_w+1;
                        count_s<=0;
                           if (count_d>4178)
                            begin
                            count_d<=85;
                            count_w<=200;
                            readover<=1;
                            end
                       end
                 end
              else
              count_w<=count_w+1;
        end
      else if(count_w>7 &&count_w<=19&&readover==0)
        begin
            write<=1'b0;
            count_w<=count_w+1;
        end
    else if(count_w>19 &&count_w<=178&&readover==0)
        begin
            write<=1'b1;
            count_w<=count_w+1;
        end
    else if (count_w==179&&readover==0)
            count_w<=0; 
   // tx_data=0;
   end
end
//end

endmodule

下面是UART部分Verilog代码

UART的top文件

/******************************************************************

*

* 	File:  		uart.v

*

* 	Purpose: 	Top level UART description.  UART implements

*			a full duplex function.  This interface

*			interprets processor read/write parallel bus

*			protocol and translates to serial interface.

*		

**********************************************************************/



`timescale 1ns / 100ps



module uart (   mclkx16, reset, read, write, data, txdata,

		sin, sout, rxrdy, txrdy, parity_error, framing_error, overrun);

               

input      	mclkx16;		// Input clock, 16 x baud rate clock

input       	read;		   	// read strobe input

input       	write;		   	// write strobe input

input	      	reset;		   	// Master reset input

input       [7:0] txdata;   wire  [7:0] txdata; //trans data

output 		[7:0] data;		// Bidirectional data bus





// Receiver input signal, error and status flags

input	    sin;	                     		// Receive  data line input from IrDA interface

output      rxrdy;      	wire     rxrdy;      	// Data ready to be read

output      parity_error;  	wire     parity_error;  // Parity error flag

output      framing_error; 	wire     framing_error; // Framing error flag

output      overrun;      	wire     overrun;    	// Overrun error flag

wire        [7:0] rxdata;		     		// Intermediate output signals from receiver





// Transmitter output signal and status flag

output      sout;       wire     sout;       // Transmit data line output

output      txrdy;      wire     txrdy;      // Transmitter ready for next byte





//Instantiation of the transmitter module

txmit tx (mclkx16, write, reset, sout, txrdy, txdata);



// Instantiation of the receiver module

rxcver  rx (mclkx16, read, sin, reset, rxrdy, parity_error, framing_error, overrun, rxdata);



// Drives the data bus during data read, otherwise tri-state the data bus

assign 		data = !read ? rxdata : 8'bzzzzzzzz;



endmodule

UART发送模块verliog代码

/******************************************************************

*

* 	File:  		txmit.v

*

* 	Purpose: 	UART transmit description.  Interprets 

*			processor read/write parallel bus cycles 

*			and converts to output serial data.

*		

**********************************************************************/



`timescale 1ns / 100ps



module txmit 

(mclkx16, write, reset, sout, txrdy, data);



input    mclkx16;		// Input clock, 16 x baudrate clock 

input    write;		      	// Transmit write signal

input	 reset;		      	// Reset

output   sout;   reg   sout;   	// Transmit data output	

output   txrdy;		      	// Transmitter ready to recieve next byte to be send

input    [7:0] data;       	// 8-bit input data bus



reg      write1, write2;      	// Delayed write signals

reg      txdone1;        	// txdone delayed signal





// Transmit shift register bits

reg      [7:0] thr;			// Transmit hold register

reg      [7:0] tsr;           		// Transmit shift register, used for shifting out data to sout

reg      tag1, tag2;		      	// Tag bits used for detecting, when the tsr is empty

wire	 paritymode = 1'b1; 		// Initialized to 1 = odd parity, 0 = even parity

reg      txparity;		   	// Parity generation register





// Transmit clock and other control signals

reg      txclk;            		// Transmit clock, i.e. baudrate clock = mclkx16 / 16

wire     txdone;		      	// Set to high, when shifting of byte is done

wire     paritycycle;	   		// Set to high, one cycle next to last shift cycle

reg      txdatardy;        		// Set to high, when data is ready in transmit hold register

reg      [2:0] cnt;           		// Counter used for generating the internal baud rate clock





// Paritycycle = 1 on next to last cycle, this means when tsr[1] gets tag2

assign   paritycycle = tsr[1] && !(tag2 || tag1 || tsr[7] || tsr[6] || tsr[5] || tsr[4] || tsr[3] || tsr[2]);



// txdone = 1 when done shifting, this means when sout gets tag2

assign   txdone = !(tag2 || tag1 || tsr[7] || tsr[6] || tsr[5] || tsr[4] || tsr[3] || tsr[2] || tsr[1] || tsr[0]);



// Ready for new data to be written, when no data is in transmit hold register

assign   txrdy = !txdatardy;





// Latch data[7:0] into the transmit hold register at falling edge of write

always @(write or data)

   if (~write) 

   	thr = data;





// Toggle txclk every 8 counts, which divides the clock by 16, to generate the baud clock

always @(posedge mclkx16 or posedge reset)

if (reset)

	begin

	txclk <= 1'b0;

	cnt <= 3'b000;

	end

else

	begin

	if (cnt == 3'b000)  

	    txclk <= !txclk; 

	cnt <= cnt + 1;

   end





// Shifting out data to sout

always @(posedge txclk or posedge reset)

if (reset)

	begin

	tsr      <= 8'h00;	   	// Reset transmit shift register

	tag2     <= 1'b0;	      	// Reset tag bit

	tag1     <= 1'b0;	      	// Reset tag bit

	txparity <= 1'b0;		// Reset txparty bit

	sout     <= 1'b1;	      	// Idle -> set start bit high

	end

else

	begin

		if (txdone && txdatardy)

			begin

			tsr        <= thr;	      		// Load thr to shift register

			tag2       <= 1'b1;	      		// Set tag bits for detecting when shifting is done 

			tag1       <= 1'b1;	      		// Set tag bits for detecting when shifting is done

			txparity   <= paritymode;		// Set parity mode -> 0 = even parity, 1 = odd parity

	    		sout       <= 1'b0;	      		// Set start bit low

			end

		

		else

	   		begin   

			tsr     <= tsr >> 1;      			// Send LSB first

			tsr[7]  <= tag1;          		 	// Set tsr[7] = tag1  

			tag1    <= tag2;          		 	// Set tag1 = tag2

			tag2    <= 1'b0;          		 	// Set tag2 = 0

			txparity <= txparity ^ tsr[0]; 			// Generate parity

         

         

	    		// Shift out data or parity bit or stop/idle bit.

	     		if (txdone)

		   		sout <= 1'b1;	     		// Output stop/idle bit

	    		else if (paritycycle)

		   		sout <= txparity;   		// Output parity bit

	     		else

				sout <= tsr[0];     		// Shift out data bit

	    	end

	end





always @(posedge mclkx16 or posedge reset)

if (reset) 

	begin

	txdatardy <= 1'b0;

	write2 <= 1'b1;

	write1 <= 1'b1;		

	txdone1 <= 1'b1;		            

	end

else

	begin

	if (write1 &&  !write2)

	   	txdatardy  <= 1'b1;           		// Set txdatardy on rising edge of write



	else if (!txdone &&  txdone1)

	     	txdatardy  <= 1'b0;			// Falling edge of txdone indicated the thr is loaded in the tsr



	// Generate delayed versions of write and txdone signals for edge detection.

	write2 <= write1;

	write1 <= write;

	txdone1 <= txdone;

	

	end 



endmodule

UART接收模块verilog代码

/******************************************************************

*

* 	File:  		rxcver.v

*

* 	Purpose: 	Main UART receiver logic module. Receives 

*			incoming serial data and present parallel

*			byte of data to system.  Includes rxrdy control

*			signals for handshaking of system bus.  Includes

*			control flags for parity, overrun data, and

*			framing errors.

*		

**********************************************************************/



`timescale 1ns / 100ps



module rxcver (mclkx16, read, sin, reset, rxrdy, parity_error, framing_error, overrun, rxdata);



input       	mclkx16;		// Input clock, 16 x baudrate clock

input       	read;			// Read control signal

input	      	sin;		  	// Receive input serial signal  

input	      	reset;			// Reset





// receive status & error signals

output      rxrdy;		   				   // Data received

output      parity_error; 		reg	parity_error;	   // Parity error control signal

output      framing_error;		reg	framing_error;	   // Framing error detect signal

output      overrun;			reg	overrun;	   // Overrun error detect signal



// 8 bit latched output data bus.

output      [7:0] rxdata;		reg 	[7:0]rxdata;	   	// 8-bit output data bus



// Internal control signals.

reg         [3:0] rxcnt;    					  	// Count of clock cycles

reg         rx1, read1, read2, idle1, hunt;     			// Delayed version signals



// Receive shift register bits

reg		[7:0] rhr;	    	     	 // Receive hold register

reg 		[7:0] rsr;  	      	 	 // Receive shift register

reg    		rxparity;	         	 // Received parity bit

reg   		paritygen;		         // Parity generated from received data

reg      	rxstop;	   	      		 // Received data stop bit



// Receive clock and control signals.

reg       	rxclk;     			// Receive data shift clock

reg      	idle;     	   		// idle = 1 when receiver is idle

reg   		rxdatardy;     			// rsdatardy = 1 when data is ready to be read





// Idle signal enables rxclk generation - idle = 0 when not shifting data

// idle = 1 when low "rxstop" bit = rsr[0]

always @(posedge rxclk or posedge reset)

   begin

   	if (reset)

      		idle <= 1'b1;

      	else 

      		idle <= !idle && !rsr[0];

	end





// Synchronizing rxclk to the centerpoint of low leading startbit

always @(posedge mclkx16)

begin



	// A start bit is eight clock times with sin=0 after a falling edge of sin

	if (reset)

	    hunt <= 1'b0;

	else if (idle && !sin && rx1 )	

	    	hunt <= 1'b1;					// Look for falling edge of sin

	else if (!idle || sin )			

	    	hunt <= 1'b0;					// Stop when shifting in data, or a 1 is found on sin

   

   	if (!idle || hunt)					

	   	rxcnt <= rxcnt + 1;				// Count clocks when not idle, or looking for start bit

	else									

	   	rxcnt <= 4'b0001;				// Hold rxcnt = 1, when idle and waiting for falling edge of sin



   	rx1 <= sin;						// Looking for falling edge detect on sin

   

   	rxclk <= rxcnt[3];               			// rxclk = mclkx16 / 16



end



// When not idle, sample data at the sin input and create parity

always @(posedge rxclk or posedge reset)

if (reset)

	begin

	rsr        <= 8'b11111111;		// Initialize shift register

	rxparity   <= 1'b1;        		// Set to 1 -> for data shifting          

	paritygen  <= 1'b1;           		// Set to 1 -> odd parity mode

	rxstop     <= 1'b0;         		// Controls idle = 1, when rsr[0] gets rxstop bit

	end

	

else

  	begin												      

	if (idle)

		begin

		rsr        <= 8'b11111111;		// Initialize shift register

		rxparity   <= 1'b1;        		// Set to 1 -> for data shifting         

		paritygen  <= 1'b1;           		// Set to 1 -> odd parity mode

		rxstop     <= 1'b0;         		// Controls idle = 1, when rsr[0] gets rxstop bit

		end

		

	else

		begin

		rsr         <= rsr >> 1;            	// Right shift sin shift register   

		rsr[7]      <= rxparity;            	// Load rsr[7] with rxparity

		rxparity    <= rxstop;              	// Load rxparity with rxstop

		rxstop      <= sin;                  	// Load rxstop with sin

        	paritygen   <= paritygen ^ rxstop;  	// Generate running parity

        	end

	end





// Generate status & error flags

always @(posedge mclkx16 or posedge reset)

if (reset) 

	begin

	rhr         	<= 8'h00;

	rxdatardy   	<= 1'b0;

	overrun	    	<= 1'b0;

	parity_error   	<= 1'b0;

	framing_error  	<= 1'b0;

	idle1       	<= 1'b1; 

	read2       	<= 1'b1; 

	read1       	<= 1'b1; 

	end

else	

	begin

	

	// Look for rising edge of idle and update output registers

	if (idle && !idle1)				   

	 	begin

		if (rxdatardy)

			overrun <= 1'b1;				// Overrun error, if previous data still in holding register

		else

			begin

			overrun <= 1'b0;				// No overrun error, since holding register is empty

			rhr <= rsr;					// Update holding register with contens of shift register

			parity_error <= paritygen;    			// paritygen = 1, if parity error

			framing_error <=  !rxstop;			// framing_error, if stop bit is not 1

			rxdatardy <= 1'b1;				// Data is ready for reading flag

			end

		end

 	   

 	   

 	// Clear error and data registers when data is read

	if (!read2 &&  read1)

		begin 					

	   	rxdatardy  	<= 1'b0;

	  	parity_error  	<= 1'b0;

	   	framing_error 	<= 1'b0;

	   	overrun    	<= 1'b0;

	   	end 



		idle1 <= idle;				        // Edge detect on idle signal

		read2 <= read1;	   				// 2 cycle delayed version of read - edge detection

		read1 <= read;					// 1 cycle delayed version of read - edge detection

   	end



assign    rxrdy = rxdatardy;		   		// Receive data ready output signal



always @(read or rhr)				   	// Latch data output when read goes low

if (~read) 

	rxdata = rhr; 



endmodule

 

你可能感兴趣的:(基于zedboard编写verilog配置ESP8266 wifi模块参考设计)