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

Subversion Repositories nysa_sata

[/] [nysa_sata/] [trunk/] [rtl/] [link/] [sata_link_layer_write.v] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 cospan
//sata_link_layer_write.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
 
26
 
27
//THERE APPEARS TO BE AN ERROR WHEN WRITING TO A HARDDRIVE, IT MANIFESTS AS A CRC ERROR
28
 
29
`include "sata_defines.v"
30
 
31
`define MIN_HOLDA_TIMEOUT 4
32
`define DHOLD_DELAY       8
33
`define DHOLD_DELAY_EN    0
34
 
35
module sata_link_layer_write(
36
 
37
  input               rst,            //reset
38
  input               clk,
39
 
40
  input               phy_ready,
41
  output              write_ready,
42
  input               en,
43
  output              idle,
44
  input               send_sync_escape,
45
 
46
  input               detect_align,
47
  input               detect_sync,
48
  input               detect_x_rdy,
49
  input               detect_r_rdy,
50
  input               detect_r_ip,
51
  input               detect_r_err,
52
  input               detect_r_ok,
53
  input               detect_cont,
54
  input               detect_hold,
55
  input               detect_holda,
56
 
57
 
58
  output  reg         send_holda,
59
 
60
  output      [31:0]  tx_dout,
61
  output              tx_isk,
62
 
63
  input       [31:0]  rx_din,
64
  input       [3:0]   rx_isk,
65
 
66
  input               write_start,
67
  output  reg         write_strobe,
68
  input       [31:0]  write_data,
69
  input       [31:0]  write_size,  //maximum 2048
70
  input               write_hold,
71
  output  reg         write_finished,
72
  output  reg         xmit_error,
73
  output  reg         wsize_z_error,
74
  input               write_abort,
75
  input               data_scrambler_en,
76
  input               is_device,
77
  output  reg [3:0]   state,
78
  output  reg [3:0]   fstate,
79
 
80
  output  reg         last_prim,
81
  output  reg         send_crc,
82
  output  reg         post_align_write,
83
 
84
  output  reg [23:0]  in_data_addra,
85
  output  reg [12:0]  d_count,
86
  output  reg [12:0]  write_count,
87
  output  reg [3:0]   buffer_pos
88
 
89
);
90
 
91
//Primatives
92
parameter           IDLE            = 4'h0;
93
 
94
//fstate
95
parameter           FIRST_DATA      = 4'h1;
96
parameter           ENQUEUE         = 4'h2;
97
parameter           WRITE_CRC       = 4'h3;
98
parameter           WAIT            = 4'h4;
99
 
100
//state
101
parameter           WRITE_START     = 4'h1;
102
parameter           WRITE           = 4'h2;
103
parameter           WRITE_END       = 4'h3;
104
parameter           WAIT_RESPONSE   = 4'h4;
105
 
106
//Registers/Wires
107
reg         [31:0]  post_align_data;
108
 
109
reg                 send_x_rdy;
110
reg                 send_sof;
111
reg                 send_eof;
112
reg                 send_wtrm;
113
reg                 send_cont;
114
reg                 send_hold;
115
//reg                 send_holda;
116
reg                 send_sync;
117
 
118
//Transport
119
reg       [31:0]    align_data_out;
120
reg                 prev_phy_ready;
121
wire                pos_phy_ready;
122
wire                neg_phy_ready;
123
 
124
reg                 prev_hold;
125
//wire                pos_hold;
126
wire                neg_holda;
127
reg       [3:0]     min_holda_count;
128
wire                min_holda_timeout;
129
 
130
reg       [3:0]     dhold_delay_cnt;
131
reg                 dhold_delay;
132
 
133
 
134
 
135
//CRC
136
//XXX: Tie the CRC_EN to the read strobe
137
wire      [31:0]    crc_dout;
138
reg       [31:0]    crc_data;
139
 
140
//Scrambler
141
reg                 scr_rst;
142
reg                 scr_en;
143
reg       [31:0]    scr_din;
144
wire      [31:0]    scr_dout;
145
 
146
//Internal FIFOs
147
reg       [23:0]    data_size;
148
reg                 wr_en;
149
 
150
wire      [31:0]    rd_dout;
151
wire                empty;
152
wire                enable_write_transaction;
153
 
154
reg       [31:0]    bump_buffer [0:3];
155
reg       [3:0]     data_pointer;
156
 
157
 
158
//XXX: Fix this aweful HACK!
159
wire      [31:0]    d0_buf;
160
wire      [31:0]    d1_buf;
161
wire      [31:0]    d2_buf;
162
wire      [31:0]    d3_buf;
163
 
164
 
165
//Sub Modules
166
blk_mem # (
167
  .DATA_WIDTH     (32                   ),
168
  .ADDRESS_WIDTH  (13                   )
169
)br(
170
  .clka           (clk                  ),
171
  .wea            (wr_en                ),
172
  .addra          (in_data_addra[12:0]  ),
173
  .dina           (scr_dout             ),
174
 
175
  .clkb           (clk                  ),
176
  .addrb          (write_count[12:0]    ),
177
  .doutb          (rd_dout              )
178
);
179
 
180
 
181
scrambler scr (
182
  .rst            (scr_rst              ),
183
  .clk            (clk                  ),
184
  .prim_scrambler (1'b0                 ),
185
  .en             (scr_en               ),
186
  .din            (scr_din              ),
187
  .dout           (scr_dout             )
188
);
189
crc c (
190
//reset the CRC any time we're in IDLE
191
  .rst            (scr_rst              ),
192
  .clk            (clk                  ),
193
  .en             (write_strobe         ),
194
  .din            (write_data           ),
195
  .dout           (crc_dout             )
196
);
197
 
198
 
199
//Asynchronous Logic
200
assign              idle  = (state == IDLE);
201
 
202
assign              tx_dout = (send_x_rdy)  ? `PRIM_X_RDY:
203
                              (send_sof)    ? `PRIM_SOF:
204
                              (send_eof)    ? `PRIM_EOF:
205
                              (send_wtrm)   ? `PRIM_WTRM:
206
                              (send_cont)   ? `PRIM_CONT:
207
                              (send_hold)   ? `PRIM_HOLD:
208
                              (send_holda)  ? `PRIM_HOLDA:
209
                              (send_sync)   ? `PRIM_SYNC:
210
                              bump_buffer[buffer_pos];
211
 
212
assign              tx_isk  = ( send_x_rdy  ||
213
                                send_sof    ||
214
                                send_eof    ||
215
                                send_wtrm   ||
216
                                send_cont   ||
217
                                send_hold   ||
218
                                send_holda  ||
219
                                send_sync);
220
 
221
assign              enable_write_transaction  = (in_data_addra != 0);
222
assign              empty                     = (in_data_addra == 0);
223
assign              pos_phy_ready             = phy_ready && ~prev_phy_ready;
224
assign              neg_phy_ready             = ~phy_ready  && prev_phy_ready;
225
//assign              pos_hold                  = detect_hold  && ~prev_hold;
226
assign              min_holda_timeout         = (min_holda_count >= `MIN_HOLDA_TIMEOUT);
227
 
228
assign              d0_buf                    = bump_buffer[0];
229
assign              d1_buf                    = bump_buffer[1];
230
assign              d2_buf                    = bump_buffer[2];
231
assign              d3_buf                    = bump_buffer[3];
232
assign              write_ready               = phy_ready && !send_holda;
233
 
234
 
235
//Synchronous Logic
236
//Incomming buffer (this is the buffer afte the scrambler and CRC)
237
always @ (posedge clk) begin
238
  if (rst) begin
239
    fstate          <=  IDLE;
240
    data_size       <=  0;
241
    in_data_addra   <=  0;
242
    scr_din         <=  0;
243
    scr_en          <=  0;
244
    scr_rst         <=  1;
245
    wr_en           <=  0;
246
    write_strobe    <=  0;
247
    crc_data        <=  0;
248
  end
249
  else begin
250
    //Strobes
251
    scr_en          <=  0;
252
    wr_en           <=  0;
253
    write_strobe    <=  0;
254
    scr_rst         <=  0;
255
 
256
 
257
    case (fstate)
258
      IDLE: begin
259
        in_data_addra     <=  0;
260
        if (write_start) begin
261
          //add an extra space for the CRC
262
          write_strobe    <=  1;
263
          data_size       <=  write_size;
264
          scr_en          <=  1;
265
          scr_din         <=  0;
266
          fstate          <=  FIRST_DATA;
267
        end
268
      end
269
      FIRST_DATA: begin
270
          write_strobe    <=  1;
271
          wr_en           <=  1;
272
          scr_en          <=  1;
273
          scr_din         <=  write_data;
274
          fstate          <=  ENQUEUE;
275
      end
276
      ENQUEUE: begin
277
        if (data_size == 1) begin
278
          in_data_addra   <=  in_data_addra + 1;
279
          wr_en           <=  1;
280
          scr_en          <=  1;
281
          scr_din         <=  crc_dout;
282
          fstate          <=  WRITE_CRC;
283
        end
284
        else begin
285
          if (in_data_addra < data_size - 1) begin
286
//          if (in_data_addra < data_size) begin
287
            //Put all the data into the FIFO
288
            write_strobe    <=  1;
289
            wr_en           <=  1;
290
            scr_en          <=  1;
291
            in_data_addra   <=  in_data_addra + 1;
292
            scr_din         <=  write_data;
293
          end
294
          else begin
295
            //put the CRC into the FIFO
296
            //in_data_addra   <=  in_data_addra + 1;
297
            wr_en           <=  1;
298
            scr_en          <=  1;
299
            in_data_addra   <=  in_data_addra + 1;
300
            scr_din         <=  crc_dout;
301
            fstate          <=  WRITE_CRC;
302
          end
303
        end
304
      end
305
      WRITE_CRC: begin
306
        fstate            <=  WAIT;
307
      end
308
      WAIT: begin
309
        scr_rst           <=  1;
310
        if (state == WRITE) begin
311
          //Because a transaction is in progress and our write buffer is full we can reset the in address to 0
312
          in_data_addra   <=  0;
313
        end
314
        if (write_finished) begin
315
          fstate          <=  IDLE;
316
          data_size       <=  0;
317
        end
318
      end
319
      default: begin
320
        fstate            <=  IDLE;
321
      end
322
    endcase
323
    if (send_sync_escape) begin
324
      fstate              <=  IDLE;
325
      data_size           <=  0;
326
    end
327
  end
328
end
329
 
330
 
331
//Detect Hold Delay
332
always @ (posedge clk) begin
333
  if (rst) begin
334
    dhold_delay     <=  0;
335
    dhold_delay_cnt <=  0;
336
 
337
  end
338
  else begin
339
 
340
    if (dhold_delay_cnt < `DHOLD_DELAY) begin
341
      dhold_delay_cnt <=  dhold_delay_cnt + 1;
342
    end
343
    else begin
344
      dhold_delay   <=  1;
345
    end
346
 
347
    //Always deassert dhold_delay whenever detect hold goes low
348
    if (!detect_hold) begin
349
      dhold_delay_cnt <=  0;
350
      dhold_delay     <=  0;
351
    end
352
  end
353
end
354
 
355
 
356
 
357
always @ (posedge clk) begin
358
  if (rst) begin
359
    state           <=  IDLE;
360
 
361
    post_align_write  <=  0;
362
    post_align_data <=  32'h0;
363
 
364
    send_x_rdy      <=  0;
365
    send_sof        <=  0;
366
    send_eof        <=  0;
367
    send_wtrm       <=  0;
368
    send_cont       <=  0;
369
    send_hold       <=  0;
370
    send_holda      <=  0;
371
    send_crc        <=  0;
372
    send_sync       <=  0;
373
 
374
    write_count     <=  0;
375
    //write_strobe    <=  0;
376
    write_finished  <=  0;
377
 
378
    //error strobe
379
    xmit_error      <=  0;
380
    wsize_z_error   <=  0;
381
    last_prim       <=  0;
382
    align_data_out  <=  0;
383
    min_holda_count <=  `MIN_HOLDA_TIMEOUT;
384
    prev_phy_ready  <=  0;
385
    prev_hold       <=  0;
386
 
387
    bump_buffer[0]  <=  0;
388
    bump_buffer[1]  <=  0;
389
    bump_buffer[2]  <=  0;
390
    bump_buffer[3]  <=  0;
391
 
392
    d_count         <=  0;
393
    buffer_pos      <=  0;
394
 
395
  end
396
  else begin
397
    if ((state == WRITE_START) || ((state != IDLE) &&  (d_count != write_count))) begin
398
      bump_buffer[3]  <=  bump_buffer[2];
399
      bump_buffer[2]  <=  bump_buffer[1];
400
      bump_buffer[1]  <=  bump_buffer[0];
401
      bump_buffer[0]  <=  rd_dout;
402
      d_count         <=  write_count;
403
    end
404
 
405
    //write_strobe    <=  0;
406
    write_finished  <=  0;
407
 
408
    xmit_error      <=  0;
409
    wsize_z_error   <=  0;
410
 
411
    //previous
412
    prev_phy_ready  <=  phy_ready;
413
 
414
`ifdef DHOLD_DELAY_EN
415
    prev_hold     <=  dhold_delay;
416
`else
417
    prev_hold     <=  detect_hold;
418
`endif
419
 
420
    if (min_holda_count < `MIN_HOLDA_TIMEOUT) begin
421
      min_holda_count <=  min_holda_count + 1;
422
    end
423
 
424
    if (phy_ready) begin
425
      send_sync     <=  0;
426
      send_x_rdy    <=  0;
427
      send_sof      <=  0;
428
      send_eof      <=  0;
429
      send_wtrm     <=  0;
430
      send_cont     <=  0;
431
      send_hold     <=  0;
432
      send_holda    <=  0;
433
      send_crc      <=  0;
434
      last_prim     <=  0;
435
    end
436
 
437
    case (state)
438
      IDLE: begin
439
        buffer_pos  <=  0;
440
        send_sync   <=  1;
441
        if (enable_write_transaction) begin
442
          //There is some data within the input write buffer
443
          state         <=  WRITE_START;
444
          write_count   <=  0;
445
          d_count       <=  0;
446
        end
447
      end
448
      WRITE_START: begin
449
        if (phy_ready) begin
450
          send_sync   <=  1;
451
          if (!is_device && detect_x_rdy) begin
452
            //hard drive wins the draw :(
453
            state         <=  IDLE;
454
          end
455
          else if (detect_r_rdy) begin
456
            state         <=  WRITE;
457
            send_sof      <=  1;
458
            //bump_buffer[buffer_pos]      <=  rd_dout;
459
            write_count   <=  write_count + 1;
460
            //Send First Read
461
            //read the first packet of data
462
          end
463
          else begin
464
            send_x_rdy      <=  1;
465
          end
466
        end
467
      end
468
      WRITE: begin
469
        if (!write_ready) begin
470
          if (neg_phy_ready && (buffer_pos == 0)) begin
471
            buffer_pos        <=  buffer_pos + 1;
472
          end
473
 
474
`ifdef DHOLD_DELAY_EN
475
          if (dhold_delay || !min_holda_timeout) begin
476
`else
477
          if (detect_hold || !min_holda_timeout) begin
478
`endif
479
            //Haven't sent out a holda yet
480
            send_holda        <=  1;
481
          end
482
          else begin
483
 
484
          //Detect the remote side finishing up with a hold
485
          //if (!detect_hold && min_holda_timeout) begin
486
            if (send_holda && !last_prim) begin
487
              last_prim       <=  1;
488
              send_holda      <=  1;
489
            end
490
          end
491
        end
492
 
493
        else begin
494
          if (write_count <= data_size + 1) begin
495
            if (buffer_pos > 0) begin
496
              buffer_pos      <=  buffer_pos - 1;
497
              if (buffer_pos == 1) begin
498
                write_count   <=  write_count + 1;
499
              end
500
            end
501
            else begin
502
              write_count     <=  write_count + 1;
503
            end
504
          end
505
          else begin
506
           send_eof          <=  1;
507
           state             <=  WAIT_RESPONSE;
508
          end
509
        end
510
 
511
//I can use this to see if the phy is ready too
512
`ifdef DHOLD_DELAY_EN
513
        if (dhold_delay && (buffer_pos == 0)) begin
514
`else
515
        if (detect_hold && (buffer_pos == 0)) begin
516
`endif
517
          min_holda_count         <=  0;
518
//XXX: I may need this to capture holds at the end of a trnasfer
519
          buffer_pos              <=  buffer_pos + 1;
520
          send_holda              <=  1;
521
        end
522
      end
523
      WRITE_END: begin
524
        state             <=  WAIT_RESPONSE;
525
      end
526
      WAIT_RESPONSE: begin
527
        send_wtrm           <=  1;
528
        if (detect_r_err) begin
529
          write_finished    <=  1;
530
          xmit_error        <=  1;
531
          state             <=  IDLE;
532
        end
533
        else if (detect_r_ok) begin
534
          write_finished    <=  1;
535
          state             <=  IDLE;
536
        end
537
      end
538
      default: begin
539
        state               <=  IDLE;
540
      end
541
    endcase
542
    if (send_sync_escape) begin
543
      send_sync             <=  1;
544
      state                 <=  IDLE;
545
      buffer_pos            <=  0;
546
      write_count           <=  0;
547
      d_count               <=  0;
548
    end
549
  end
550
end
551
 
552
 
553
endmodule

powered by: WebSVN 2.1.0

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