这是本文档旧的修订版!
22-1(a)读操作时序
22-1(b)写操作时序
本实验基于ARM+FPGA构架,通过SPI实现ARM与FPGA之间通信,ARM通过SPI总线向FPGA发送相关指令;FPGA内部例化的FIFO作为ARM的外部存储器,根据指令进行对应的读写操作,从而实现ARM对FPGA内部FIFO的数据读写功能。实验流程较为简单,重点是掌握FIFO IP核的调用及时序的描述。
四、 FIFO IP核调用 1、新建一个工程名为fifo的工程,然后选中工程右击,下拉菜单中选择New Source…,如图22-2所示。
图22-2 2、弹出窗口选择新建IP核文件,既IP(CORE Generator & Architecture Wizard)选项。右侧的File name栏给IP核文件命名为fifo,点击Next。
图22-3 3、弹出IP核选择界面,点击Memories & Storage Elements 前面的“+”,再点击FIFOs前面的“+”,然后点击FIFO Generator选定,点击Next。
图22-4 4、点击Finish。
图22-5 5、弹出FIFO IP核相关参数设置界面,如下图所示,这里的Interface Type 选择Native,然后点击Next。
图22-6 6、选择时钟和存储器类型。本实验对FIFO的读和写是独立操作的,因此时钟选择异步模式;block RAM 是FPGA内部定制的RAM资源,Distributed RAM则是由LUT构成的RAM资源。所以本实验FIFO Implementation栏下选择Independent Clocks(RD_CLK,WR_CLK) Block RAM,然后点击Next。
图22-7 7、如下界面中设置Read Mode为Standard FIFO,;设置FIFO的读和写的位宽为8,写深度参数为1024,读深度根据这几个参数自动计算出来为1024;这里需要注意的是Write Depth参数设置为1024,Actual Write Depth为1023。
图22-8 8、此界面默认选项即可,点击Next。
图22-9 9、这里Initialization栏下取消复位引脚,然后点击Next。
图22-10 10、此界面默认,点击Next。
图22-11 11、点击Generate,生成FIFO IP核文件。
图22-12 12、在工程目录栏选中FIFO IP核文件,然后点击Processes: u0-spi_fifo窗口CORE Generator前面的“+”。双击View HDL Instantiation Template,可以看到所有需要例化的FIFO端口信号。
图22-13
//------------------------------------------------// //spi_fifo //负责存储SPI通信的数据 //FIFO:先进先出,主要用于缓存数据。 spi_fifo u0( .data(receive_byte), .wrclk(wrclk), .wrreq(wrreq), .wrfull(), .rdclk(rdclk), .rdreq(rdreq), .rdempty(), .q(data_out) ); case(rx_state) rx_idle_state:begin//空闲状态,匹配伪命令时钟 rx_state <= rx_judge_state; end rx_judge_state:begin//接收指令字节,判断指令含义分配跳转状态机状态 case(receive_byte) 8'h01:begin//存储指令编码(获取设备状态) order <= receive_byte; end 8'h04:begin rx_state <= rx_wr_add_state; order <= receive_byte; end 8'h07:begin rx_state <= rx_rd_add_state; order <= receive_byte; end default:; endcase end rx_wr_add_state:begin//控制写请求信号 case(rx_cnt) 8'd0:begin rx_cnt <= rx_cnt + 1'd1; end 8'd1:begin wrreq_r <= 1'd1; end default:begin end endcase end rx_rd_add_state:begin//控制读请求信号,通过计数器rd_cnt控制读请求 case(rx_cnt) //信号的使能状态 8'd0:begin rx_cnt <= rx_cnt + 1'd1; end 8'd1:begin rdreq_r <= 1'd1; rx_cnt <= rx_cnt + 1'd1; rd_cnt <= rd_cnt + 1'd1; end 8'd2:begin if(rd_cnt == 12'd1023) begin rd_cnt <= 12'd0; rdreq_r <= 1'd1; end else begin rd_cnt <= rd_cnt + 1'd1; end end default:; endcase end endcase
图22-14
图22-15