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);
}
Leave a Reply