processor_interface.v
module processor_interface
(
    clock, resetj,
    up_pi_cs, up_pi_addr, up_pi_write, up_pi_read,
    up_pi_data, pi_up_data, pi_up_ready, pi_up_int,
    pi_tf_write, pi_tf_data, tf_pi_size, tf_pi_ready,
    pi_rf_read, rf_pi_data, rf_pi_size, rf_pi_ready,
    pi_ci_enable
);

// INTERFACE

    input         clock;
    input         resetj;

    // PROCESSOR BUS

    input         up_pi_cs;
    input   [1:0] up_pi_addr;
    input         up_pi_write;
    input         up_pi_read;
    input  [15:0] up_pi_data;
    output [15:0] pi_up_data;
    output        pi_up_ready;
    output        pi_up_int;

    // TRANSMIT FIFO INTERFACE

    output        pi_tf_write;
    output [15:0] pi_tf_data;
    input   [6:0] tf_pi_size;
    input         tf_pi_ready;

    // RECEIVE FIFO INTERFACE

    output        pi_rf_read;
    input  [15:0] rf_pi_data;
    input   [6:0] rf_pi_size;
    input         rf_pi_ready;

    // CHANNEL CONTROL BUS

    output  [1:0] pi_ci_enable;

// CONSTANTS

    // REGISTER ADDRESSES

    parameter     COS_Data     = 0;
    parameter     COS_Level    = 1;
    parameter     COS_Transmit = 2;
    parameter     COS_Receive  = 3;

// INTERNAL SIGNALS

    // CHANNEL ENABLES. THE "Enable" FIELDS OF "Transmit" AND "Receive"

    reg        tf_enable;
    reg        rf_enable;

    // CHANNEL INTERRUPT MASKS. THE "Mask" FIELDS OF "Transmit" AND "Receive"

    reg        tf_imask;
    reg        rf_imask;

    // INTERRUPT WATERMARK LEVEL. THE "Level" REGISTER

    reg [13:0] level;

    // OUTPUT DATA BUS

    reg [15:0] up_data;

    // OUTPUT INTERRUPT. THE "Interrupt" FIELDS OF "Transmit" AND "Receive"

    wire [1:0] up_int;

// IMPLEMENTATION

    always@(posedge clock or negedge resetj)

        // IF RESET ACTIVE, RESET REGISTERS

        if (!resetj)
        begin
            tf_enable <= 1'b0;
            rf_enable <= 1'b0;
            tf_imask  <= 1'b0;
            rf_imask  <= 1'b0;
            level     <= 14'b0;
        end

        // ELSE

        else
        begin
            // IF THIS IS A WRITE OPERATION

            if (up_pi_cs && up_pi_write)
            begin
                // SELECT THE REGISTER ASSOCIATED WITH THE ADDRESS

                case (up_pi_addr)

                // IF THE REGISTER IS "Level"

                COS_Level:

                    // WRITE TO THE "Level" REGISTER

                    level     <= up_pi_data[13:0];

                // IF THE REGISTER IS "Transmit"

                COS_Transmit:

                    // WRITE TO THE FIELDS OF "Transmit"

                    begin
                        tf_enable <= up_pi_data[15];
                        tf_imask  <= up_pi_data[14];
                    end

                // IF THE REGISTER IS "Receive"

                COS_Receive:

                    // WRITE TO THE FIELDS OF "Receive"

                    begin
                        rf_enable <= up_pi_data[15];
                        rf_imask  <= up_pi_data[14];
                    end
                endcase
            end
        end

    // SET THE OUTPUT DATA BUS FROM THE REGISTER SELECTED BY THE ADDRESS

    always@(up_pi_addr or rf_pi_data or level or tf_enable or tf_imask or
        rf_enable or rf_imask or up_int or tf_pi_size or rf_pi_size)

        // SELECT THE REGISTER ASSOCIATED WITH THE ADDRESS

        case (up_pi_addr)

        // IF THE REGISTER IS "Data"

        COS_Data:

            // READ THE RECEIVE FIFO

            up_data = rf_pi_data;

        // IF THE REGISTER IS "Level"

        COS_Level:

            // READ THE "Level" REGISTER

            up_data = level;

        // IF THE REGISTER IS "Transmit"

        COS_Transmit:

            // ASSEMBLE THE FIELDS OF "Transmit"

            up_data = {tf_enable, tf_imask, up_int[0], 6'b0, tf_pi_size};

        // IF THE REGISTER IS "Receive"

        COS_Receive:

            // ASSEMBLE THE FIELDS OF "Receive"

            up_data = {rf_enable, rf_imask, up_int[1], 6'b0, rf_pi_size};
        endcase

    assign pi_up_data = up_data;

    // ASSERT THE READY SIGNAL PROVIDED THE CHIP IS SELECTED AND...

    assign pi_up_ready = up_pi_cs && (

        // EITHER THE REGISTER IS NOT "Data"

        (up_pi_addr != COS_Data) ||

        // OR THE APPROPRIATE FIFO IS READY

        (tf_pi_ready && up_pi_write) ||
        (rf_pi_ready && up_pi_read));

    // ASSERT THE TRANSMIT/RECEIVE INTERRUPT IF NOT MASKED AND PROVIDED THE
    // TRANSMIT/RECEIVE FIFO CONTAINS MORE FREE/DATA WORDS THAN THE WATERMARK 

    assign up_int = {rf_imask & (rf_pi_size>level), tf_imask & (tf_pi_size>level)};

    // COMBINE THE INTERRUPT SIGNALS FOR OUTPUT TO THE PROCESSOR

    assign pi_up_int    = |up_int;

    // SET THE TRANSMIT FIFO DATA TO EQUAL THE PROCESSOR INPUT DATA BUS

    assign pi_tf_data   = up_pi_data;

    // ASSERT THE TRANSMIT/RECEIVE FIFO WRITE/READ SIGNAL IF THE CHIP IS
    // SELECTED AND THE "Data" REGISTER IS BEING WRITTEN/READ

    assign pi_tf_write  = up_pi_cs && up_pi_addr == COS_Data && up_pi_write;
    assign pi_rf_read   = up_pi_cs && up_pi_addr == COS_Data && up_pi_read;

    // ASSEMBLE THE CHANNEL CONTROL BUS

    assign pi_ci_enable = {rf_enable, tf_enable};

endmodule
© Copyright 2000-2001 Adrian Lewis