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

Subversion Repositories nysa_sata

[/] [nysa_sata/] [trunk/] [rtl/] [command/] [sata_command_layer.v] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 cospan
//sata_command_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
`define RESET_TIMEOUT 32'h00000002
28
 
29
module sata_command_layer (
30
 
31
  input               rst,            //reset
32
  input               linkup,
33
  input               clk,
34
  input               data_in_clk,
35
  input               data_in_clk_valid,
36
  input               data_out_clk,
37
  input               data_out_clk_valid,
38
 
39
//User Interface
40
  output              command_layer_ready,
41 3 cospan
  output  reg         sata_busy,
42 2 cospan
  input               send_sync_escape,
43
  input       [15:0]  user_features,
44
 
45
//XXX: New Stb
46 3 cospan
//  input               write_data_stb,
47
//  input               read_data_stb,
48
  output              hard_drive_error,
49 2 cospan
 
50 3 cospan
  input               execute_command_stb,
51
  input               command_layer_reset,
52 2 cospan
 
53
  output  reg         pio_data_ready,
54 3 cospan
  input       [7:0]   hard_drive_command,
55 2 cospan
 
56
  input       [15:0]  sector_count,
57
  input       [47:0]  sector_address,
58
 
59
  input       [31:0]  user_din,
60
  input               user_din_stb,
61
  output      [1:0]   user_din_ready,
62
  input       [1:0]   user_din_activate,
63
  output      [23:0]  user_din_size,
64 3 cospan
  output              user_din_empty,
65 2 cospan
 
66
  output      [31:0]  user_dout,
67
  output              user_dout_ready,
68
  input               user_dout_activate,
69
  input               user_dout_stb,
70
  output      [23:0]  user_dout_size,
71
 
72
 
73
 //Transfer Layer Interface
74
  input               transport_layer_ready,
75
  output  reg         sync_escape,
76
 
77
  output              t_send_command_stb,
78
  output  reg         t_send_control_stb,
79
  output              t_send_data_stb,
80
 
81
  input               t_dma_activate_stb,
82
  input               t_d2h_reg_stb,
83
  input               t_pio_setup_stb,
84
  input               t_d2h_data_stb,
85
  input               t_dma_setup_stb,
86
  input               t_set_device_bits_stb,
87
 
88
  input               t_remote_abort,
89
  input               t_xmit_error,
90
  input               t_read_crc_error,
91
 
92
 
93
//PIO
94
  input               t_pio_response,
95
  input               t_pio_direction,
96
  input       [15:0]  t_pio_transfer_count,
97
  input       [7:0]   t_pio_e_status,
98
 
99
//Host to Device Register Values
100
  output      [7:0]   h2d_command,
101
  output  reg [15:0]  h2d_features,
102
  output      [7:0]   h2d_control,
103
  output      [3:0]   h2d_port_mult,
104
  output      [7:0]   h2d_device,
105
  output      [47:0]  h2d_lba,
106
  output      [15:0]  h2d_sector_count,
107
 
108
//Device to Host Register Values
109
  input               d2h_interrupt,
110
  input               d2h_notification,
111
  input       [3:0]   d2h_port_mult,
112
  input       [7:0]   d2h_device,
113
  input       [47:0]  d2h_lba,
114
  input       [15:0]  d2h_sector_count,
115
  input       [7:0]   d2h_status,
116
  input       [7:0]   d2h_error,
117
 
118 3 cospan
  output              d2h_error_bbk,    //Bad Block
119
  output              d2h_error_unc,    //Uncorrectable Error
120
  output              d2h_error_mc,     //Removable Media Error
121
  output              d2h_error_idnf,   //request sector's ID Field could not be found
122
  output              d2h_error_mcr,    //Removable Media Error
123
  output              d2h_error_abrt,   //Abort (from invalid command, drive not ready, write fault)
124
  output              d2h_error_tk0nf,  //Track 0 not found
125
  output              d2h_error_amnf,   //Data Address Mark is not found after finding correct ID
126 2 cospan
 
127 3 cospan
  output              d2h_status_bsy,   //Set to 1 when drive has access to command block, no other bits are valid when 1
128
                                        //  Set after reset
129
                                        //  Set after soft reset (srst)
130
                                        //  Set immediately after host writes to command register
131
  output              d2h_status_drdy,  //Drive is ready to accept command
132
  output              d2h_status_dwf,   //Drive Write Fault
133
  output              d2h_status_dsc,   //Drive Seek Complete
134
  output              d2h_status_drq,   //Data Request, Drive is ready to send data to the host
135
  output              d2h_status_corr,  //Correctable Data bit (an error that was encountered but was corrected)
136
  output              d2h_status_idx,   //once per disc revolution this bit is set to one then back to zero
137
  output              d2h_status_err,   //error bit, if this bit is high check the error flags
138 2 cospan
 
139
//command layer data interface
140
  input               t_if_strobe,
141
  output      [31:0]  t_if_data,
142
  output              t_if_ready,
143
  input               t_if_activate,
144
  output      [23:0]  t_if_size,
145
 
146
  input               t_of_strobe,
147
  input       [31:0]  t_of_data,
148
  output      [1:0]   t_of_ready,
149
  input       [1:0]   t_of_activate,
150
  output      [23:0]  t_of_size,
151
 
152
 
153
//Debug
154
  output      [3:0]   cl_c_state,
155 3 cospan
  output      [3:0]   cl_w_state
156 2 cospan
 
157
);
158
 
159
 
160
//Parameters
161
parameter IDLE                = 4'h0;
162
parameter PIO_WAIT_FOR_DATA   = 4'h1;
163
parameter PIO_WRITE_DATA      = 4'h2;
164
 
165
parameter WAIT_FOR_DMA_ACT    = 4'h1;
166
parameter WAIT_FOR_WRITE_DATA = 4'h2;
167
parameter SEND_DATA           = 4'h3;
168
 
169
//Registers/Wires
170
reg         [3:0]   cntrl_state;
171
reg                 srst;
172
reg         [7:0]   status;
173
wire                idle;
174
reg                 cntrl_send_data_stb;
175
reg                 send_command_stb;
176
 
177
wire                dev_busy;
178
wire                dev_data_req;
179
 
180
//Write State Machine
181
reg         [3:0]   write_state;
182
 
183
reg                 dma_send_data_stb;
184 3 cospan
reg                 dma_act_detected_en;
185 2 cospan
 
186
reg                 enable_tl_data_ready;
187
 
188
//Ping Pong FIFOs
189
wire        [1:0]   if_write_ready;
190
wire        [1:0]   if_write_activate;
191
wire        [23:0]  if_write_size;
192
wire                if_write_strobe;
193
wire        [31:0]  if_write_data;
194
 
195
wire                if_read_strobe;
196
wire                if_read_ready;
197
wire                if_read_activate;
198
wire        [23:0]  if_read_size;
199
wire        [31:0]  if_read_data;
200
 
201
wire                if_reset;
202
 
203
wire        [31:0]  of_write_data;
204
wire        [1:0]   of_write_ready;
205
wire        [1:0]   of_write_activate;
206
wire        [23:0]  of_read_size;
207
wire                of_write_strobe;
208
wire                out_fifo_starved;
209
 
210
wire                of_read_ready;
211
wire        [31:0]  of_read_data;
212
wire                of_read_activate;
213
wire        [23:0]  of_write_size;
214
wire                of_read_strobe;
215
 
216
wire                of_reset;
217
 
218
//ping pong FIFO
219
//Input FIFO
220
ppfifo # (
221
  .DATA_WIDTH           (`DATA_SIZE               ),
222
  .ADDRESS_WIDTH        (`FIFO_ADDRESS_WIDTH      )
223
) fifo_in (
224
  .reset                (if_reset                 ),  //XXX: Veify that new PPFIFO doesn't need an external reset
225
 
226
  //write side
227
//XXX: This can be different clocks
228
  .write_clock          (data_in_clk              ),
229
  .write_data           (if_write_data            ),
230
  .write_ready          (if_write_ready           ),
231
  .write_activate       (if_write_activate        ),
232
  .write_fifo_size      (if_write_size            ),
233
  .write_strobe         (if_write_strobe          ),
234 3 cospan
  //.starved              (if_starved               ),
235
  .starved              (user_din_empty           ),
236 2 cospan
 
237
  //read side
238
//XXX: This can be different clocks
239
  .read_clock           (clk                      ),
240
  .read_strobe          (if_read_strobe           ),
241
  .read_ready           (if_read_ready            ),
242
  .read_activate        (if_read_activate         ),
243
  .read_count           (if_read_size             ),
244 3 cospan
  .read_data            (if_read_data             ),
245
  .inactive             (                         )
246 2 cospan
);
247
 
248
 
249
//Output FIFO
250
ppfifo # (
251
  .DATA_WIDTH           (`DATA_SIZE               ),
252
  .ADDRESS_WIDTH        (`FIFO_ADDRESS_WIDTH      )
253
) fifo_out (
254
  .reset                (of_reset                 ),
255
  //.reset                (0),
256
 
257
  //write side
258
//XXX: This can be different clocks
259
  .write_clock          (clk                      ),
260
  .write_data           (of_write_data            ),
261
  .write_ready          (of_write_ready           ),
262
  .write_activate       (of_write_activate        ),
263
  .write_fifo_size      (of_write_size            ),
264
  .write_strobe         (of_write_strobe          ),
265 3 cospan
  //.starved              (out_fifo_starved         ),
266
  .starved              (                         ),
267 2 cospan
 
268
  //read side
269
//XXX: This can be different clocks
270
  .read_clock           (data_out_clk             ),
271
  .read_strobe          (of_read_strobe           ),
272
  .read_ready           (of_read_ready            ),
273
  .read_activate        (of_read_activate         ),
274
  .read_count           (of_read_size             ),
275 3 cospan
  .read_data            (of_read_data             ),
276
  .inactive             (                         )
277 2 cospan
);
278
 
279
 
280
//Asynchronous Logic
281
//Attach output of Input FIFO to TL
282
assign  t_if_ready            = if_read_ready && enable_tl_data_ready;
283
assign  t_if_size             = if_read_size;
284
assign  t_if_data             = if_read_data;
285
 
286
assign  if_read_activate      = t_if_activate;
287
assign  if_read_strobe        = t_if_strobe;
288
 
289
//Attach input of output FIFO to TL
290
assign  t_of_ready            = of_write_ready;
291
//assign  t_of_size             = of_write_size;
292
assign  t_of_size             = 24'h00800;
293
assign  of_write_data         = t_of_data;
294
 
295
assign  of_write_activate     = t_of_activate;
296
assign  of_write_strobe       = t_of_strobe;
297
 
298
assign  of_reset              = (rst && data_out_clk_valid);
299
assign  if_reset              = (rst && data_in_clk_valid);
300
 
301
 
302
 
303
assign  if_write_data         = user_din;
304
assign  if_write_strobe       = user_din_stb;
305
assign  user_din_ready        = if_write_ready;
306
assign  if_write_activate     = user_din_activate;
307 3 cospan
assign  user_din_size         = if_write_size;
308 2 cospan
 
309
assign  user_dout             = of_read_data;
310
assign  user_dout_ready       = of_read_ready;
311
assign  of_read_activate      = user_dout_activate;
312
assign  user_dout_size        = of_read_size;
313
assign  of_read_strobe        = user_dout_stb;
314
 
315 3 cospan
assign  d2h_status_bsy        = d2h_status[7];
316
assign  d2h_status_drdy       = d2h_status[6];
317
assign  d2h_status_dwf        = d2h_status[5];
318
assign  d2h_status_dsc        = d2h_status[4];
319
assign  d2h_status_drq        = d2h_status[3];
320
assign  d2h_status_corr       = d2h_status[2];
321
assign  d2h_status_idx        = d2h_status[1];
322
assign  d2h_status_err        = d2h_status[0];
323 2 cospan
 
324 3 cospan
assign  d2h_error_bbk         = d2h_error[7];
325
assign  d2h_error_unc         = d2h_error[6];
326
assign  d2h_error_mc          = d2h_error[5];
327
assign  d2h_error_idnf        = d2h_error[4];
328
assign  d2h_error_mcr         = d2h_error[3];
329
assign  d2h_error_abrt        = d2h_error[2];
330
assign  d2h_error_tk0nf       = d2h_error[1];
331
assign  d2h_error_amnf        = d2h_error[0];
332 2 cospan
 
333
//Strobes
334 3 cospan
//assign  t_send_command_stb    = read_data_stb ||  write_data_stb  || execute_command_stb;
335
assign  t_send_command_stb    = execute_command_stb;
336 2 cospan
assign  t_send_data_stb       = dma_send_data_stb ||cntrl_send_data_stb;
337
 
338
//IDLE
339
assign  idle                  = (cntrl_state  == IDLE) &&
340
                                (write_state  == IDLE) &&
341
                                transport_layer_ready;
342
 
343
assign  command_layer_ready   = idle;
344
 
345 3 cospan
assign  h2d_command           = hard_drive_command;
346 2 cospan
assign  h2d_sector_count      = sector_count;
347 3 cospan
assign  h2d_lba               = sector_address;
348 2 cospan
 
349
//XXX: The individual bits should be controlled directly
350
assign  h2d_control           = {5'h00, srst, 2'b00};
351
//XXX: This should be controlled from a higher level
352
assign  h2d_port_mult         = 4'h0;
353
//XXX: This should be controlled from a higher level
354
assign  h2d_device            = `D2H_REG_DEVICE;
355
 
356
assign  dev_busy              = status[`STATUS_BUSY_BIT];
357
assign  dev_data_req          = status[`STATUS_DRQ_BIT];
358 3 cospan
assign  hard_drive_error      = status[`STATUS_ERR_BIT];
359 2 cospan
 
360 3 cospan
assign  cl_c_state            = cntrl_state;
361
assign  cl_w_state            = write_state;
362 2 cospan
 
363
//Synchronous Logic
364
 
365
//Control State Machine
366
always @ (posedge clk) begin
367
  if (rst || (!linkup)) begin
368
    cntrl_state                   <=  IDLE;
369
 
370
    h2d_features                  <=  `D2H_REG_FEATURES;
371
    srst                          <=  0;
372
 
373
    //Strobes
374
    t_send_control_stb            <=  0;
375
    cntrl_send_data_stb           <=  0;
376
    pio_data_ready                <=  0;
377
    status                        <=  0;
378
 
379 3 cospan
    sata_busy                     <=  0;
380
    sync_escape                   <=  0;
381 2 cospan
  end
382
  else begin
383
    t_send_control_stb            <=  0;
384
    cntrl_send_data_stb           <=  0;
385
    pio_data_ready                <=  0;
386
    //Reset Count
387
 
388
    if (t_d2h_reg_stb) begin
389 3 cospan
      //Receiving a register strobe from the device
390
      sata_busy                   <=  0;
391 2 cospan
      h2d_features                <=  `D2H_REG_FEATURES;
392
    end
393 3 cospan
    /*
394
    if (t_send_command_stb || t_send_control_stb) begin
395
      sata_busy                   <=  1;
396 2 cospan
    end
397 3 cospan
    */
398
    if (execute_command_stb) begin
399
      h2d_features                <=  user_features;
400
      sata_busy                   <=  1;
401
    end
402 2 cospan
 
403
    case (cntrl_state)
404
      IDLE: begin
405
 
406
        //Soft Reset will break out of any flow
407 3 cospan
        if (command_layer_reset && !srst) begin
408 2 cospan
          srst                  <=  1;
409
          t_send_control_stb    <=  1;
410
        end
411
 
412
        if (idle) begin
413
          //The only way to transition to another state is if CL is IDLE
414
 
415
          //User Initiated commands
416 3 cospan
          if (!command_layer_reset && srst) begin
417 2 cospan
            srst                  <=  0;
418
            t_send_control_stb    <=  1;
419
          end
420
       end
421
 
422
        //Device Initiated Transfers
423
        if(t_pio_setup_stb) begin
424
          if (t_pio_direction) begin
425
            //Read from device
426
            cntrl_state           <=  PIO_WAIT_FOR_DATA;
427
          end
428
          else begin
429
            //Write to device
430
            cntrl_state           <=  PIO_WRITE_DATA;
431
          end
432
        end
433
        if (t_set_device_bits_stb) begin
434
          status                  <=  d2h_status;
435
          //status register was updated
436
        end
437
        if (t_d2h_reg_stb) begin
438
          status                  <=  d2h_status;
439
        end
440
      end
441
      PIO_WAIT_FOR_DATA: begin
442
        if (t_d2h_data_stb) begin
443
          //the next peice of data is related to the PIO
444
          pio_data_ready          <=  1;
445
          cntrl_state             <=  IDLE;
446
          status                  <=  t_pio_e_status;
447
        end
448
      end
449
      PIO_WRITE_DATA: begin
450
        if (if_read_activate) begin
451
          cntrl_send_data_stb     <=  0;
452
          cntrl_state             <=  IDLE;
453
          status                  <=  t_pio_e_status;
454
        end
455
      end
456
 
457
      default: begin
458
        cntrl_state               <=  IDLE;
459
      end
460
    endcase
461
 
462
    if (send_sync_escape) begin
463
      cntrl_state                 <=  IDLE;
464 3 cospan
      sync_escape                 <=  1;
465
      sata_busy                   <=  0;
466 2 cospan
    end
467
  end
468
end
469
 
470
//Write State Machine
471
always @ (posedge clk) begin
472 3 cospan
  if (rst || !linkup) begin
473 2 cospan
    write_state                   <=  IDLE;
474
    dma_send_data_stb             <=  0;
475
    enable_tl_data_ready          <=  0;
476 3 cospan
    dma_act_detected_en           <=  0;
477 2 cospan
  end
478
  else begin
479
    dma_send_data_stb             <=  0;
480
 
481
    if (t_dma_activate_stb) begin
482
      //Set an enable signal instead of a strobe so that there is no chance of missing this signal
483 3 cospan
      dma_act_detected_en         <=  1;
484 2 cospan
    end
485
 
486
    case (write_state)
487
      IDLE: begin
488 3 cospan
        enable_tl_data_ready      <=  0;
489 2 cospan
        if (idle) begin
490
          //The only way to transition to another state is if CL is IDLE
491 3 cospan
          //if (write_data_stb) begin
492
          if (dma_act_detected_en) begin
493
            //send a request to write data
494
            write_state           <= WAIT_FOR_DMA_ACT;
495 2 cospan
          end
496
        end
497
      end
498
      WAIT_FOR_DMA_ACT: begin
499 3 cospan
        if (dma_act_detected_en) begin
500
          dma_act_detected_en     <=  0;
501 2 cospan
          enable_tl_data_ready    <=  1;
502
          write_state             <=  WAIT_FOR_WRITE_DATA;
503
        end
504
      end
505
      WAIT_FOR_WRITE_DATA: begin
506
        if (if_read_activate) begin
507 3 cospan
          enable_tl_data_ready    <=  0;
508 2 cospan
          write_state             <=  SEND_DATA;
509
        end
510
      end
511
      SEND_DATA: begin
512
        if (transport_layer_ready) begin
513
          //Send the Data FIS
514
          dma_send_data_stb       <=  1;
515 3 cospan
          dma_act_detected_en     <=  0;
516 2 cospan
          write_state             <=  IDLE;
517
        end
518
      end
519
      default: begin
520
        write_state               <=  IDLE;
521
      end
522
    endcase
523
 
524
 
525 3 cospan
    //if (command_layer_reset || !reset_timeout) begin
526
    if (command_layer_reset) begin
527 2 cospan
      //Break out of the normal flow and return to IDLE
528
      write_state                 <=  IDLE;
529
    end
530
    if (t_d2h_reg_stb) begin
531
      //Whenever I read a register transfer from the device I need to go back to IDLE
532
      write_state                 <=  IDLE;
533
    end
534
    if (send_sync_escape) begin
535
      write_state                 <=  IDLE;
536
    end
537
  end
538
end
539
 
540
endmodule
541
 

powered by: WebSVN 2.1.0

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