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 3

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

powered by: WebSVN 2.1.0

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