1`timescale 1ns / 1ps 2/* 3 * This software is Copyright (c) 2016 Denis Burykin 4 * [denis_burykin yahoo com], [denis-burykin2014 yandex ru] 5 * and it is hereby released to the general public under the following terms: 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted. 8 * 9 */ 10 11//***************************************************************************** 12// 13// High-Speed communtcation to USB device controller's Slave FIFO 14// 15// For Slave FIFO's signaling and timing diagram, see CY7C68013-56PVC-Datasheet 16// 17// Version 1 comment: 18// 19// It is implemented on a state machine with outputs dependent on both input 20// and internal state. That's slow and is unable to operate at 48 MHz IFCLK. 21// 22// Version 2 improvements: 23// 24// 1. Removed asynchronous circuitry. That allows to operate at 48 MHz, 25// removes synchronization to CPU issues. 26// 2. I/O registers placed most close to pins - into ILOGIC/OLOGIC components. 27// That removes the nesessity to manually allocate areas in UCF file. 28// IFCLK appears to arrive too late, added some phase backshift. 29// 3. One cycle delay when switching control outputs into Z-state on CS deassertion 30// so controls for Slave FIFO (active low) always in a defined state. 31// 32//***************************************************************************** 33 34module hs_io_v2 #( 35 parameter USB_ENDPOINT_IN = 2, // from the point of view from the host 36 parameter USB_ENDPOINT_OUT = 6 37 )( 38 input IFCLK, 39 // Low CS puts all outputs into Z-state, 40 // exactly as examples/intraffic is doing 41 input CS, 42 input out_z_wait1, 43 44 // enable read/write 45 // Deasserted EN doesn't perform read/write, 46 // keeps signals for Slave FIFO in proper state. 47 input EN, 48 49 // Attention: attempt to send data to FPGA not aligned to 50 // 2-byte word would result in a junk in upper byte 51 inout [15:0] FIFO_DATA, 52 output FIFOADR0, 53 output FIFOADR1, 54 // Following signals are active low. 55 output SLOE, // Slave output enable 56 output SLRD, 57 output SLWR, 58 output PKTEND, 59 // FLAGA/B/C are fixed (independent from FIFOADR) 60 input FLAGA, // PROG_FULL 61 input FLAGB, // FULL 62 input FLAGC, // EMPTY 63 64 // write into some internal FIFO 65 output [15:0] dout, 66 output wr_en, 67 input almost_full, 68 69 // read from some internal FIFO 70 input [15:0] din, 71 output rd_en, 72 input empty, 73 74 // status information 75 output [7:0] io_timeout, // in ~1us intervals @30MHz IFCLK 76 output reg io_fsm_error = 0, // CS or EN deasserted while active I/O 77 output reg sfifo_not_empty = 0, 78 output reg io_err_write = 0 79 ); 80 81 reg rw_direction = 0; // 1: FPGA writes 82 83 always @(posedge IFCLK) 84 if (CS & EN) 85 sfifo_not_empty <= FLAGC_R; 86 87 // Timeout 88 localparam TIMEOUT_MSB = 12; 89 reg [TIMEOUT_MSB:0] timeout = {TIMEOUT_MSB+1{1'b1}}; 90 assign io_timeout = timeout[TIMEOUT_MSB : TIMEOUT_MSB-7]; 91 92 93 // FIFOADR (Address for USB endpoint buffer) 94 // - at 48 MHz, sometimes takes 2 cycles to propagate 95 localparam USB_EP_OUT_B = (USB_ENDPOINT_OUT-2) >> 1; 96 localparam USB_EP_IN_B = (USB_ENDPOINT_IN-2) >> 1; 97 assign {FIFOADR1, FIFOADR0} = 98 out_z_wait1 ? 2'bz : 99 rw_direction ? USB_EP_IN_B[1:0] : 100 USB_EP_OUT_B[1:0]; 101 102 103 // ************************* 104 // 105 // High-Speed Input 106 // 107 // ************************* 108 109 // FPGA's Input register (data-out from hs_io) 110 (* IOB="true" *) reg [15:0] input_r; 111 assign dout = input_r; 112 always @(posedge IFCLK) 113 input_r <= FIFO_DATA; 114 115 (* IOB="true" *) reg FLAGC_R = 0; 116 always @(posedge IFCLK) 117 FLAGC_R <= FLAGC; 118 119 (* IOB="true" *) reg SLOE_R = 1; 120 assign SLOE = out_z_wait1 ? 1'bz : SLOE_R; 121 122 (* IOB="true" *) reg SLRD_R = 1; 123 assign SLRD = out_z_wait1 ? 1'bz : SLRD_R; 124 125 // input_r_ok indicates there was read last cycle (SLRD was active) 126 reg input_r_ok = 0; 127 always @(posedge IFCLK) 128 input_r_ok <= ~SLRD_R; 129 assign wr_en = input_r_ok & FLAGC_R; 130 131 132 // ************************* 133 // 134 // High-Speed Output 135 // 136 // ************************* 137 138 // FLAGA(active low) is configured to be active when 0 bytes in buffer 139 (* IOB="true" *) reg FLAGA_R = 1; 140 always @(posedge IFCLK) 141 FLAGA_R <= FLAGA; 142 143 (* IOB="true" *) reg FLAGB_R = 0; 144 always @(posedge IFCLK) 145 FLAGB_R <= FLAGB; 146 147 (* IOB="true" *) reg SLWR_R = 1; 148 assign SLWR = out_z_wait1 ? 1'bz : SLWR_R; 149 150 // FPGA's output register. 151 // valid data must be present on output 9.2 ns before write 152 (* IOB="true" *) reg [15:0] output_r = 0; 153 // Tristate-enable FF inside OLOGIC component 154 (* IOB="true" *) reg out_z = 1; 155 assign FIFO_DATA = out_z ? 16'bz : output_r; 156 always @(posedge IFCLK) 157 out_z <= ~(CS & EN & rw_direction); 158 159 // Flag indicates valid data in output register. 160 // Could be better if output FIFO had almost_empty flag. 161 reg output_r_valid = 0; 162 assign rd_en = (~SLWR_R | io_state == IO_STATE_WR_SETUP1 & ~output_r_valid); 163 164 (* IOB="true" *) reg PKTEND_R = 1; 165 assign PKTEND = out_z_wait1 ? 1'bz : PKTEND_R; 166 167 168 // It works as follows: 169 // 1. reads as long as possible; 170 // 2. writes up to USB_PKT_SIZE. 171 localparam USB_PKT_SIZE = 256; // in 16-bit words 172 reg [8:0] word_counter = 0; 173 174 // Finally deal with PKTEND issue. 175 // - when output FIFO is in mode_limit, there's no problem: 176 // FIFO already has all the data, so it outputs every cycle 177 // until EMPTY. 178 // - when mode_limit is off, the data might arrive from FPGA's output FIFO 179 // in small pieces such as 2-8 bytes or so, with intervals like 2-4 cycles. 180 // That might result in partial reads by the host and overall performance degradation. 181 // 182 localparam PKTEND_WR_TIMEOUT = 5; 183 reg [2:0] wr_timeout = 0; 184 185 186 //localparam IO_STATE_RESET = 1; 187 localparam IO_STATE_READ_SETUP0 = 2; 188 localparam IO_STATE_READ_SETUP1 = 3; 189 localparam IO_STATE_READ_SETUP2 = 4; 190 localparam IO_STATE_READ = 6; 191 localparam IO_STATE_WR_SETUP0 = 7; 192 localparam IO_STATE_WR_SETUP1 = 8; 193 localparam IO_STATE_WR_SETUP2 = 9; 194 localparam IO_STATE_WR = 11; 195 localparam IO_STATE_DISABLED = 13; 196 localparam IO_STATE_WR_WAIT = 14; 197 localparam IO_STATE_PKT_COMMIT = 15; 198 199 (* FSM_EXTRACT="YES" *) 200 reg [4:0] io_state = IO_STATE_DISABLED; 201 202 always @(posedge IFCLK) 203 begin 204 if ( ! (&timeout[TIMEOUT_MSB : TIMEOUT_MSB-7]) 205 & io_state != IO_STATE_READ & io_state != IO_STATE_WR) 206 timeout <= timeout + 1'b1; 207 208 // Disabled: EN is off, outputs in proper state 209 if (io_state == IO_STATE_DISABLED) begin 210 if (CS & EN) 211 io_state <= IO_STATE_READ_SETUP0; 212 end 213 214 else if (~CS | ~EN) begin 215 // Expecting EZ-USB to disable hs_io before selecting other fpga 216 if (!io_timeout | (~CS & EN)) 217 io_fsm_error <= 1; 218 219 SLOE_R <= 1; 220 SLRD_R <= 1; 221 SLWR_R <= 1; 222 output_r_valid <= 0; 223 PKTEND_R <= 1; 224 rw_direction <= 0; 225 io_state <= IO_STATE_DISABLED; 226 end 227 228 else // CS & EN 229 (* FULL_CASE, PARALLEL_CASE *) case (io_state) 230 231 IO_STATE_READ_SETUP0: begin 232 if (almost_full | ~FLAGC_R) 233 io_state <= IO_STATE_WR_SETUP0; 234 else begin 235 io_state <= IO_STATE_READ_SETUP1; 236 end 237 end 238 239 IO_STATE_READ_SETUP1: begin 240 io_state <= IO_STATE_READ_SETUP2; 241 end 242 243 IO_STATE_READ_SETUP2: begin 244 // must assert 18.7 ns before read 245 SLOE_R <= 0; 246 SLRD_R <= 0; 247 io_state <= IO_STATE_READ; 248 end 249 250 IO_STATE_READ: begin 251 if (!almost_full & FLAGC_R) begin 252 timeout <= 0; 253 end 254 else begin 255 SLOE_R <= 1; 256 SLRD_R <= 1; 257 io_state <= IO_STATE_WR_SETUP0; 258 end 259 end 260 261 IO_STATE_WR_SETUP0: begin 262 if ((empty & ~output_r_valid) | FLAGA_R) 263 io_state <= IO_STATE_READ_SETUP0; 264 // go on transmit 265 else begin 266 rw_direction <= 1; 267 word_counter <= 0; 268 io_state <= IO_STATE_WR_SETUP1; 269 end 270 end 271 272 IO_STATE_WR_SETUP1: begin 273 if (~output_r_valid) begin 274 output_r <= din; 275 output_r_valid <= 1; 276 end 277 io_state <= IO_STATE_WR_SETUP2; 278 end 279 280 IO_STATE_WR_SETUP2: begin 281 // must assert 18.1 ns before write 282 SLWR_R <= 0; 283 io_state <= IO_STATE_WR; 284 end 285 286 IO_STATE_WR: begin 287 output_r <= din; 288 timeout <= 0; 289 wr_timeout <= 0; 290 word_counter <= word_counter + 1'b1; 291 if (empty) 292 output_r_valid <= 0; 293 294 if (word_counter == USB_PKT_SIZE - 1) begin 295 SLWR_R <= 1; 296 rw_direction <= 0; 297 io_state <= IO_STATE_READ_SETUP0; 298 end 299 else if (empty) begin 300 SLWR_R <= 1; 301 io_state <= IO_STATE_WR_WAIT; 302 end 303 304 if (~FLAGB_R) 305 io_err_write <= 1; 306 end 307 308 IO_STATE_WR_WAIT: begin 309 wr_timeout <= wr_timeout + 1'b1; 310 311 if (wr_timeout == PKTEND_WR_TIMEOUT) begin 312 PKTEND_R <= 0; 313 io_state <= IO_STATE_PKT_COMMIT; 314 end 315 else if (!empty) 316 io_state <= IO_STATE_WR_SETUP1; 317 end 318 319 IO_STATE_PKT_COMMIT: begin 320 PKTEND_R <= 1; 321 rw_direction <= 0; 322 io_state <= IO_STATE_READ_SETUP0; 323 end 324 325 endcase 326 // CS & EN 327 328 end // IFCLK 329 330 331endmodule 332 333