|
用FPGA做图像处理算法时,经常需要传输大数据量的图像数据到FPGA或者从FPGA到PC。这样就需要简单快速的传输方法。单片机常用串口,但速度有限。并口是PC机基本配置,传输速度相对较快。且EPP协议时序比较简单,故本文基于FPGA用Verilog HDL实现并口EPP协议,与PC机通讯。 并口有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 machinealways @ (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 以上模块实现的状态机转换图如下:图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;} |
|