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

Subversion Repositories nysa_sata

[/] [nysa_sata/] [trunk/] [rtl/] [command/] [sata_command_layer.v] - Diff between revs 2 and 3

Only display areas with differences | Details | Blame | View Log

Rev 2 Rev 3
//sata_command_layer.v
//sata_command_layer.v
/*
/*
Distributed under the MIT license.
Distributed under the MIT license.
Copyright (c) 2011 Dave McCoy (dave.mccoy@cospandesign.com)
Copyright (c) 2011 Dave McCoy (dave.mccoy@cospandesign.com)
 
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
so, subject to the following conditions:
 
 
The above copyright notice and this permission notice shall be included in all
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
copies or substantial portions of the Software.
 
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.
*/
*/
 
 
`include "sata_defines.v"
`include "sata_defines.v"
 
 
`define RESET_TIMEOUT 32'h00000002
`define RESET_TIMEOUT 32'h00000002
 
 
module sata_command_layer (
module sata_command_layer (
 
 
  input               rst,            //reset
  input               rst,            //reset
  input               linkup,
  input               linkup,
  input               clk,
  input               clk,
  input               data_in_clk,
  input               data_in_clk,
  input               data_in_clk_valid,
  input               data_in_clk_valid,
  input               data_out_clk,
  input               data_out_clk,
  input               data_out_clk_valid,
  input               data_out_clk_valid,
 
 
//User Interface
//User Interface
  output              sata_init,
 
  output              command_layer_ready,
  output              command_layer_ready,
  output  reg         busy,
  output  reg         sata_busy,
  input               send_sync_escape,
  input               send_sync_escape,
  input       [15:0]  user_features,
  input       [15:0]  user_features,
 
 
//XXX: New Stb
//XXX: New Stb
  input               write_data_en,
//  input               write_data_stb,
  input               single_rdwr,
//  input               read_data_stb,
  input               read_data_en,
  output              hard_drive_error,
  output              dev_error,
 
 
 
  input               send_user_command_stb,
  input               execute_command_stb,
  input               soft_reset_en,
  input               command_layer_reset,
 
 
  output  reg         pio_data_ready,
  output  reg         pio_data_ready,
  input       [7:0]   command,
  input       [7:0]   hard_drive_command,
 
 
  input       [15:0]  sector_count,
  input       [15:0]  sector_count,
  input       [47:0]  sector_address,
  input       [47:0]  sector_address,
 
 
  input       [31:0]  user_din,
  input       [31:0]  user_din,
  input               user_din_stb,
  input               user_din_stb,
  output      [1:0]   user_din_ready,
  output      [1:0]   user_din_ready,
  input       [1:0]   user_din_activate,
  input       [1:0]   user_din_activate,
  output      [23:0]  user_din_size,
  output      [23:0]  user_din_size,
 
  output              user_din_empty,
 
 
  output      [31:0]  user_dout,
  output      [31:0]  user_dout,
  output              user_dout_ready,
  output              user_dout_ready,
  input               user_dout_activate,
  input               user_dout_activate,
  input               user_dout_stb,
  input               user_dout_stb,
  output      [23:0]  user_dout_size,
  output      [23:0]  user_dout_size,
 
 
 
 
 //Transfer Layer Interface
 //Transfer Layer Interface
  input               transport_layer_ready,
  input               transport_layer_ready,
  output  reg         sync_escape,
  output  reg         sync_escape,
 
 
  output              t_send_command_stb,
  output              t_send_command_stb,
  output  reg         t_send_control_stb,
  output  reg         t_send_control_stb,
  output              t_send_data_stb,
  output              t_send_data_stb,
 
 
  input               t_dma_activate_stb,
  input               t_dma_activate_stb,
  input               t_d2h_reg_stb,
  input               t_d2h_reg_stb,
  input               t_pio_setup_stb,
  input               t_pio_setup_stb,
  input               t_d2h_data_stb,
  input               t_d2h_data_stb,
  input               t_dma_setup_stb,
  input               t_dma_setup_stb,
  input               t_set_device_bits_stb,
  input               t_set_device_bits_stb,
 
 
  input               t_remote_abort,
  input               t_remote_abort,
  input               t_xmit_error,
  input               t_xmit_error,
  input               t_read_crc_error,
  input               t_read_crc_error,
 
 
 
 
//PIO
//PIO
  input               t_pio_response,
  input               t_pio_response,
  input               t_pio_direction,
  input               t_pio_direction,
  input       [15:0]  t_pio_transfer_count,
  input       [15:0]  t_pio_transfer_count,
  input       [7:0]   t_pio_e_status,
  input       [7:0]   t_pio_e_status,
 
 
//Host to Device Register Values
//Host to Device Register Values
  output      [7:0]   h2d_command,
  output      [7:0]   h2d_command,
  output  reg [15:0]  h2d_features,
  output  reg [15:0]  h2d_features,
  output      [7:0]   h2d_control,
  output      [7:0]   h2d_control,
  output      [3:0]   h2d_port_mult,
  output      [3:0]   h2d_port_mult,
  output      [7:0]   h2d_device,
  output      [7:0]   h2d_device,
  output      [47:0]  h2d_lba,
  output      [47:0]  h2d_lba,
  output      [15:0]  h2d_sector_count,
  output      [15:0]  h2d_sector_count,
 
 
//Device to Host Register Values
//Device to Host Register Values
  input               d2h_interrupt,
  input               d2h_interrupt,
  input               d2h_notification,
  input               d2h_notification,
  input       [3:0]   d2h_port_mult,
  input       [3:0]   d2h_port_mult,
  input       [7:0]   d2h_device,
  input       [7:0]   d2h_device,
  input       [47:0]  d2h_lba,
  input       [47:0]  d2h_lba,
  input       [15:0]  d2h_sector_count,
  input       [15:0]  d2h_sector_count,
  input       [7:0]   d2h_status,
  input       [7:0]   d2h_status,
  input       [7:0]   d2h_error,
  input       [7:0]   d2h_error,
 
 
 
  output              d2h_error_bbk,    //Bad Block
 
  output              d2h_error_unc,    //Uncorrectable Error
 
  output              d2h_error_mc,     //Removable Media Error
 
  output              d2h_error_idnf,   //request sector's ID Field could not be found
 
  output              d2h_error_mcr,    //Removable Media Error
 
  output              d2h_error_abrt,   //Abort (from invalid command, drive not ready, write fault)
 
  output              d2h_error_tk0nf,  //Track 0 not found
 
  output              d2h_error_amnf,   //Data Address Mark is not found after finding correct ID
 
 
 
  output              d2h_status_bsy,   //Set to 1 when drive has access to command block, no other bits are valid when 1
 
                                        //  Set after reset
 
                                        //  Set after soft reset (srst)
 
                                        //  Set immediately after host writes to command register
 
  output              d2h_status_drdy,  //Drive is ready to accept command
 
  output              d2h_status_dwf,   //Drive Write Fault
 
  output              d2h_status_dsc,   //Drive Seek Complete
 
  output              d2h_status_drq,   //Data Request, Drive is ready to send data to the host
 
  output              d2h_status_corr,  //Correctable Data bit (an error that was encountered but was corrected)
 
  output              d2h_status_idx,   //once per disc revolution this bit is set to one then back to zero
 
  output              d2h_status_err,   //error bit, if this bit is high check the error flags
 
 
//command layer data interface
//command layer data interface
  input               t_if_strobe,
  input               t_if_strobe,
  output      [31:0]  t_if_data,
  output      [31:0]  t_if_data,
  output              t_if_ready,
  output              t_if_ready,
  input               t_if_activate,
  input               t_if_activate,
  output      [23:0]  t_if_size,
  output      [23:0]  t_if_size,
 
 
  input               t_of_strobe,
  input               t_of_strobe,
  input       [31:0]  t_of_data,
  input       [31:0]  t_of_data,
  output      [1:0]   t_of_ready,
  output      [1:0]   t_of_ready,
  input       [1:0]   t_of_activate,
  input       [1:0]   t_of_activate,
  output      [23:0]  t_of_size,
  output      [23:0]  t_of_size,
 
 
 
 
//Debug
//Debug
  output      [3:0]   cl_c_state,
  output      [3:0]   cl_c_state,
  output      [3:0]   cl_w_state,
  output      [3:0]   cl_w_state
  output      [3:0]   cl_r_state
 
 
 
);
);
 
 
 
 
//Parameters
//Parameters
parameter IDLE                = 4'h0;
parameter IDLE                = 4'h0;
parameter PIO_WAIT_FOR_DATA   = 4'h1;
parameter PIO_WAIT_FOR_DATA   = 4'h1;
parameter PIO_WRITE_DATA      = 4'h2;
parameter PIO_WRITE_DATA      = 4'h2;
 
 
parameter WAIT_FOR_DATA       = 4'h1;
 
 
 
parameter WAIT_FOR_DMA_ACT    = 4'h1;
parameter WAIT_FOR_DMA_ACT    = 4'h1;
parameter WAIT_FOR_WRITE_DATA = 4'h2;
parameter WAIT_FOR_WRITE_DATA = 4'h2;
parameter SEND_DATA           = 4'h3;
parameter SEND_DATA           = 4'h3;
parameter WAIT_FOR_STATUS     = 4'h4;
 
 
 
//Registers/Wires
//Registers/Wires
reg         [3:0]   cntrl_state;
reg         [3:0]   cntrl_state;
reg                 srst;
reg                 srst;
reg         [7:0]   status;
reg         [7:0]   status;
wire                idle;
wire                idle;
reg                 cntrl_send_data_stb;
reg                 cntrl_send_data_stb;
reg                 send_command_stb;
reg                 send_command_stb;
reg                 prev_send_command;
 
 
 
wire                dev_busy;
wire                dev_busy;
wire                dev_data_req;
wire                dev_data_req;
 
 
reg         [31:0]  reset_count;
 
wire                reset_timeout;
 
 
 
//Read State Machine
 
reg         [3:0]   read_state;
 
reg                 read_data_stb;
 
reg                 single_read_prev;
 
 
 
//Write State Machine
//Write State Machine
reg         [3:0]   write_state;
reg         [3:0]   write_state;
reg                 write_data_stb;
 
reg                 single_write_prev;
 
 
 
reg                 dma_send_data_stb;
reg                 dma_send_data_stb;
reg                 dma_act_detected;
reg                 dma_act_detected_en;
 
 
wire                write_data_available;
 
reg                 first_write;
 
reg                 first_read;
 
 
 
reg                 enable_tl_data_ready;
reg                 enable_tl_data_ready;
 
 
//Ping Pong FIFOs
//Ping Pong FIFOs
wire        [1:0]   if_write_ready;
wire        [1:0]   if_write_ready;
wire        [1:0]   if_write_activate;
wire        [1:0]   if_write_activate;
wire        [23:0]  if_write_size;
wire        [23:0]  if_write_size;
wire                if_write_strobe;
wire                if_write_strobe;
wire                if_starved;
 
wire        [31:0]  if_write_data;
wire        [31:0]  if_write_data;
 
 
wire                if_read_strobe;
wire                if_read_strobe;
wire                if_read_ready;
wire                if_read_ready;
wire                if_read_activate;
wire                if_read_activate;
wire        [23:0]  if_read_size;
wire        [23:0]  if_read_size;
wire        [31:0]  if_read_data;
wire        [31:0]  if_read_data;
 
 
wire                if_reset;
wire                if_reset;
 
 
wire        [31:0]  of_write_data;
wire        [31:0]  of_write_data;
wire        [1:0]   of_write_ready;
wire        [1:0]   of_write_ready;
wire        [1:0]   of_write_activate;
wire        [1:0]   of_write_activate;
wire        [23:0]  of_read_size;
wire        [23:0]  of_read_size;
wire                of_write_strobe;
wire                of_write_strobe;
wire                out_fifo_starved;
wire                out_fifo_starved;
 
 
wire                of_read_ready;
wire                of_read_ready;
wire        [31:0]  of_read_data;
wire        [31:0]  of_read_data;
wire                of_read_activate;
wire                of_read_activate;
wire        [23:0]  of_write_size;
wire        [23:0]  of_write_size;
wire                of_read_strobe;
wire                of_read_strobe;
 
 
wire                of_reset;
wire                of_reset;
 
 
//ping pong FIFO
//ping pong FIFO
//Input FIFO
//Input FIFO
ppfifo # (
ppfifo # (
  .DATA_WIDTH           (`DATA_SIZE               ),
  .DATA_WIDTH           (`DATA_SIZE               ),
  .ADDRESS_WIDTH        (`FIFO_ADDRESS_WIDTH      )
  .ADDRESS_WIDTH        (`FIFO_ADDRESS_WIDTH      )
) fifo_in (
) fifo_in (
  .reset                (if_reset                 ),  //XXX: Veify that new PPFIFO doesn't need an external reset
  .reset                (if_reset                 ),  //XXX: Veify that new PPFIFO doesn't need an external reset
 
 
  //write side
  //write side
//XXX: This can be different clocks
//XXX: This can be different clocks
  .write_clock          (data_in_clk              ),
  .write_clock          (data_in_clk              ),
  .write_data           (if_write_data            ),
  .write_data           (if_write_data            ),
  .write_ready          (if_write_ready           ),
  .write_ready          (if_write_ready           ),
  .write_activate       (if_write_activate        ),
  .write_activate       (if_write_activate        ),
  .write_fifo_size      (if_write_size            ),
  .write_fifo_size      (if_write_size            ),
  .write_strobe         (if_write_strobe          ),
  .write_strobe         (if_write_strobe          ),
  .starved              (if_starved               ),
  //.starved              (if_starved               ),
 
  .starved              (user_din_empty           ),
 
 
  //read side
  //read side
//XXX: This can be different clocks
//XXX: This can be different clocks
  .read_clock           (clk                      ),
  .read_clock           (clk                      ),
  .read_strobe          (if_read_strobe           ),
  .read_strobe          (if_read_strobe           ),
  .read_ready           (if_read_ready            ),
  .read_ready           (if_read_ready            ),
  .read_activate        (if_read_activate         ),
  .read_activate        (if_read_activate         ),
  .read_count           (if_read_size             ),
  .read_count           (if_read_size             ),
  .read_data            (if_read_data             )
  .read_data            (if_read_data             ),
 
  .inactive             (                         )
);
);
 
 
 
 
//Output FIFO
//Output FIFO
ppfifo # (
ppfifo # (
  .DATA_WIDTH           (`DATA_SIZE               ),
  .DATA_WIDTH           (`DATA_SIZE               ),
  .ADDRESS_WIDTH        (`FIFO_ADDRESS_WIDTH      )
  .ADDRESS_WIDTH        (`FIFO_ADDRESS_WIDTH      )
) fifo_out (
) fifo_out (
  .reset                (of_reset                 ),
  .reset                (of_reset                 ),
  //.reset                (0),
  //.reset                (0),
 
 
  //write side
  //write side
//XXX: This can be different clocks
//XXX: This can be different clocks
  .write_clock          (clk                      ),
  .write_clock          (clk                      ),
  .write_data           (of_write_data            ),
  .write_data           (of_write_data            ),
  .write_ready          (of_write_ready           ),
  .write_ready          (of_write_ready           ),
  .write_activate       (of_write_activate        ),
  .write_activate       (of_write_activate        ),
  .write_fifo_size      (of_write_size            ),
  .write_fifo_size      (of_write_size            ),
  .write_strobe         (of_write_strobe          ),
  .write_strobe         (of_write_strobe          ),
  .starved              (out_fifo_starved         ),
  //.starved              (out_fifo_starved         ),
 
  .starved              (                         ),
 
 
  //read side
  //read side
//XXX: This can be different clocks
//XXX: This can be different clocks
  .read_clock           (data_out_clk             ),
  .read_clock           (data_out_clk             ),
  .read_strobe          (of_read_strobe           ),
  .read_strobe          (of_read_strobe           ),
  .read_ready           (of_read_ready            ),
  .read_ready           (of_read_ready            ),
  .read_activate        (of_read_activate         ),
  .read_activate        (of_read_activate         ),
  .read_count           (of_read_size             ),
  .read_count           (of_read_size             ),
  .read_data            (of_read_data             )
  .read_data            (of_read_data             ),
 
  .inactive             (                         )
);
);
 
 
 
 
//Asynchronous Logic
//Asynchronous Logic
//Attach output of Input FIFO to TL
//Attach output of Input FIFO to TL
assign  t_if_ready            = if_read_ready && enable_tl_data_ready;
assign  t_if_ready            = if_read_ready && enable_tl_data_ready;
assign  t_if_size             = if_read_size;
assign  t_if_size             = if_read_size;
assign  t_if_data             = if_read_data;
assign  t_if_data             = if_read_data;
 
 
assign  if_read_activate      = t_if_activate;
assign  if_read_activate      = t_if_activate;
assign  if_read_strobe        = t_if_strobe;
assign  if_read_strobe        = t_if_strobe;
 
 
//Attach input of output FIFO to TL
//Attach input of output FIFO to TL
assign  t_of_ready            = of_write_ready;
assign  t_of_ready            = of_write_ready;
//assign  t_of_size             = of_write_size;
//assign  t_of_size             = of_write_size;
assign  t_of_size             = 24'h00800;
assign  t_of_size             = 24'h00800;
assign  of_write_data         = t_of_data;
assign  of_write_data         = t_of_data;
 
 
assign  of_write_activate     = t_of_activate;
assign  of_write_activate     = t_of_activate;
assign  of_write_strobe       = t_of_strobe;
assign  of_write_strobe       = t_of_strobe;
 
 
assign  of_reset              = (rst && data_out_clk_valid);
assign  of_reset              = (rst && data_out_clk_valid);
assign  if_reset              = (rst && data_in_clk_valid);
assign  if_reset              = (rst && data_in_clk_valid);
 
 
 
 
 
 
assign  if_write_data         = user_din;
assign  if_write_data         = user_din;
assign  if_write_strobe       = user_din_stb;
assign  if_write_strobe       = user_din_stb;
assign  user_din_ready        = if_write_ready;
assign  user_din_ready        = if_write_ready;
assign  if_write_activate     = user_din_activate;
assign  if_write_activate     = user_din_activate;
//assign  user_din_size         = if_write_size;
assign  user_din_size         = if_write_size;
assign  user_din_size         = 24'h00800;
 
//assign  user_din_size         = 24'h00400;
 
//assign  user_din_size         = 24'h00200;
 
 
 
assign  user_dout             = of_read_data;
assign  user_dout             = of_read_data;
assign  user_dout_ready       = of_read_ready;
assign  user_dout_ready       = of_read_ready;
assign  of_read_activate      = user_dout_activate;
assign  of_read_activate      = user_dout_activate;
assign  user_dout_size        = of_read_size;
assign  user_dout_size        = of_read_size;
assign  of_read_strobe        = user_dout_stb;
assign  of_read_strobe        = user_dout_stb;
 
 
 
assign  d2h_status_bsy        = d2h_status[7];
assign  write_data_available  = (if_read_ready || if_read_activate) ||  (if_write_ready != 2'b11);
assign  d2h_status_drdy       = d2h_status[6];
 
assign  d2h_status_dwf        = d2h_status[5];
 
assign  d2h_status_dsc        = d2h_status[4];
 
assign  d2h_status_drq        = d2h_status[3];
 
assign  d2h_status_corr       = d2h_status[2];
 
assign  d2h_status_idx        = d2h_status[1];
 
assign  d2h_status_err        = d2h_status[0];
 
 
 
assign  d2h_error_bbk         = d2h_error[7];
 
assign  d2h_error_unc         = d2h_error[6];
 
assign  d2h_error_mc          = d2h_error[5];
 
assign  d2h_error_idnf        = d2h_error[4];
 
assign  d2h_error_mcr         = d2h_error[3];
 
assign  d2h_error_abrt        = d2h_error[2];
 
assign  d2h_error_tk0nf       = d2h_error[1];
 
assign  d2h_error_amnf        = d2h_error[0];
 
 
//Strobes
//Strobes
assign  t_send_command_stb    = read_data_stb ||  write_data_stb  || send_command_stb;
//assign  t_send_command_stb    = read_data_stb ||  write_data_stb  || execute_command_stb;
 
assign  t_send_command_stb    = execute_command_stb;
assign  t_send_data_stb       = dma_send_data_stb ||cntrl_send_data_stb;
assign  t_send_data_stb       = dma_send_data_stb ||cntrl_send_data_stb;
 
 
//IDLE
//IDLE
assign  idle                  = (cntrl_state  == IDLE) &&
assign  idle                  = (cntrl_state  == IDLE) &&
                                (read_state   == IDLE) &&
 
                                (write_state  == IDLE) &&
                                (write_state  == IDLE) &&
                                transport_layer_ready;
                                transport_layer_ready;
 
 
assign  command_layer_ready   = idle;
assign  command_layer_ready   = idle;
assign  sata_init             = reset_timeout;
 
 
 
assign  h2d_command           = (write_data_en)   ?        `COMMAND_DMA_WRITE_EX    :
 
                                (read_data_en)    ?        `COMMAND_DMA_READ_EX     :
 
                                (send_user_command_stb) ? command                   :
 
                                h2d_command;
 
 
 
 
assign  h2d_command           = hard_drive_command;
assign  h2d_sector_count      = sector_count;
assign  h2d_sector_count      = sector_count;
assign  h2d_lba               = (write_data_en) ? (!single_rdwr && !first_write)  ?   d2h_lba + 1 : sector_address :
assign  h2d_lba               = sector_address;
                                (read_data_en)  ? (!single_rdwr && !first_read)   ?   d2h_lba + 1 : sector_address :
 
                                sector_address;
 
 
 
//XXX: The individual bits should be controlled directly
//XXX: The individual bits should be controlled directly
assign  h2d_control           = {5'h00, srst, 2'b00};
assign  h2d_control           = {5'h00, srst, 2'b00};
//XXX: This should be controlled from a higher level
//XXX: This should be controlled from a higher level
assign  h2d_port_mult         = 4'h0;
assign  h2d_port_mult         = 4'h0;
//XXX: This should be controlled from a higher level
//XXX: This should be controlled from a higher level
assign  h2d_device            = `D2H_REG_DEVICE;
assign  h2d_device            = `D2H_REG_DEVICE;
 
 
assign  dev_busy              = status[`STATUS_BUSY_BIT];
assign  dev_busy              = status[`STATUS_BUSY_BIT];
assign  dev_data_req          = status[`STATUS_DRQ_BIT];
assign  dev_data_req          = status[`STATUS_DRQ_BIT];
assign  dev_error             = status[`STATUS_ERR_BIT];
assign  hard_drive_error      = status[`STATUS_ERR_BIT];
 
 
assign  cl_c_state           = cntrl_state;
assign  cl_c_state           = cntrl_state;
assign  cl_r_state           = read_state;
 
assign  cl_w_state           = write_state;
assign  cl_w_state           = write_state;
 
 
assign  reset_timeout         = (reset_count >=  `RESET_TIMEOUT);
 
 
 
//Synchronous Logic
//Synchronous Logic
 
 
//Control State Machine
//Control State Machine
always @ (posedge clk) begin
always @ (posedge clk) begin
  if (rst || (!linkup)) begin
  if (rst || (!linkup)) begin
    cntrl_state                   <=  IDLE;
    cntrl_state                   <=  IDLE;
 
 
    h2d_features                  <=  `D2H_REG_FEATURES;
    h2d_features                  <=  `D2H_REG_FEATURES;
    srst                          <=  0;
    srst                          <=  0;
 
 
    //Strobes
    //Strobes
    t_send_control_stb            <=  0;
    t_send_control_stb            <=  0;
    cntrl_send_data_stb           <=  0;
    cntrl_send_data_stb           <=  0;
    pio_data_ready                <=  0;
    pio_data_ready                <=  0;
    status                        <=  0;
    status                        <=  0;
 
 
    prev_send_command             <=  0;
    sata_busy                     <=  0;
    send_command_stb              <=  0;
    sync_escape                   <=  0;
 
 
    reset_count                   <=  0;
 
    busy                          <=  1;
 
  end
  end
  else begin
  else begin
    t_send_control_stb            <=  0;
    t_send_control_stb            <=  0;
    cntrl_send_data_stb           <=  0;
    cntrl_send_data_stb           <=  0;
    pio_data_ready                <=  0;
    pio_data_ready                <=  0;
    send_command_stb              <=  0;
 
 
 
    //Reset Count
    //Reset Count
    if (reset_count < `RESET_TIMEOUT) begin
 
      reset_count                 <=  reset_count + 1;
 
    end
 
    if (!reset_timeout) begin
 
      cntrl_state                 <=  IDLE;
 
    end
 
 
 
    //detected the first a user attempting to send a command
 
    if (send_user_command_stb && !prev_send_command) begin
 
      prev_send_command           <=  1;
 
      send_command_stb            <=  1;
 
    end
 
    if (!send_user_command_stb) begin
 
      prev_send_command           <=  0;
 
    end
 
 
 
    if (t_d2h_reg_stb) begin
    if (t_d2h_reg_stb) begin
      busy                        <=  0;
      //Receiving a register strobe from the device
 
      sata_busy                   <=  0;
      h2d_features                <=  `D2H_REG_FEATURES;
      h2d_features                <=  `D2H_REG_FEATURES;
    end
    end
    if (t_send_command_stb || t_send_control_stb || send_user_command_stb) begin
    /*
      busy                        <=  1;
    if (t_send_command_stb || t_send_control_stb) begin
      if (send_user_command_stb) begin
      sata_busy                   <=  1;
 
    end
 
    */
 
    if (execute_command_stb) begin
        h2d_features              <=  user_features;
        h2d_features              <=  user_features;
      end
      sata_busy                   <=  1;
    end
    end
 
 
    case (cntrl_state)
    case (cntrl_state)
      IDLE: begin
      IDLE: begin
 
 
        //Soft Reset will break out of any flow
        //Soft Reset will break out of any flow
        if ((soft_reset_en) && !srst) begin
        if (command_layer_reset && !srst) begin
          srst                  <=  1;
          srst                  <=  1;
          t_send_control_stb    <=  1;
          t_send_control_stb    <=  1;
          reset_count           <=  0;
 
        end
        end
 
 
        if (idle) begin
        if (idle) begin
          //The only way to transition to another state is if CL is IDLE
          //The only way to transition to another state is if CL is IDLE
 
 
          //User Initiated commands
          //User Initiated commands
          if (!soft_reset_en && srst && reset_timeout) begin
          if (!command_layer_reset && srst) begin
            srst                  <=  0;
            srst                  <=  0;
            t_send_control_stb    <=  1;
            t_send_control_stb    <=  1;
          end
          end
       end
       end
 
 
        //Device Initiated Transfers
        //Device Initiated Transfers
        if(t_pio_setup_stb) begin
        if(t_pio_setup_stb) begin
          if (t_pio_direction) begin
          if (t_pio_direction) begin
            //Read from device
            //Read from device
            cntrl_state           <=  PIO_WAIT_FOR_DATA;
            cntrl_state           <=  PIO_WAIT_FOR_DATA;
          end
          end
          else begin
          else begin
            //Write to device
            //Write to device
            cntrl_state           <=  PIO_WRITE_DATA;
            cntrl_state           <=  PIO_WRITE_DATA;
          end
          end
        end
        end
        if (t_set_device_bits_stb) begin
        if (t_set_device_bits_stb) begin
          status                  <=  d2h_status;
          status                  <=  d2h_status;
          //status register was updated
          //status register was updated
        end
        end
        if (t_d2h_reg_stb) begin
        if (t_d2h_reg_stb) begin
          status                  <=  d2h_status;
          status                  <=  d2h_status;
        end
        end
      end
      end
      PIO_WAIT_FOR_DATA: begin
      PIO_WAIT_FOR_DATA: begin
        if (t_d2h_data_stb) begin
        if (t_d2h_data_stb) begin
          //the next peice of data is related to the PIO
          //the next peice of data is related to the PIO
          pio_data_ready          <=  1;
          pio_data_ready          <=  1;
          cntrl_state             <=  IDLE;
          cntrl_state             <=  IDLE;
          status                  <=  t_pio_e_status;
          status                  <=  t_pio_e_status;
        end
        end
      end
      end
      PIO_WRITE_DATA: begin
      PIO_WRITE_DATA: begin
        if (if_read_activate) begin
        if (if_read_activate) begin
          cntrl_send_data_stb     <=  0;
          cntrl_send_data_stb     <=  0;
          cntrl_state             <=  IDLE;
          cntrl_state             <=  IDLE;
          status                  <=  t_pio_e_status;
          status                  <=  t_pio_e_status;
        end
        end
      end
      end
 
 
      default: begin
      default: begin
        cntrl_state               <=  IDLE;
        cntrl_state               <=  IDLE;
      end
      end
    endcase
    endcase
 
 
    if (send_sync_escape) begin
    if (send_sync_escape) begin
      cntrl_state                 <=  IDLE;
      cntrl_state                 <=  IDLE;
      busy                        <=  0;
 
    end
 
  end
 
end
 
 
 
//Read State Machine
 
always @ (posedge clk) begin
 
  if (rst || (!linkup)) begin
 
    read_state                    <=  IDLE;
 
    sync_escape                   <=  0;
 
    read_data_stb                 <=  0;
 
    single_read_prev              <=  0;
 
    first_read                    <=  1;
 
  end
 
  else begin
 
    read_data_stb                 <=  0;
 
    sync_escape                   <=  0;
 
 
 
    if (!read_data_en) begin
 
      single_read_prev            <=  0;
 
    end
 
 
 
    case (read_state)
 
      IDLE: begin
 
        if (idle) begin
 
          sync_escape             <=  0;
 
          //The only way to transition to another state is if CL is IDLE
 
          if (read_data_en) begin
 
            if (single_rdwr) begin
 
              if (!single_read_prev) begin
 
                single_read_prev  <=  1;
 
                read_data_stb     <=  1;
 
                read_state        <=  WAIT_FOR_DATA;
 
              end
 
            end
 
            else begin
 
              //send a request to read data
 
              read_data_stb       <=  1;
 
              read_state          <=  WAIT_FOR_DATA;
 
            end
 
          end
 
          else begin
 
            first_read            <=  1;
 
          end
 
        end
 
      end
 
      WAIT_FOR_DATA: begin
 
        //This state seems useless because it only sets a value but the state is used to indicate the system is idle or not
 
        if (t_d2h_data_stb) begin
 
          first_read          <=  0;
 
        end
 
        /*
 
        if (soft_reset_en) begin
 
//XXX: Issue a SYNC ESCAPE to cancel a large read request otherwise let it play out
 
          //sync_escape         <=  1;
 
        end
 
      */
 
      end
 
      default: begin
 
        read_state                <=  IDLE;
 
      end
 
    endcase
 
 
 
    if (soft_reset_en || !reset_timeout || send_sync_escape) begin
 
      if (read_state  != IDLE) begin
 
        sync_escape               <=  1;
        sync_escape               <=  1;
      end
      sata_busy                   <=  0;
      if (send_sync_escape) begin
 
        sync_escape               <=  1;
 
      end
 
      read_state                  <=  IDLE;
 
    end
 
 
 
    //If this is received go back to IDLE
 
    if (t_d2h_reg_stb) begin
 
      read_state                  <=  IDLE;
 
    end
    end
  end
  end
end
end
 
 
//Write State Machine
//Write State Machine
always @ (posedge clk) begin
always @ (posedge clk) begin
  if (rst || (!linkup)) begin
  if (rst || !linkup) begin
    write_state                   <=  IDLE;
    write_state                   <=  IDLE;
 
 
    dma_send_data_stb             <=  0;
    dma_send_data_stb             <=  0;
 
 
    write_data_stb                <=  0;
 
    single_write_prev             <=  0;
 
    first_write                   <=  1;
 
    enable_tl_data_ready          <=  0;
    enable_tl_data_ready          <=  0;
 
    dma_act_detected_en           <=  0;
    dma_act_detected              <=  0;
 
  end
  end
  else begin
  else begin
    dma_send_data_stb             <=  0;
    dma_send_data_stb             <=  0;
    write_data_stb                <=  0;
 
 
 
    if (enable_tl_data_ready && if_read_activate) begin
 
      //Closes the loop on the data write feedback
 
      enable_tl_data_ready        <=  0;
 
    end
 
 
 
    if (!write_data_en) begin
 
      single_write_prev           <=  0;
 
    end
 
 
 
    if (t_dma_activate_stb) begin
    if (t_dma_activate_stb) begin
      //Set an enable signal instead of a strobe so that there is no chance of missing this signal
      //Set an enable signal instead of a strobe so that there is no chance of missing this signal
      dma_act_detected            <=  1;
      dma_act_detected_en         <=  1;
    end
    end
 
 
    case (write_state)
    case (write_state)
      IDLE: begin
      IDLE: begin
 
        enable_tl_data_ready      <=  0;
        if (idle) begin
        if (idle) begin
          //The only way to transition to another state is if CL is IDLE
          //The only way to transition to another state is if CL is IDLE
          if (write_data_en) begin
          //if (write_data_stb) begin
            if (single_rdwr) begin
          if (dma_act_detected_en) begin
              if (!single_write_prev) begin
 
                single_write_prev   <=  1;
 
                write_state         <=  WAIT_FOR_DMA_ACT;
 
                write_data_stb      <=  1;
 
              end
 
            end
 
            else begin
 
              //send a request to write data
              //send a request to write data
              write_state           <=  WAIT_FOR_DMA_ACT;
              write_state           <=  WAIT_FOR_DMA_ACT;
              write_data_stb        <=  1;
 
            end
 
          end
 
          else begin
 
            //reset the the first write when the user deassertes the write_data_en
 
            first_write             <=  1;
 
          end
          end
        end
        end
      end
      end
      WAIT_FOR_DMA_ACT: begin
      WAIT_FOR_DMA_ACT: begin
        if (dma_act_detected) begin
        if (dma_act_detected_en) begin
          dma_act_detected        <=  0;
          dma_act_detected_en     <=  0;
          first_write             <=  0;
 
          enable_tl_data_ready    <=  1;
          enable_tl_data_ready    <=  1;
          write_state             <=  WAIT_FOR_WRITE_DATA;
          write_state             <=  WAIT_FOR_WRITE_DATA;
        end
        end
      end
      end
      WAIT_FOR_WRITE_DATA: begin
      WAIT_FOR_WRITE_DATA: begin
        if (if_read_activate) begin
        if (if_read_activate) begin
 
          enable_tl_data_ready    <=  0;
          write_state             <=  SEND_DATA;
          write_state             <=  SEND_DATA;
        end
        end
      end
      end
      SEND_DATA: begin
      SEND_DATA: begin
        if (transport_layer_ready) begin
        if (transport_layer_ready) begin
          //Send the Data FIS
          //Send the Data FIS
          dma_send_data_stb       <=  1;
          dma_send_data_stb       <=  1;
          write_state             <=  WAIT_FOR_DMA_ACT;
          dma_act_detected_en     <=  0;
        end
 
      end
 
      WAIT_FOR_STATUS: begin
 
        if (t_d2h_reg_stb) begin
 
          write_state             <=  IDLE;
          write_state             <=  IDLE;
        end
        end
      end
      end
      default: begin
      default: begin
        write_state               <=  IDLE;
        write_state               <=  IDLE;
      end
      end
    endcase
    endcase
 
 
 
 
    if (soft_reset_en || !reset_timeout) begin
    //if (command_layer_reset || !reset_timeout) begin
 
    if (command_layer_reset) begin
      //Break out of the normal flow and return to IDLE
      //Break out of the normal flow and return to IDLE
      write_state                 <=  IDLE;
      write_state                 <=  IDLE;
    end
    end
    if (t_d2h_reg_stb) begin
    if (t_d2h_reg_stb) begin
      //Whenever I read a register transfer from the device I need to go back to IDLE
      //Whenever I read a register transfer from the device I need to go back to IDLE
      write_state                 <=  IDLE;
      write_state                 <=  IDLE;
    end
    end
    if (send_sync_escape) begin
    if (send_sync_escape) begin
      write_state                 <=  IDLE;
      write_state                 <=  IDLE;
    end
    end
  end
  end
end
end
 
 
 
 
 
 
endmodule
endmodule
 
 
 
 
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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