FX2LP与FPGA的简单批量回环
我需求将FPGA处理的视频数据通过USB发送给电脑,先实现一个小目标,做一个简单的数据回环。
利用赛普拉斯EZ-USB FX2LP系列USB2.0的接口控制器,固件配置好为异步批量模式,并通过官方提供的Control Center进行测试。
上图是FX2LP连接至FPGA时所需的硬件连接
它们之间的接口信号说明如下
- FLAGA OUT FIFO空标志位,高电平表示非空
- FLAGC IN FIFO满标志位,高电平表示不满
- SLCS 片选信号,低电平有效
- SLOE 输出使能,低电平有效
- SLRD 读控制,低电平有效
- SLWR 写控制,低电平有效
- FIFOADR[1:0] FIFO地址选择,2'b00为OUT FIFO地址,2'b10为IN FIFO地址
- FD[15:0] 双向数据信号
设计时参看规格书给出的时序图
从时序图中,大致可以看出在异步模式下,数据是在SLWR和SLRD的上升沿读入读出,
设计时序如上图,时钟选取为10MHz
下面附上具体代码
module usb_loop( input sys_clk_p , input sys_clk_n , input reset_n , input usb_flaga , input usb_flagc , output reg [1:0] usb_fifoaddr , output reg usb_slcs , output reg usb_sloe , output reg usb_slrd , output reg usb_slwr , inout [15:0] usb_fd ); reg usb_fd_en; reg [15:0] usb_data; // Clock // differential clock -> single clock -> 10MHz clock wire sys_clk ; IBUFGDS buf_clk ( .I (sys_clk_p ), .IB (sys_clk_n ), .O (sys_clk ) ); pll_10 u_pll_10 ( .clk_in1 (sys_clk ), // 200Mhz .clk_out1 (clk_10 ) // 10Mhz ); // count reg flag_cnt; reg [2:0] cnt; wire add_cnt; wire end_cnt; always @(posedge clk_10 or negedge reset_n) begin if(reset_n == 0) cnt <= 0; else if(add_cnt) begin if(end_cnt) cnt <= 0; else cnt <= cnt + 1; end end assign add_cnt = flag_cnt; assign end_cnt = add_cnt && cnt == 6 - 1; always @(posedge clk_10 or negedge reset_n) begin if(reset_n == 0) flag_cnt <= 0; else if(flag_cnt == 0 && usb_flaga == 1 && usb_flagc == 1) flag_cnt <= 1; else if(end_cnt) flag_cnt <= 0; end always @(posedge clk_10 or negedge reset_n) begin if(reset_n == 0) usb_slcs <= 1; else usb_slcs <= 0; end /* cnt 0 1 2 3 4 5 addr 0 0 0 2 2 2 slrd 1 0 1 1 1 1 sloe 1 0 1 1 1 1 slwr 1 1 1 1 0 1 */ always @(posedge clk_10 or negedge reset_n) begin if(reset_n == 0) usb_fifoaddr <= 0; else if(add_cnt && cnt == 3 - 1) usb_fifoaddr <= 2'b10; else if(end_cnt) usb_fifoaddr <= 0; end always @(posedge clk_10 or negedge reset_n) begin if(reset_n == 0) usb_slrd <= 1; else if(add_cnt && cnt == 1 - 1) usb_slrd <= 0; else if(add_cnt && cnt == 2 - 1) usb_slrd <= 1; end always @(posedge clk_10 or negedge reset_n) begin if(reset_n == 0) usb_sloe <= 1; else if(add_cnt && cnt == 1 - 1) usb_sloe <= 0; else if(add_cnt && cnt == 2 - 1) usb_sloe <= 1; end always @(posedge clk_10 or negedge reset_n) begin if(reset_n == 0) usb_slwr <= 1; else if(add_cnt && cnt == 4 - 1) usb_slwr <= 0; else if(add_cnt && cnt == 5 - 1) usb_slwr <= 1; end assign usb_fd = (usb_fd_en) ? usb_data : 16'hz; always @(posedge clk_10 or negedge reset_n) begin if(reset_n == 0) usb_data <= 0; else if(add_cnt && cnt == 2 - 1) usb_data <= usb_fd; end always @(posedge clk_10 or negedge reset_n) begin if(reset_n == 0) usb_fd_en <= 0; else if(add_cnt && cnt == 3 - 1) usb_fd_en <= 1; else if(end_cnt) usb_fd_en <= 0; end endmodule