IP Core for interfacing between PS2 Controller and DE10-nano

1. Pinout of PS2 Controller

2. Connection to DE10 nano

  • DATA -> GPIO_1[4]
  • ATTENTION (CS) -> GPIO_1[3]
  • CLOCK -> GPIO_1[1]
  • COMMAND -> GPIO_1[5]

3. System Verilog

a. IP core

b. Internal registers

parameter counterBitMax = 96;
reg    [counterBitMax:0]       status;
reg                            signal_clk;
reg                            signal_cmd;
reg                            signal_data;
reg                            signal_att;
reg    [            6:0]       counterCLK;
reg    [           17:0]       counterATT;
reg    [counterBitMax:0]       Data_cmd;
reg    [            7:0]       counterBit;

c. Logic control and clock generator

  • Activating Attention every 50ms.
  • In each period of 50ms, generate clock to read 96 bit.
  • Deactivating Attention after transferring 96 bit data completely.
  • The IP core uses 3.072 MHz clock.
// Generating SCLK generation and Controlling ATT
always_ff @ (posedge clk_3072) begin
    if (reset) begin
        counterATT <= 0;
        signal_att <= 1'b1;
        counterCLK <= 0;
        signal_clk <= 1'b1;
        counterBit <= 0;
    end
    else begin
        if (counterATT > 153600) begin
            counterATT <= 0;
            signal_att <= 0;
            counterCLK <= 0;
            signal_clk <= 1'b1;
            counterBit <= 0;
        end
        else begin
            if (counterBit > counterBitMax) begin
                signal_att <= 1'b1;
                counterCLK <= 0;
                signal_clk <= 1'b1;  
            end
            else begin
                signal_att <= 0;  
                if (counterCLK > 77) begin
                    counterCLK <= 0;
                    signal_clk <= ~signal_clk;
                    if (signal_clk) begin
                        counterBit <= counterBit + 1'b1;
                    end
                end
                else begin
                    counterCLK <= counterCLK + 1'b1;
                end  
            end          
            counterATT <= counterATT + 1'b1;
        end   
    end
end

d. Write to controller

// Write to Controller
always_ff @ (negedge signal_clk) begin
    if (reset) begin
        signal_cmd <= 'x;
    end
    else
        signal_cmd <= Data_cmd[counterBit];
end

e. Read from controller

// Read from Controller
always_ff @ (negedge signal_clk) begin
    if (reset) begin
        status <= 0;
    end
    else
        status[counterBit] <= signal_data;
end

f. Send data to Avalon

// Read operations performed on the Avalon-MM Slave interface
always_ff @ (posedge clk) begin
    if (reset) begin
        avs_s0_readdata <= 'x;   
    end
    else if (avs_s0_read) begin
        case (avs_s0_address)
            2'd0    : avs_s0_readdata <= status[31:0];
            2'd1    : avs_s0_readdata <= status[63:32];
            2'd2    : avs_s0_readdata <= status[95:64];
            default : avs_s0_readdata <= 'x;
        endcase 
    end
    else
        avs_s0_readdata <= 'x;
end

g. Build command from data which is sent from Avalon

// Write operations performed on the Avalon-MM Slave interface
always_ff @ (posedge clk) begin
    if (reset) begin
        Data_cmd <= {{80{1'b0}},8'h42,8'h01};
    end
    else begin
        if (avs_s0_write) begin   
            case (avs_s0_address)
                2'd0    : Data_cmd[31:0] <= avs_s0_writedata;
                2'd1    : Data_cmd[63:32] <= avs_s0_writedata;
                2'd2    : Data_cmd[95:64] <= avs_s0_writedata;
                default : Data_cmd <= {{80{1'b0}},8'h42,8'h01};
            endcase
        end
    end
end

h. Assign logic states

assign ps_cs       = signal_att;
assign ps_clk      = signal_clk;
assign ps_cmd      = signal_cmd;
assign signal_data = ps_dat;

4. C/C++ code to communicate with the IP core

/* Playstation wireless */
printf("\r\n---> Playstation IP...\r\n");
playstation_ip_map = getBASE(virtual_base,ALT_LWFPGASLVS_OFST,PLAYSTATION_WIRELESS_0_BASE,HW_REGS_MASK);
i = 0;
while(1){           
    printf("[%d] playstation_ip_map @ LW = 0x%08X,%08X,%08X @ %X\r\n",i,*(playstation_ip_map + 0x02),*(playstation_ip_map + 0x01),*playstation_ip_map,(uint32_t)playstation_ip_map);
    i++;
    // Wait 0.2s
    usleep(200000);
}

5. Testing

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *