OpenCores
URL https://opencores.org/ocsvn/nysa_sata/nysa_sata/trunk

Subversion Repositories nysa_sata

[/] [nysa_sata/] [trunk/] [rtl/] [transport/] [sata_transport_layer.v] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 cospan
//sata_transport_layer.v
2
/*
3
Distributed under the MIT license.
4
Copyright (c) 2011 Dave McCoy (dave.mccoy@cospandesign.com)
5
 
6
Permission is hereby granted, free of charge, to any person obtaining a copy of
7
this software and associated documentation files (the "Software"), to deal in
8
the Software without restriction, including without limitation the rights to
9
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10
of the Software, and to permit persons to whom the Software is furnished to do
11
so, subject to the following conditions:
12
 
13
The above copyright notice and this permission notice shall be included in all
14
copies or substantial portions of the Software.
15
 
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
SOFTWARE.
23
*/
24
 
25
`include "sata_defines.v"
26
 
27
module sata_transport_layer (
28
  input               rst,            //reset
29
  input               clk,
30
  input               phy_ready,
31
 
32
 
33
//Transport Layer Control/Status
34
  output              transport_layer_ready,
35
  input               sync_escape,
36
 
37
  output  reg         d2h_reg_stb,
38
  output  reg         dma_activate_stb,
39
  output  reg         d2h_data_stb,
40
  output  reg         dma_setup_stb,
41
  output  reg         pio_setup_stb,
42
  output  reg         set_device_bits_stb,
43
 
44
  output  reg         remote_abort,
45
  output              xmit_error,
46
  output              read_crc_error,
47
 
48
  input               send_command_stb,
49
  input               send_control_stb,
50
  input               send_data_stb,
51
 
52
//PIO
53
  output reg          pio_response,
54
  output reg          pio_direction,
55
  output reg  [15:0]  pio_transfer_count,
56
  output reg  [7:0]   pio_e_status,
57
 
58
 
59
//Host to Device Registers
60
  input       [7:0]   h2d_command,
61
  input       [15:0]  h2d_features,
62
  input       [7:0]   h2d_control,
63
  input       [3:0]   h2d_port_mult,
64
  input       [7:0]   h2d_device,
65
  input       [47:0]  h2d_lba,
66
  input       [15:0]  h2d_sector_count,
67
 
68
//Device to Host Registers
69 3 cospan
  output  reg [7:0]   d2h_fis,
70 2 cospan
  output  reg         d2h_interrupt,
71
  output  reg         d2h_notification,
72
  output  reg [3:0]   d2h_port_mult,
73
  output  reg [7:0]   d2h_device,
74
  output  reg [47:0]  d2h_lba,
75
  output  reg [15:0]  d2h_sector_count,
76
  output  reg [7:0]   d2h_status,
77
  output  reg [7:0]   d2h_error,
78
 
79
//DMA Specific Control
80
 
81
//Data Control
82
  input               cl_if_ready,
83
  output reg          cl_if_activate,
84
  input       [23:0]  cl_if_size,
85
 
86
  output              cl_if_strobe,
87
  input       [31:0]  cl_if_data,
88
 
89
  input       [1:0]   cl_of_ready,
90
  output  reg [1:0]   cl_of_activate,
91
  output              cl_of_strobe,
92
  output      [31:0]  cl_of_data,
93
  input       [23:0]  cl_of_size,
94
 
95
 
96
//Link Layer Interface
97
  input               link_layer_ready,
98
  output              ll_sync_escape,
99
 
100
  output              ll_write_start,
101
  input               ll_write_strobe,
102
  input               ll_write_finished,
103
  output      [31:0]  ll_write_data,
104 3 cospan
  output      [23:0]  ll_write_size,
105 2 cospan
  output              ll_write_hold,
106
  output              ll_write_abort,
107
  input               ll_xmit_error,
108
 
109
  input               ll_read_start,
110
  output              ll_read_ready,
111
  input       [31:0]  ll_read_data,
112
  input               ll_read_strobe,
113
  input               ll_read_finished,
114
  input               ll_read_crc_ok,
115
  input               ll_remote_abort,
116
 
117
  output      [3:0]   lax_state
118
);
119
 
120
 
121
//Parameters
122
parameter           IDLE                  = 4'h0;
123
parameter           READ_FIS              = 4'h1;
124
parameter           WAIT_FOR_END          = 4'h2;
125
 
126
 
127
parameter           CHECK_FIS_TYPE        = 4'h1;
128
parameter           WRITE_H2D_REG         = 4'h2;
129
parameter           RETRY                 = 4'h3;
130
parameter           READ_D2H_REG          = 4'h4;
131
parameter           READ_PIO_SETUP        = 4'h5;
132
parameter           READ_SET_DEVICE_BITS  = 4'h6;
133
parameter           DMA_ACTIVATE          = 4'h7;
134
parameter           SEND_DATA             = 4'h8;
135
parameter           READ_DATA             = 4'h9;
136
 
137
 
138
//Registers/Wires
139
reg         [3:0]   fis_id_state;
140 3 cospan
reg         [7:0]   current_fis;
141 2 cospan
reg         [3:0]   state;
142
reg                 detect_fis;
143
wire                processing_fis;
144
 
145
//data direction
146
wire                data_direction;
147
 
148
//Detect FIS from the device
149
wire                detect_d2h_reg;
150
wire                detect_dma_activate;
151
wire                detect_dma_setup;
152
wire                detect_d2h_data;
153
wire                detect_pio_setup;
154
wire                detect_set_device_bits;
155
 
156
//control data signals
157
wire        [31:0]  register_fis          [5:0];
158
reg         [7:0]   register_fis_ptr;
159
reg                 cmd_bit;
160
 
161
reg                 reg_write_start;
162
wire        [31:0]  reg_write_data;
163 3 cospan
wire        [23:0]  reg_write_size;
164 2 cospan
reg                 reg_write_ready;
165
wire                reg_write_hold;
166
wire                reg_write_abort;
167
wire                reg_write_strobe;
168
 
169
//read register
170
wire                reg_read;
171
wire                reg_write;
172
reg         [7:0]   reg_read_count;
173
wire                reg_read_stb;
174
 
175
 
176
 
177
//data state machine signals
178
reg                 data_write_start;
179
wire                data_write_strobe;
180
wire                data_read_strobe;
181 3 cospan
wire        [23:0]  data_write_size;
182 2 cospan
wire        [31:0]  data_write_data;
183
wire                data_write_hold;
184
wire                data_write_abort;
185
 
186
reg                 data_read_ready;
187
reg                 send_data_fis_id;
188
 
189 3 cospan
reg                 ll_write_finished_en;
190 2 cospan
 
191
 
192 3 cospan
 
193 2 cospan
//Asnchronous Logic
194
assign  lax_state               = state;
195
assign  transport_layer_ready   = (state == IDLE) && link_layer_ready;
196
assign  ll_sync_escape          = sync_escape;
197
assign  xmit_error              = ll_xmit_error;
198
 
199
//Attach Control/Data Signals to link layer depending on the conditions
200
 
201
//Write Control
202
assign  ll_write_start          = (reg_write)   ? reg_write_start                : data_write_start;
203
assign  ll_write_data           = (reg_write)   ? register_fis[register_fis_ptr] : data_write_data;
204
assign  ll_write_size           = (reg_write)   ? reg_write_size                 : data_write_size;
205 3 cospan
assign  ll_write_hold           = (reg_write)   ? 1'b0                           : data_write_hold;
206
assign  ll_write_abort          = (reg_write)   ? 1'b0                           : data_write_abort;
207
assign  cl_if_strobe            = (reg_write)   ? 1'b0                           : (!send_data_fis_id && data_write_strobe);
208 2 cospan
 
209
//Read Control
210 3 cospan
assign  ll_read_ready           = (reg_read)    ? 1'b1                           : data_read_ready;
211
assign  cl_of_strobe            = (reg_read)    ? 1'b0                           : ((state == READ_DATA) && data_read_strobe);
212 2 cospan
assign  cl_of_data              = ll_read_data;
213
 
214
//Data Register Write Control Signals
215 3 cospan
assign  data_write_data         = (send_data_fis_id)     ? {24'h000, `FIS_DATA}  : cl_if_data;
216 2 cospan
                                                      //the first DWORD is the FIS ID
217 3 cospan
assign  data_write_size         = cl_if_size + 24'h1;
218 2 cospan
                                                      //Add 1 to the size so that there is room for the FIS ID
219
assign  data_write_strobe       = ll_write_strobe;
220
assign  data_read_strobe        = ll_read_strobe;
221 3 cospan
assign  data_write_hold         = 1'b0;
222 2 cospan
                                                   //There should never be a hold on the data becuase the CL will set it up
223 3 cospan
assign  data_write_abort        = 1'b0;
224 2 cospan
assign  read_crc_error          = !ll_read_crc_ok;
225
 
226
 
227
//H2D Register Write control signals
228
assign  reg_write_strobe        = ll_write_strobe;
229
assign  reg_write_size          = `FIS_H2D_REG_SIZE;
230 3 cospan
assign  reg_write_hold          = 1'b0;
231
assign  reg_write_abort         = 1'b0;
232 2 cospan
assign  reg_write               = (state == WRITE_H2D_REG)        || (send_command_stb || send_control_stb);
233
 
234
//D2H Register Read control signals
235
assign  reg_read                = (state == READ_D2H_REG)         ||  detect_d2h_reg          ||
236
                                  (state == READ_PIO_SETUP)       ||  detect_pio_setup        ||
237
                                  (state == READ_SET_DEVICE_BITS) ||  detect_set_device_bits;
238
 
239
assign  reg_read_stb            = ll_read_strobe;
240
 
241
//Data Read control signals
242
 
243
//Detect Signals
244
assign  processing_fis          = (state == READ_FIS);
245
 
246
assign  detect_d2h_reg          = detect_fis ? (ll_read_data[7:0] == `FIS_D2H_REG)       : (current_fis == `FIS_D2H_REG      );
247
assign  detect_dma_activate     = detect_fis ? (ll_read_data[7:0] == `FIS_DMA_ACT)       : (current_fis == `FIS_DMA_ACT      );
248
assign  detect_d2h_data         = detect_fis ? (ll_read_data[7:0] == `FIS_DATA)          : (current_fis == `FIS_DATA         );
249
assign  detect_dma_setup        = detect_fis ? (ll_read_data[7:0] == `FIS_DMA_SETUP)     : (current_fis == `FIS_DMA_SETUP    );
250
assign  detect_pio_setup        = detect_fis ? (ll_read_data[7:0] == `FIS_PIO_SETUP)     : (current_fis == `FIS_PIO_SETUP    );
251
assign  detect_set_device_bits  = detect_fis ? (ll_read_data[7:0] == `FIS_SET_DEV_BITS)  : (current_fis == `FIS_SET_DEV_BITS );
252
 
253
assign  register_fis[0]         = {h2d_features[7:0], h2d_command, cmd_bit, 3'b000, h2d_port_mult, `FIS_H2D_REG};
254
assign  register_fis[1]         = {h2d_device, h2d_lba[23:0]};
255
assign  register_fis[2]         = {h2d_features[15:8], h2d_lba[47:24]};
256
assign  register_fis[3]         = {h2d_control, 8'h00, h2d_sector_count};
257
assign  register_fis[4]         = {32'h00000000};
258
 
259
//Synchronous Logic
260
//FIS ID State machine
261
always @ (posedge clk) begin
262
  if (rst) begin
263 3 cospan
    fis_id_state                <=  IDLE;
264
    detect_fis                  <=  0;
265
    current_fis                 <=  0;
266
    d2h_fis                     <=  0;
267 2 cospan
  end
268
  else begin
269
    //in order to set all the detect_* high when the actual fis is detected send this strobe
270
    if(ll_read_finished) begin
271 3 cospan
      current_fis               <=  0;
272
      fis_id_state              <=  IDLE;
273 2 cospan
    end
274
    else begin
275
      case (fis_id_state)
276
        IDLE: begin
277 3 cospan
          current_fis           <=  0;
278
          detect_fis            <=  0;
279 2 cospan
          if (ll_read_start) begin
280 3 cospan
            detect_fis          <=  1;
281
            fis_id_state        <=  READ_FIS;
282 2 cospan
          end
283
        end
284
        READ_FIS: begin
285
          if (ll_read_strobe) begin
286 3 cospan
            detect_fis          <=  0;
287 2 cospan
            current_fis         <=  ll_read_data[7:0];
288 3 cospan
            d2h_fis             <=  ll_read_data[7:0];
289 2 cospan
            fis_id_state        <=  WAIT_FOR_END;
290
          end
291
        end
292
        WAIT_FOR_END: begin
293
          if (ll_read_finished) begin
294 3 cospan
            current_fis         <=  0;
295
            fis_id_state        <=  IDLE;
296 2 cospan
          end
297
        end
298
        default: begin
299 3 cospan
          fis_id_state          <=  IDLE;
300 2 cospan
        end
301
      endcase
302
    end
303
  end
304
end
305
 
306
 
307
//main DATA state machine
308
always @ (posedge clk) begin
309
  if (rst) begin
310
    state                       <=  IDLE;
311
    cl_of_activate              <=  0;
312
    cl_if_activate              <=  0;
313
    data_read_ready             <=  0;
314
 
315
    //Data Send
316
 
317
    send_data_fis_id            <=  0;
318
 
319
    //H2D Register
320
    register_fis_ptr            <=  0;
321
    reg_write_start             <=  0;
322
 
323
    //D2H Register
324
    reg_read_count              <=  0;
325
 
326
    //Device Status
327
    d2h_interrupt               <=  0;
328
    d2h_notification            <=  0;
329
    d2h_port_mult               <=  0;
330
    d2h_lba                     <=  0;
331
    d2h_sector_count            <=  0;
332
    d2h_status                  <=  0;
333
    d2h_error                   <=  0;
334
 
335
    d2h_reg_stb                 <=  0;
336
    d2h_data_stb                <=  0;
337
    pio_setup_stb               <=  0;
338
    set_device_bits_stb         <=  0;
339
    dma_activate_stb            <=  0;
340
    dma_setup_stb               <=  0;
341
 
342
    remote_abort                <=  0;
343
 
344
    cmd_bit                     <=  0;
345
 
346
    //PIO
347
    pio_transfer_count          <=  0;
348
    pio_e_status                <=  0;
349
    pio_direction               <=  0;
350
    pio_response                <=  0;
351
 
352
    data_write_start            <=  0;
353
 
354 3 cospan
    ll_write_finished_en        <=  0;
355 2 cospan
  end
356
  else begin
357
    //Strobed signals
358
    if (phy_ready) begin
359 3 cospan
      //only deassert a link layer strobe when Phy is ready and not sending aligns
360 2 cospan
      data_write_start          <=  0;
361
      reg_write_start           <=  0;
362
    end
363
 
364
    d2h_reg_stb                 <=  0;
365
    d2h_data_stb                <=  0;
366
    pio_setup_stb               <=  0;
367
    set_device_bits_stb         <=  0;
368
    dma_activate_stb            <=  0;
369
    dma_setup_stb               <=  0;
370
 
371
    remote_abort                <=  0;
372
 
373
 
374
 
375
    d2h_device                  <=  0;
376
    //Always attempt to get a free buffer
377
    if ((cl_of_activate == 0) && (cl_of_ready > 0)) begin
378
      if (cl_of_ready[0]) begin
379
        cl_of_activate[0]       <= 1;
380
      end
381
      else begin
382
        cl_of_activate[1]       <= 1;
383
      end
384
      data_read_ready           <= 1;
385
    end
386
    else if (cl_of_activate == 0) begin
387
//XXX: NO BUFFER AVAILABLE!!!! Can't accept new data from the Hard Drive
388
      data_read_ready           <= 0;
389
    end
390
 
391
    //Always attempt to get the incomming buffer
392
    if (cl_if_ready && !cl_if_activate) begin
393
      cl_if_activate            <=  1;
394
    end
395
 
396 3 cospan
    if (ll_write_finished) begin
397
        ll_write_finished_en    <= 1;
398
    end
399
 
400 2 cospan
    case (state)
401
      IDLE: begin
402
        register_fis_ptr        <=  0;
403
        reg_read_count          <=  0;
404
        cmd_bit                 <=  0;
405 3 cospan
        ll_write_finished_en    <=  0;
406 2 cospan
        //Detect a FIS
407
        if(ll_read_start) begin
408
          //detect the start of a frame
409
          state                 <=  CHECK_FIS_TYPE;
410
//Clear Errors when a new transaction starts
411
        end
412
        //Send Register
413
        if (send_command_stb || send_control_stb) begin
414
//Clear Errors when a new transaction starts
415
 
416
          if (send_command_stb) begin
417
            cmd_bit               <=  1;
418
          end
419
          else if (send_control_stb) begin
420
            cmd_bit               <=  0;
421
          end
422
 
423
          reg_write_start       <=  1;
424
          state                 <=  WRITE_H2D_REG;
425
        end
426
        //Send Data
427
        else if (send_data_stb) begin
428
//Clear Errors when a new transaction starts
429
          data_write_start      <=  1;
430
          send_data_fis_id      <=  1;
431
          state                 <=  SEND_DATA;
432
        end
433
      end
434
      CHECK_FIS_TYPE: begin
435
        if (detect_dma_setup) begin
436
//XXX: Future work!
437 3 cospan
          reg_read_count        <=  reg_read_count + 8'h1;
438 2 cospan
          state                 <=  IDLE;
439
        end
440
        else if (detect_dma_activate) begin
441
          //hard drive is ready to receive data
442
          state                 <=  DMA_ACTIVATE;
443 3 cospan
          reg_read_count        <=  reg_read_count + 8'h1;
444 2 cospan
          //state                 <=  IDLE;
445
        end
446
        else if (detect_d2h_data) begin
447
          //incomming data, because the out FIFO is directly connected to the output during a read
448
          state                 <=  READ_DATA;
449
        end
450
        else if (detect_d2h_reg) begin
451
          //store the error, status interrupt from this read
452
          d2h_status            <=  ll_read_data[23:16];
453
          d2h_error             <=  ll_read_data[31:24];
454
          d2h_interrupt         <=  ll_read_data[14];
455
          d2h_port_mult         <=  ll_read_data[11:8];
456
 
457
          state                 <=  READ_D2H_REG;
458 3 cospan
          reg_read_count        <=  reg_read_count + 8'h1;
459 2 cospan
        end
460
        else if (detect_pio_setup) begin
461
          //store the error, status, direction interrupt from this read
462
          pio_response          <=  1;
463
 
464
          d2h_status            <=  ll_read_data[23:16];
465
          d2h_error             <=  ll_read_data[31:24];
466
          d2h_interrupt         <=  ll_read_data[14];
467
          pio_direction         <=  ll_read_data[13];
468
          d2h_port_mult         <=  ll_read_data[11:8];
469
 
470
          state                 <=  READ_PIO_SETUP;
471 3 cospan
          reg_read_count        <=  reg_read_count + 8'h1;
472 2 cospan
        end
473
        else if (detect_set_device_bits) begin
474
          //store the error, a subset of the status bit and the interrupt
475
          state                 <=  IDLE;
476
          d2h_status[6:4]       <=  ll_read_data[22:20];
477
          d2h_status[2:0]       <=  ll_read_data[18:16];
478
          d2h_error             <=  ll_read_data[31:24];
479
          d2h_notification      <=  ll_read_data[15];
480
          d2h_interrupt         <=  ll_read_data[14];
481
          d2h_port_mult         <=  ll_read_data[11:8];
482
 
483
          state                 <=  READ_SET_DEVICE_BITS;
484
        end
485
        else if (ll_read_finished) begin
486
          //unrecognized FIS
487
          state                 <=  IDLE;
488
        end
489
      end
490
      WRITE_H2D_REG: begin
491
        if  (register_fis_ptr < `FIS_H2D_REG_SIZE) begin
492
          if (reg_write_strobe) begin
493 3 cospan
            register_fis_ptr    <=  register_fis_ptr + 8'h1;
494 2 cospan
          end
495
        end
496 3 cospan
        if (ll_write_finished_en) begin
497 2 cospan
          if (ll_xmit_error) begin
498
            state               <=  RETRY;
499
          end
500
          else begin
501
            state               <=  IDLE;
502
          end
503
        end
504
      end
505
      RETRY: begin
506
        if (link_layer_ready) begin
507 3 cospan
          ll_write_finished_en  <=  0;
508 2 cospan
          reg_write_start       <=  1;
509
          register_fis_ptr      <=  0;
510
          state                 <=  WRITE_H2D_REG;
511
        end
512
      end
513
      READ_D2H_REG: begin
514
        case (reg_read_count)
515
          1: begin
516
            d2h_device          <=  ll_read_data[31:24];
517
            d2h_lba[23:0]       <=  ll_read_data[23:0];
518
          end
519
          2: begin
520
            d2h_lba[47:24]      <=  ll_read_data[23:0];
521
          end
522
          3: begin
523
            d2h_sector_count    <=  ll_read_data[15:0];
524
          end
525
          4: begin
526
          end
527
          default: begin
528
          end
529
        endcase
530
        if (reg_read_stb) begin
531 3 cospan
          reg_read_count        <=  reg_read_count + 8'h1;
532 2 cospan
        end
533
        if (ll_read_finished) begin
534
          d2h_reg_stb           <=  1;
535
          state                 <=  IDLE;
536
        end
537
      end
538
      READ_PIO_SETUP: begin
539
        case (reg_read_count)
540
          1: begin
541
            d2h_device          <=  ll_read_data[31:24];
542
            d2h_lba[23:0]       <=  ll_read_data[23:0];
543
          end
544
          2: begin
545
            d2h_lba[47:24]      <=  ll_read_data[23:0];
546
          end
547
          3: begin
548
            d2h_sector_count    <=  ll_read_data[15:0];
549
            pio_e_status        <=  ll_read_data[31:24];
550
          end
551
          4: begin
552
            pio_transfer_count  <=  ll_read_data[15:0];
553
          end
554
          default: begin
555
          end
556
        endcase
557
        if (reg_read_stb) begin
558 3 cospan
          reg_read_count        <=  reg_read_count + 8'h1;
559 2 cospan
        end
560
        if (ll_read_finished) begin
561
          pio_setup_stb         <=  1;
562
          state                 <=  IDLE;
563
        end
564
      end
565
      READ_SET_DEVICE_BITS: begin
566
        state                 <=  IDLE;
567
        set_device_bits_stb   <=  1;
568
      end
569
      DMA_ACTIVATE: begin
570
        state                 <=  IDLE;
571
        dma_activate_stb      <=  1;
572
      end
573
      SEND_DATA: begin
574
        if (ll_write_strobe && send_data_fis_id) begin
575
          send_data_fis_id      <=  0;
576
        end
577 3 cospan
        if (ll_write_finished_en) begin
578 2 cospan
          cl_if_activate        <=  0;
579
          state                 <=  IDLE;
580
          if (pio_response) begin
581
            //write the end status to the status pin
582
            d2h_status          <=  pio_e_status;
583
          end
584
        end
585
      end
586
      READ_DATA: begin
587
        //NOTE: the data_read_ready will automatically 'flow control' the data from the link layer
588
        //so we don't have to check it here
589
        //NOTE: We don't have to keep track of the count because the lower level will give a max of 2048 DWORDS
590
        if (ll_read_finished) begin
591
          //deactivate FIFO
592
          d2h_data_stb      <=  1;
593
          cl_of_activate    <=  0;
594
          state             <=  IDLE;
595
          if (pio_response) begin
596
            //write the end status to the status pin
597
            d2h_status        <=  pio_e_status;
598
          end
599
        end
600
      end
601
      default: begin
602
        state               <=  IDLE;
603
      end
604
    endcase
605
    if (sync_escape) begin
606
      state                 <=  IDLE;
607
    end
608
  end
609
end
610
 
611
 
612
endmodule
613
 
614
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.