ms_dma.v 4.38 KB
 /************************************************************************\
 *                                                                        *
 *               Copyright (C) 1994, Silicon Graphics, Inc.               *
 *                                                                        *
 *  These coded instructions, statements, and computer programs  contain  *
 *  unpublished  proprietary  information of Silicon Graphics, Inc., and  *
 *  are protected by Federal copyright  law.  They  may not be disclosed  *
 *  to  third  parties  or copied or duplicated in any form, in whole or  *
 *  in part, without the prior written consent of Silicon Graphics, Inc.  *
 *                                                                        *
 \************************************************************************/

// $Id: ms_dma.v,v 1.6 2003/01/24 23:07:37 berndt Exp $
//  cbus module for memspan dma requests, from jlsmith

//  this module takes memspan rdram dma requests (c/z r/w)
//  of up to 128 bytes (64 for writes) per request and acts
//  as interface between io and memspan;  the actual request
//  line is wired directly (as are grant, start, done) and are
//  not appearing here.  this module includes tristate cbus i/f.
//
//  a number of ports here are for diag use, as indicated;  the
//  widths and nature of these functions are still to be worked out.

//mod 11-15-94  read/write delay params updated (read_delay to be verified)

module ms_dma(clock, reset_l,
   cbus_read_enable, cbus_write_enable, cbus_select, cbus_command,
   read_grant, dma_read, dma_down, dma_address, dma_length,
   read_request,
   cbus_din, cbus_dout);

`include "ms.vh"

parameter READ_DELAY = 8'd2;
parameter WRITE_DELAY = -8'd2;

input clock;                                 // system clock
input reset_l;                               // system reset_l

input cbus_read_enable;                      // enable cbus read mux
input cbus_write_enable;                     // enable cbus tristate drivers
input [1:0] cbus_select;    // cbus data select
input [2:0] cbus_command;  // cbus data type
input read_grant;                            // read response granted
input dma_read;                              // DMA read/write select
input dma_down;                              // DMA up/down select
input [DRAM_ADDRESS_SIZE-1:0] dma_address;   // DMA slave address
input [DMA_LENGTH_SIZE-1:0] dma_length;      // DMA length in words

output read_request;                         // dma read request cycle

input [31:0] cbus_din;        // IO cbus
output [31:0] cbus_dout;        // IO cbus


// input/output registers
reg read_request;
reg [2:0] cbus_command_reg;
reg [31:0] cbus_data_reg;

assign  cbus_dout = cbus_write_enable ? cbus_data_reg : 32'b0;

always @(posedge clock) begin : cbus_block
   reg [31:0] cbus_data_out;

   case (cbus_select)
      `CBUS_SEL_ADDR : cbus_data_out = dma_address;
      `CBUS_SEL_LEN : case ({dma_down, dma_read})
         2'b00 : cbus_data_out = {DMA_BLOCK, DMA_MASKED, DMA_UP,
           DMA_NSEQ, `CBUS_DEV_SPAN, WRITE_DELAY, DMA_WRITE, dma_length};

         2'b01 : cbus_data_out = {DMA_BLOCK, DMA_NON_MASKED, DMA_UP,
           DMA_SEQ, `CBUS_DEV_SPAN, READ_DELAY, DMA_READ, dma_length};

         2'b10 : cbus_data_out = {DMA_BLOCK, DMA_MASKED, DMA_DOWN,
           DMA_NSEQ, `CBUS_DEV_SPAN, WRITE_DELAY, DMA_WRITE, dma_length};

         2'b11 : cbus_data_out = {DMA_BLOCK, DMA_NON_MASKED, DMA_DOWN,
           DMA_NSEQ, `CBUS_DEV_SPAN, READ_DELAY, DMA_READ, dma_length};
         endcase
      default : cbus_data_out = 'bx;
      endcase

   cbus_command_reg <= cbus_command;
   cbus_data_reg <= cbus_read_enable ? cbus_din : cbus_data_out;
   end


always @(posedge clock) begin
   if (reset_l == 1'b0) begin
      // resetable registers
      read_request <= LOW;
      end
   else begin : main_block
      reg next_read_request;
      reg [BUS_ID_SIZE-1:0] next_id;
      reg next_select;
      reg next_read_command;

      next_read_request = read_request;

      next_id = cbus_data_reg >> BUS_ID_OFFSET;
      next_select = next_id == `CBUS_SPAN;
      next_read_command = cbus_command_reg == `CBUS_CMD_READ;

      if (next_select) begin
         if (next_read_command) begin
            next_read_request = HIGH;
            end
         end

      if (read_request && read_grant) begin
         next_read_request = LOW;
         end

      read_request <= next_read_request;
      end
   end
endmodule