Use DMA for SCSI and SD card transfers for a massive performance boost.
[SCSI2SD-V6.git] / software / SCSI2SD / SCSI2SD.cydsn / scsiTarget / scsiTarget.v
1 \r
2 //`#start header` -- edit after this line, do not edit this line\r
3 //      Copyright (C) 2013 Michael McMaster <michael@codesrc.com>\r
4 //\r
5 //      This file is part of SCSI2SD.\r
6 //\r
7 //      SCSI2SD is free software: you can redistribute it and/or modify\r
8 //      it under the terms of the GNU General Public License as published by\r
9 //      the Free Software Foundation, either version 3 of the License, or\r
10 //      (at your option) any later version.\r
11 //\r
12 //      SCSI2SD is distributed in the hope that it will be useful,\r
13 //      but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 //      GNU General Public License for more details.\r
16 //\r
17 //      You should have received a copy of the GNU General Public License\r
18 //      along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.\r
19 `include "cypress.v"\r
20 //`#end` -- edit above this line, do not edit this line\r
21 // Generated on 10/16/2013 at 00:01\r
22 // Component: scsiTarget\r
23 module scsiTarget (\r
24         output [7:0] DBx_out, // Active High, connected to SCSI bus via inverter\r
25         output  REQ, // Active High, connected to SCSI bus via inverter\r
26         input   nACK, // Active LOW, connected directly to SCSI bus.\r
27         input  [7:0] nDBx_in, // Active LOW, connected directly to SCSI bus.\r
28         input   IO, // Active High, set by CPU via status register.\r
29         input   nRST, // Active LOW, connected directly to SCSI bus.\r
30         input   clk,\r
31         output tx_intr,\r
32         output rx_intr\r
33 );\r
34 \r
35 \r
36 //`#start body` -- edit after this line, do not edit this line\r
37 \r
38 /////////////////////////////////////////////////////////////////////////////\r
39 // Force Clock Sync\r
40 /////////////////////////////////////////////////////////////////////////////\r
41 // The udb_clock_enable primitive component is used to indicate that the input\r
42 // clock must always be synchronous and if not implement synchronizers to make\r
43 // it synchronous.\r
44 wire op_clk;\r
45 cy_psoc3_udb_clock_enable_v1_0 #(.sync_mode(`TRUE)) ClkSync\r
46 (\r
47     .clock_in(clk),\r
48     .enable(1'b1),\r
49     .clock_out(op_clk)\r
50 );\r
51 \r
52 /////////////////////////////////////////////////////////////////////////////\r
53 // CONSTANTS\r
54 /////////////////////////////////////////////////////////////////////////////\r
55 localparam IO_WRITE = 1'b1;\r
56 localparam IO_READ = 1'b0;\r
57 \r
58 /////////////////////////////////////////////////////////////////////////////\r
59 // STATE MACHINE\r
60 /////////////////////////////////////////////////////////////////////////////\r
61 // TX States:\r
62 // IDLE\r
63 //     Wait for the SCSI Initiator to be ready\r
64 // FIFOLOAD\r
65 //     Load F0 into A0. Feed (old) A0 into the ALU SRCA.\r
66 // TX\r
67 //     Load data register from PO. PO is fed by A0 going into the ALU via SRCA\r
68 //     A0 must remain unchanged.\r
69 // DESKEW_INIT\r
70 //     DBx output signals will be output in this state\r
71 //     Load deskew clock count into A0 from D0\r
72 // DESKEW\r
73 //     DBx output signals will be output in this state\r
74 //     Wait for the SCSI deskew time of 55ns. (DEC A0).\r
75 //     A1 must be fed into SRCA, so PO is now useless.\r
76 // READY\r
77 //     REQ and DBx output signals will be output in this state\r
78 //     Wait for acknowledgement from the SCSI initiator\r
79 //     Wait for space in output fifo\r
80 // RX\r
81 //     Dummy state for flow control.\r
82 //     REQ signal will be output in this state\r
83 //     PI enabled for input into ALU "PASS" operation, storing into F1.\r
84 //\r
85 // RX States:\r
86 // IDLE\r
87 //     Wait for a dummy "enabling" entry in the input FIFO,\r
88 //     and for the SCSI Initiator to be ready\r
89 // FIFOLOAD\r
90 //     Load F0 into A0.\r
91 //     The input FIFO is used to control the number of bytes we attempt to\r
92 //     read from the SCSI bus.\r
93 // READY\r
94 //     REQ signal will be output in this state\r
95 //     Wait for the initiator to send a byte on the SCSI bus.\r
96 //     Wait for space in output fifo\r
97 // RX\r
98 //     REQ signal will be output in this state\r
99 //     PI enabled for input into ALU "PASS" operation, storing into F1.\r
100 \r
101 \r
102 localparam STATE_IDLE = 3'b000;\r
103 localparam STATE_FIFOLOAD = 3'b001;\r
104 localparam STATE_TX = 3'b010;\r
105 localparam STATE_DESKEW_INIT = 3'b011;\r
106 localparam STATE_DESKEW = 3'b100;\r
107 // This state intentionally not used.\r
108 localparam STATE_READY = 3'b110;\r
109 localparam STATE_RX = 3'b111;\r
110 \r
111 // state selects the datapath register.\r
112 reg[2:0] state;\r
113 \r
114 // Data being read/written from/to the SCSI bus\r
115 reg[7:0] data;\r
116 \r
117 // Set by the datapath zero detector (z1). High when A1 counts down to zero.\r
118 wire deskewComplete;\r
119 \r
120 // Parallel input to the datapath SRCA.\r
121 // Selected for input through to the ALU if CFB EN bit set for the datapath\r
122 // state and enabled by PI DYN bit in CFG15-14\r
123 wire[7:0] pi;\r
124 \r
125 // Parallel output from the selected SRCA value (A0 or A1) to the ALU.\r
126 wire[7:0] po;\r
127 \r
128 // Set true to trigger storing A1 into F1.\r
129 wire fifoStore;\r
130 \r
131 // Set Output Pins\r
132 assign REQ = state[1] & state[2]; // STATE_READY & STATE_RX\r
133 assign DBx_out[7:0] = data;\r
134 assign pi[7:0] = ~nDBx_in[7:0]; // Invert active low scsi bus\r
135 assign fifoStore = (state == STATE_RX) ? 1'b1 : 1'b0;\r
136 \r
137 \r
138 /////////////////////////////////////////////////////////////////////////////\r
139 // FIFO Status Register\r
140 /////////////////////////////////////////////////////////////////////////////\r
141 // Status Register: scsiTarget_StatusReg__STATUS_REG\r
142 //     Bit 0: Tx FIFO not full\r
143 //     Bit 1: Rx FIFO not empty\r
144 //     Bit 2: Tx FIFO empty\r
145 //     Bit 3: Rx FIFO full\r
146 //     Bit 4: TX Complete. Fifos empty and idle.\r
147 //\r
148 // TX FIFO Register: scsiTarget_scsiTarget_u0__F0_REG\r
149 // RX FIFO Register: scsiTarget_scsiTarget_u0__F1_REG\r
150 // Use with CY_GET_REG8 and CY_SET_REG8\r
151 wire f0_bus_stat;   // Tx FIFO not full\r
152 wire f0_blk_stat;       // Tx FIFO empty\r
153 wire f1_bus_stat;       // Rx FIFO not empty\r
154 wire f1_blk_stat;       // Rx FIFO full\r
155 wire txComplete = f0_blk_stat && (state == STATE_IDLE);\r
156 cy_psoc3_status #(.cy_force_order(1), .cy_md_select(8'h00)) StatusReg\r
157 (\r
158     /* input          */  .clock(op_clk),\r
159     /* input  [04:00] */  .status({3'b0, txComplete, f1_blk_stat, f0_blk_stat, f1_bus_stat, f0_bus_stat})\r
160 );\r
161 \r
162 // DMA outputs\r
163 assign tx_intr = f0_bus_stat;\r
164 assign rx_intr = f1_bus_stat;\r
165 \r
166 /////////////////////////////////////////////////////////////////////////////\r
167 // State machine\r
168 /////////////////////////////////////////////////////////////////////////////\r
169 always @(posedge op_clk) begin\r
170         case (state)\r
171                 STATE_IDLE:\r
172                 begin\r
173                         // Check that SCSI initiator is ready, and input FIFO is not empty,\r
174                         // and output FIFO is not full.\r
175                         // Note that output FIFO is unused in TX mode.\r
176                         if (!nRST) state <= STATE_IDLE;\r
177                         else if (nACK & !f0_blk_stat)\r
178                                 state <= STATE_FIFOLOAD;\r
179                         else\r
180                                 state <= STATE_IDLE;\r
181 \r
182                         // Clear our output pins\r
183                         data <= 8'b0;\r
184                 end\r
185 \r
186                 STATE_FIFOLOAD:\r
187                         if (!nRST) state <= STATE_IDLE;\r
188                         else state <= IO == IO_WRITE ? STATE_TX : STATE_READY;\r
189 \r
190                 STATE_TX:\r
191                 begin\r
192                         if (!nRST) state <= STATE_IDLE;\r
193                         else state <= STATE_DESKEW_INIT;\r
194                         data <= po;\r
195                 end\r
196 \r
197                 STATE_DESKEW_INIT:\r
198                         if (!nRST) state <= STATE_IDLE;\r
199                         else state <= STATE_DESKEW;\r
200 \r
201                 STATE_DESKEW:\r
202                         if (!nRST) state <= STATE_IDLE;\r
203                         else if(deskewComplete) state <= STATE_READY;\r
204                         else state <= STATE_DESKEW;\r
205 \r
206                 STATE_READY:\r
207                         if (!nRST) state <= STATE_IDLE;\r
208                         else if (~nACK && ((IO == IO_WRITE) || !f1_blk_stat)) state <= STATE_RX;\r
209                         else state <= STATE_READY;\r
210 \r
211                 STATE_RX: // same code here as for the IDLE state, as we make\r
212                         // a quick run back to the next byte if possible.\r
213                         if (!nRST) state <= STATE_IDLE;\r
214                         else if (nACK & !f0_blk_stat)\r
215                                 state <= STATE_FIFOLOAD;\r
216                         else\r
217                                 state <= STATE_IDLE;\r
218 \r
219                 default: state <= STATE_IDLE;\r
220         endcase\r
221 end\r
222 \r
223 // D0 is used for the deskew count.\r
224 // The data output is valid during the DESKEW_INIT phase as well,\r
225 // so we subtract 1.\r
226 // D0 = [0.000000055 / (1 / clk)] - 1\r
227 cy_psoc3_dp #(.d0_init(2), \r
228 .cy_dpconfig(\r
229 {\r
230     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,\r
231     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,\r
232     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,\r
233     `CS_CMP_SEL_CFGA, /*CFGRAM0:          IDLE*/\r
234     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,\r
235     `CS_SHFT_OP_PASS, `CS_A0_SRC___F0, `CS_A1_SRC_NONE,\r
236     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,\r
237     `CS_CMP_SEL_CFGA, /*CFGRAM1:          FIFO Load*/\r
238     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,\r
239     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,\r
240     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,\r
241     `CS_CMP_SEL_CFGA, /*CFGRAM2:          TX*/\r
242     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,\r
243     `CS_SHFT_OP_PASS, `CS_A0_SRC___D0, `CS_A1_SRC_NONE,\r
244     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,\r
245     `CS_CMP_SEL_CFGA, /*CFGRAM3:          DESKEW INIT*/\r
246     `CS_ALU_OP__DEC, `CS_SRCA_A0, `CS_SRCB_D0,\r
247     `CS_SHFT_OP_PASS, `CS_A0_SRC__ALU, `CS_A1_SRC_NONE,\r
248     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,\r
249     `CS_CMP_SEL_CFGA, /*CFGRAM4:          DESKEW*/\r
250     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,\r
251     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,\r
252     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,\r
253     `CS_CMP_SEL_CFGA, /*CFGRAM5:    Not used*/\r
254     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,\r
255     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,\r
256     `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,\r
257     `CS_CMP_SEL_CFGA, /*CFGRAM6:          READY*/\r
258     `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,\r
259     `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,\r
260     `CS_FEEDBACK_ENBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,\r
261     `CS_CMP_SEL_CFGA, /*CFGRAM7:          RX*/\r
262     8'hFF, 8'h00,  /*CFG9:             */\r
263     8'hFF, 8'hFF,  /*CFG11-10:             */\r
264     `SC_CMPB_A1_D1, `SC_CMPA_A1_D1, `SC_CI_B_ARITH,\r
265     `SC_CI_A_ARITH, `SC_C1_MASK_DSBL, `SC_C0_MASK_DSBL,\r
266     `SC_A_MASK_DSBL, `SC_DEF_SI_0, `SC_SI_B_DEFSI,\r
267     `SC_SI_A_DEFSI, /*CFG13-12:             */\r
268     `SC_A0_SRC_ACC, `SC_SHIFT_SL, `SC_PI_DYN_EN,\r
269     1'h0, `SC_FIFO1_ALU, `SC_FIFO0_BUS,\r
270     `SC_MSB_DSBL, `SC_MSB_BIT0, `SC_MSB_NOCHN,\r
271     `SC_FB_NOCHN, `SC_CMP1_NOCHN,\r
272     `SC_CMP0_NOCHN, /*CFG15-14:             */\r
273     10'h00, `SC_FIFO_CLK__DP,`SC_FIFO_CAP_AX,\r
274     `SC_FIFO_LEVEL,`SC_FIFO__SYNC,`SC_EXTCRC_DSBL,\r
275     `SC_WRK16CAT_DSBL /*CFG17-16:             */\r
276 }\r
277 )) datapath(\r
278         /*  input                   */  .reset(1'b0),\r
279         /*  input                   */  .clk(op_clk),\r
280         /*  input   [02:00]         */  .cs_addr(state),\r
281         /*  input                   */  .route_si(1'b0),\r
282         /*  input                   */  .route_ci(1'b0),\r
283         /*  input                   */  .f0_load(1'b0),\r
284         /*  input                   */  .f1_load(fifoStore),\r
285         /*  input                   */  .d0_load(1'b0),\r
286         /*  input                   */  .d1_load(1'b0),\r
287         /*  output                  */  .ce0(),\r
288         /*  output                  */  .cl0(),\r
289         /*  output                  */  .z0(deskewComplete),\r
290         /*  output                  */  .ff0(),\r
291         /*  output                  */  .ce1(),\r
292         /*  output                  */  .cl1(),\r
293         /*  output                  */  .z1(),\r
294         /*  output                  */  .ff1(),\r
295         /*  output                  */  .ov_msb(),\r
296         /*  output                  */  .co_msb(),\r
297         /*  output                  */  .cmsb(),\r
298         /*  output                  */  .so(),\r
299         /*  output                  */  .f0_bus_stat(f0_bus_stat),\r
300         /*  output                  */  .f0_blk_stat(f0_blk_stat),\r
301         /*  output                  */  .f1_bus_stat(f1_bus_stat),\r
302         /*  output                  */  .f1_blk_stat(f1_blk_stat),\r
303         \r
304         /* input                    */  .ci(1'b0),     // Carry in from previous stage\r
305         /* output                   */  .co(),         // Carry out to next stage\r
306         /* input                    */  .sir(1'b0),    // Shift in from right side\r
307         /* output                   */  .sor(),        // Shift out to right side\r
308         /* input                    */  .sil(1'b0),    // Shift in from left side\r
309         /* output                   */  .sol(),        // Shift out to left side\r
310         /* input                    */  .msbi(1'b0),   // MSB chain in\r
311         /* output                   */  .msbo(),       // MSB chain out\r
312         /* input [01:00]            */  .cei(2'b0),    // Compare equal in from prev stage\r
313         /* output [01:00]           */  .ceo(),        // Compare equal out to next stage\r
314         /* input [01:00]            */  .cli(2'b0),    // Compare less than in from prv stage\r
315         /* output [01:00]           */  .clo(),        // Compare less than out to next stage\r
316         /* input [01:00]            */  .zi(2'b0),     // Zero detect in from previous stage\r
317         /* output [01:00]           */  .zo(),         // Zero detect out to next stage\r
318         /* input [01:00]            */  .fi(2'b0),     // 0xFF detect in from previous stage\r
319         /* output [01:00]           */  .fo(),         // 0xFF detect out to next stage\r
320         /* input [01:00]            */  .capi(2'b0),   // Software capture from previous stage\r
321         /* output [01:00]           */  .capo(),       // Software capture to next stage\r
322         /* input                    */  .cfbi(1'b0),   // CRC Feedback in from previous stage\r
323         /* output                   */  .cfbo(),       // CRC Feedback out to next stage\r
324         /* input [07:00]            */  .pi(pi),     // Parallel data port\r
325         /* output [07:00]           */  .po(po)          // Parallel data port\r
326 );\r
327 //`#end` -- edit above this line, do not edit this line\r
328 endmodule\r
329 //`#start footer` -- edit after this line, do not edit this line\r
330 //`#end` -- edit above this line, do not edit this line\r
331 \r