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 4

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

powered by: WebSVN 2.1.0

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