原创 基于FPGA实现并口EPP协议

2008-8-9 14:48 3846 4 4 分类: FPGA/CPLD

作者:xdkui


基于FPGA实现并口EPP协议rar


FPGA做图像处理算法时,经常需要传输大数据量的图像数据到FPGA或者从FPGA到PC。这样就需要简单快速的传输方法。单片机常用串口,但速度有限。并口是PC机基本配置,传输速度相对较快。且EPP协议时序比较简单,故本文基于FPGA用Verilog HDL实现并口EPP协议,与PC机通讯。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


    并口有SPP,EPP,ECP3种模式,具体区别就不说了。选用EPP模式。其特性,时序及PC机端的IO端口地址见附件里的资料(Interfacing the Enhanced Parallel Port)。下面为用有限状态机实现的EPP协议(epp.v):


module EPP (EPP_Write0,EPP_Data,EPP_Interrupt,EPP_Wait,EPP_DataStrobe0,EPP_Reset0,EPP_AddressStrobe0,,clk24,rst,led);


 


    //EPP interface signals


    input EPP_Write0;


    inout [7:0] EPP_Data;


    output EPP_Interrupt;


    output EPP_Wait;


    input EPP_DataStrobe0;


    input EPP_Reset0;


    input EPP_AddressStrobe0;


    //


    input clk24;


    input rst;


    output led;


 


/******************** module regs define ***************************/


    //regs related to EPP


    reg EPP_Interrupt,EPP_Wait;


    reg EPP_Write,EPP_DataStrobe,EPP_AddressStrobe,EPP_Reset;


    reg [7:0] epp_dataout,epp_datain;


 


    //internal regs


    reg led;


    reg [2:0] epp_state;


    reg [7:0] cmd;//from epp address write


 


/**********************  module constant define *****************/


    //parameters EPP state parameter EPP_IDLE=3'b000,EPP_WAIT_ADDRREAD=3'b001,EPP_WAIT_ADDRWRITE=3'b010,


        EPP_WAIT_DATAREAD=3'b011,EPP_WAIT_DATAWRITE=3'b100;


/*********************  module internal logic  ******************/


 


//并口输入进来的信号,需要同步。加入锁存器


always @ (posedge clk24)


begin


    if(!rst)


        EPP_Write<=1;


    else


        EPP_Write<=EPP_Write0;


end


 


always @ (posedge clk24)


begin


    if(!rst)


        EPP_DataStrobe<=1;


    else


        EPP_DataStrobe<=EPP_DataStrobe0;


end


 


always @ (posedge clk24)


begin


    if(!rst)


        EPP_AddressStrobe<=1;


    else


        EPP_AddressStrobe<=EPP_AddressStrobe0;


end


 


always @ (posedge clk24)


begin


    if(!rst)


        EPP_Reset<=1;


    else


        EPP_Reset<=EPP_Reset0;


end


 


//EPP state machine


always @ (posedge clk24)


begin


    if(!rst )


    begin


        epp_state<=EPP_IDLE;


        EPP_Interrupt<=0;


        EPP_Wait<=0;


        epp_dataout<=8'b0;


        epp_datain<=8'b0;


        cmd<=8'b0;


        //SRAM_Addr<=20'b0;


        sram_raddr<=20'b0;


        sram_waddr<=20'd0;


    end


    else


        case(epp_state)


            EPP_IDLE:


            begin


                epp_state<=EPP_IDLE;


                EPP_Wait<=0;


                if(!EPP_AddressStrobe)


                begin


                   if(EPP_Write)


                   begin//EPP address read


                       epp_dataout<=EPP地址读,这里是要从地址寄存器读取的数据;


                       EPP_Wait<=1;


                       epp_state<=EPP_WAIT_ADDRREAD;


                   end


                   else


                   begin//EPP address write    cmd come from EPP address write


                       cmd<=EPP_Data;//EPP_Data为EPP地址寄存器写入的数据


                       EPP_Wait<=1;


                       epp_state<=EPP_WAIT_ADDRWRITE;


                   end


                end


                else if(!EPP_DataStrobe)


                begin


                   if(EPP_Write)


                   begin//EPP data read


                       epp_dataout<=EPP数据读,这里是要从数据寄存器读取的数据;


                       EPP_Wait<=1;


                       epp_state<=EPP_WAIT_DATAREAD;


                   end


                   else


                   begin//EPP data write


                       epp_datain<=EPP_Data;//EPP数据写,是写入数据寄存器的数据


                       EPP_Wait<=1;


                       epp_state<=EPP_WAIT_DATAWRITE;


                   end


                end


            end


            EPP_WAIT_ADDRREAD:


            begin


                if(EPP_AddressStrobe)


                begin


                   EPP_Wait<=0;


                   //led<=~led;


                   epp_state<=EPP_IDLE;


                end


            end


            EPP_WAIT_ADDRWRITE:


            begin


                if(EPP_AddressStrobe)


                begin


                   EPP_Wait<=0;


                   epp_state<=EPP_IDLE;


                end


            end


            EPP_WAIT_DATAREAD:


            begin


                if(EPP_DataStrobe)


                begin


                   EPP_Wait<=0;


                   //led<=~led;


                   epp_state<=EPP_IDLE;


                   sram_raddr<=sram_raddr+1;


                end


            end


            EPP_WAIT_DATAWRITE:


            begin


                if(EPP_DataStrobe)


                begin


                   EPP_Wait<=0;


                   //led<=~led;


                    epp_state<=EPP_IDLE;


                   sram_waddr<=sram_waddr+1;


                end


            end


            default: epp_state<=EPP_IDLE;


        endcase


    end


 


assign EPP_Data=((epp_state==EPP_WAIT_DATAREAD)||(epp_state==EPP_WAIT_ADDRREAD))?epp_dataout:8'bz;


 


endmodule      


    以上模块实现的状态机转换图如下:


<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />060919171923.jpg


1 并口EPP状态转换图


   


    为上面模块指定IO口,编程进FPGA,通过并口线连接到PC机。即可在PC中读写IO端口与FPGA通讯。在Windows NT平台下,IO口属于保护资源,需要写驱动或者第3方的开发库,我这里使用DLPortIO库。即可使用该库导出的DlPortReadPortUchar和DlPortWritePortUchar函数读写EPP端口。EPP地址寄存器为基地址+3,EPP数据寄存器为基地址+4。


    比如给EPP地址寄存器写入数据0,则:


DlPortWritePortUchar(PORTBASE+3,addmask(PORTBASE+3,0));


则在epp.v里的“cmd<=EPP_Data;//EPP_Data为EPP地址寄存器写入的数据”处即可得到PC写入的数据0。


    另外,由于并口内部有的位有反向器,故先要用addmask函数处理要写入的数据,该函数如下:


#define PORTBASE 0x378   //EPP端口基地址


 


unsigned char addmask(UINT port,unsigned char value)


{


    UCHAR mask;


    switch(port) //并口有些IO口的位写入1得时候输出是0,写入0得时候输出是1,可自己测试。。。。


    {


    case PORTBASE:


        mask=value^0x00;


        break;


    case PORTBASE+1:


        mask=value^0x80;


        break;


    case PORTBASE+2:


        mask=value^0x0B;


        break;


    case PORTBASE+3:


        mask=value^0x00;


        break;


    case PORTBASE+4:


        mask=value^0x00;


        break;


    default:


        mask=value;


    }


    return mask;


}

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
4
关闭 站长推荐上一条 /3 下一条