pif.v 9.33 KB

//vi: set tabstop=4 shiftwidth=4  wrapmargin=4:

/**************************************************************************
 *                                                                        *
 *               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.  *
 *                                                                        *
 *************************************************************************/

// to simulate restart switch depression, set nmi under program control
// nmi generation: if enable_nmi
//                 1 write 0xdeaddead to physical address 1fc007c0
//                 2 read 64B from if 1fc07c0 == deaddead , nmi will pulse





// $Id: pif.v,v 1.1 2002/03/28 00:26:11 berndt Exp $

module pif (pchclk, reset_l, 
    pch_cmd,
    pch_rsp, nmi_l);

`include "si.vh"

// in out list

input pchclk;
input reset_l;
// pchannel io
input pch_cmd;
output pch_rsp;
output nmi_l;


reg pch_rsp;
reg nmi_l;
reg nmi_enabled;
reg nmi_pending;

reg [11:0] pif_cnt ;
reg pch_cmd_reg;
reg pch_cmd_reg_d1;
reg pch_cmd_reg_d2;

reg [3:0] pif_state;

reg [511:0] pif_shf_reg;

reg [8:0] pif_adrs ;
reg [1:0] pif_operation;

reg [15:0] tempi;
reg pif_ack_given ;


// memory buffer
reg [31:0] memory[0:'d511]; // 512 words of 32 bits = 2kbytes


// memory debug monitor
reg [31:0] memory_monitor;

initial begin
    if ($test$plusargs("load_pif")) begin
       $display("loading PIF from pif.data...");
       $readmemh("pif.data", memory);
    end
    if ($test$plusargs("enable_nmi")) begin
        nmi_enabled = 1;
        $display("Requested nmi generation, nmi_enabled =  %h",nmi_enabled);
    end
end

reg pif_monitor;
initial pif_monitor = $test$plusargs("pif_mon");

always @ (negedge pchclk or negedge reset_l ) begin
    if ( reset_l == 0 ) begin
    pch_cmd_reg <= 1'b1;
    pch_cmd_reg_d1 <= 1'b1;
    pch_cmd_reg_d2 <= 1'b1;
    end
    else begin

    pch_cmd_reg <= pch_cmd;
    pch_cmd_reg_d1 <= pch_cmd_reg;
    pch_cmd_reg_d2 <= pch_cmd_reg_d1;
    end
end


always @ (posedge pchclk or negedge reset_l ) begin
    if (reset_l == 0 ) begin
        pif_state <= 0;
        pch_rsp <= 1;
        pif_shf_reg <= 0;
        pif_ack_given = 0;

	nmi_l = 1'b1;

    end
    else begin

    nmi_pending = 0;

        // if start detect
        if (pif_state == 0) begin
            if (pch_cmd_reg == 0 && pch_cmd_reg_d1 == 1) begin
                pif_state <= 1;
                pch_rsp <= 1;
                pif_cnt <= 11; // 11 word address shift
            end
        end
        if (pif_state == 1) begin
        // address phase
            if (pif_cnt != 0) begin
                pif_shf_reg[11:0] <= {pif_shf_reg[10:0] ,pch_cmd_reg};
                pif_cnt <= pif_cnt -1;
            end

            if (pif_cnt == 0) begin // address is shifted in
                pif_adrs <= pif_shf_reg[8:0];
                pif_operation <= pif_shf_reg[10:09];
                pif_state <= 2;
            end
        end
        // state 2, operation decode
        if (pif_state == 2) begin
            if (pif_operation == 0 ) begin // write64B
                pif_cnt <= 0; // do an upcount on pif_cnt for write
                pif_state <= 6 ; // go do pif write xfer handling
                // remove the force of address for 64B ops
		// pif_adrs <= 9'h1f0; // force ram address space for 64B
            end
            if ( pif_operation == 2) begin // write 4B 
                pif_cnt <= 0; // do an upcount on pif_cnt for write
                pif_state <= 6 ; // go do pif write xfer handling
            end
        

            if (pif_operation == 3) begin // read4B
                pif_shf_reg [31:0] <= memory[pif_adrs];
                pif_cnt <= 32;
                pif_state <= 3;
            end
            if (pif_operation == 1) begin // read64B

                pif_shf_reg[31:0] <= memory[pif_adrs+15];
                pif_shf_reg[63:32] <= memory[pif_adrs+14];
                pif_shf_reg[95:64] <= memory[pif_adrs+13];
                pif_shf_reg[127:96] <= memory[pif_adrs+12];
                pif_shf_reg[159:128] <= memory[pif_adrs+11];
                pif_shf_reg[191:160] <= memory[pif_adrs+10];
                pif_shf_reg[223:192] <= memory[pif_adrs+9];
                pif_shf_reg[255:224] <= memory[pif_adrs+8];
                pif_shf_reg[287:256] <= memory[pif_adrs+7];
                pif_shf_reg[319:288] <= memory[pif_adrs+6];
                pif_shf_reg[351:320] <= memory[pif_adrs+5];
                pif_shf_reg[383:352] <= memory[pif_adrs+4];
                pif_shf_reg[415:384] <= memory[pif_adrs+3];
                pif_shf_reg[447:416] <= memory[pif_adrs+2];
                pif_shf_reg[479:448] <= memory[pif_adrs+1];
                pif_shf_reg[511:480] <= memory[pif_adrs+0];
                if (nmi_enabled) begin
                        if (memory[pif_adrs] == 32'hdeaddead) begin
                            nmi_pending = 1;
                        end 
                end

                pif_cnt <= 512;
                pif_state <= 3;
            end

        end
        if (pif_state == 3) begin // ack the return read data
if (pif_monitor) begin
$display("PIF read4B  state 3: pif_shf_reg[31:0]  = %h", pif_shf_reg[31:0]);
end
            pch_rsp <= 0;
            pif_state <= 4;
        end
        if (pif_state == 4) begin // return read data
            if (pif_operation == 3) begin // read4B
                if (pif_cnt != 0) begin
                    pif_cnt <= pif_cnt -1;
                    pch_rsp <= pif_shf_reg [31];
                    pif_shf_reg [31:0] <= {pif_shf_reg[30:0],1'b0};
                end
                else if (pif_cnt == 0) begin
                    pif_state <= 0;
		    pch_rsp <= 1'b1;
                end
            end
            if (pif_operation == 1) begin // read64B
                if (pif_cnt != 0) begin
                        pif_cnt <= pif_cnt -1;
                        pch_rsp <= pif_shf_reg [511];
                        pif_shf_reg [511:0] <= {pif_shf_reg[510:0],1'b0};
                end
                else if (pif_cnt == 0) begin
                    pif_state <= 0;
		    pch_rsp <= 1'b1;
                end
            end
        end

        if (pif_state == 6) begin
            // issue a write ack to rcp, then wait for ack from rcp
            if (pif_ack_given == 0) begin
                pch_rsp <= 0; // ack the write operation request
                pif_ack_given <= 1;
            end
            else if (pif_ack_given == 1) begin
                pch_rsp <= 1; // end write ack
                //  wait for write start (ack)
                if (pch_cmd_reg_d1 == 0 && pch_cmd_reg_d2 == 1) begin
                    pif_state <= 7;
                    pif_ack_given <= 0; // clear out for next time
                end
            end
        end

        if (pif_state == 7) begin // pif write shift handler

            if (pif_operation == 0) begin // pif write 64B
                if (pif_cnt != 512) begin
                        pif_cnt <= pif_cnt +1;
                        pif_shf_reg [31:0] <= {pif_shf_reg[30:0],pch_cmd_reg_d1};
                        if ((pif_cnt !== 0) && (pif_cnt[4:0] == 0)) begin
                        // 32 bit multiple but not first time thru.
                            if (pif_adrs >= 9'h1f0) begin
                                // prevent writes to rom memory
                                memory[pif_adrs] = pif_shf_reg[31:0];   
                                if (pif_monitor) begin
                                    $display("PIF mem_write"," : pif_mem[%h] = %h",
                                        pif_adrs,pif_shf_reg[31:0]);
                                end
                            end
                            pif_adrs <= pif_adrs +1;
                        end
                end
                else  begin
                    memory[pif_adrs] = pif_shf_reg[31:0];
                    pif_state <= 0; // idle
                    if (pif_monitor) begin
                        
                      for (tempi = 10'h1f0 ; tempi < 10'h200; tempi = tempi +1) begin
                      $display("PIF write mem_data" , " : pif_mem[  %h ] = %h",
                                          tempi, memory[tempi] );

                      end
                    end


                end
            end
            if (pif_operation == 2) begin // pif write 4B
                if (pif_cnt != 32) begin
                    pif_cnt <= pif_cnt +1;
                    pif_shf_reg [31:0] <= {pif_shf_reg[30:0],pch_cmd_reg_d1};
                end
                if (pif_cnt[5:0] == 32) begin
                    memory[pif_adrs] = pif_shf_reg[31:0];
                    pif_state <= 0; // idle
if (pif_monitor) begin
$display("PIF mem_write"," : pif_mem[%h] = %h", pif_adrs,pif_shf_reg[31:0]);
end
                end
            end

        end // state == 7
    memory_monitor <= memory[pif_adrs];
    nmi_l = 1;

    if (nmi_pending) begin
        nmi_l = 0;
        nmi_pending = 0;
    end
    
    end // not reset
end // always


endmodule