想用FPGA读PS2手柄,用串口模块改装是否可行?
前提:1 PS2手柄宽接口的那种
PS手柄针脚输出端(面对插头)
---------------------------------------------------------
PIN 1->| ooo | ooo | ooo |
\________________________________/
2 PS手柄信号
PS手柄通讯都是8 bit串行数据最低有效位先行。在PS 手柄总线的所有时码在时钟下降沿都是同步的。传送一个字节的情况如下所示。
|BIT 0|BIT 1|BIT 2|BIT 3|BIT 4|BIT 5|BIT 6|BIT 7|
CLOCK -----___---___---___---___---___---___---___---___-----------
DATA-----000000111111222222333333444444555555666666777777--------
* * * * * * * *
CMND-----000000111111222222333333444444555555666666777777--------
注: CMND:FPGA端向手柄端发送指令
DATA:手柄端向FPGA端发送信号
3 串口收发模块借用《verilog那些事》里串口收发模块
两者异同:
同: 都是8位有效位,低位先行。
上升沿采集信号
收发互不干扰
异: 收发模块时钟同频率,但是不一定同步。
串口没有时钟线,PS2需要(FPGA端)提供时钟信号
正式问题:
在《verilog那些事》里串口收发模块各自都有BPS模块,但是发送端只有在有数据要发送时BPS才开始计时。接受模块也是在接受到第一位信号时BPS才开始计时的。我想把这两个BPS模块从收发模块中独立出来。用这个模块输出PS2端口的时钟,同时送给两个收发模块。收发模块都有使能信号。不使能时应该不会影响。
再加一个控制模块直接接受串口接收模块的8位数据,再发送另一个8位数据给串口发送模块。以实现解读PS2手柄信息。
想请教一下这种想法是否可行,如可行还有那些地方我要注意的也请多多指教。
另:本人基础薄弱,描述的不清楚请见谅。 肯定可以,但是为什么要用串口模块改装,不如重新写 zkf0100007 发表于 2015-1-21 19:05
肯定可以,但是为什么要用串口模块改装,不如重新写
开始懒得重写,现在越来越发现好像该还不如重写。 倒是可以参考PS键盘和鼠标的代码 zkf0100007 发表于 2015-1-22 09:11
倒是可以参考PS键盘和鼠标的代码
谢谢,两者很相似么?PS键盘没研究过 liyang53719 发表于 2015-1-22 18:54
谢谢,两者很相似么?PS键盘没研究过
------------------------------------------------------------------------
-- Keyboard.vhd -- Demonstrate basic keyboard function
------------------------------------------------------------------------
-- Author:Ken Nelson
-- Copyright 2004 Digilent, Inc.
------------------------------------------------------------------------
-- DESCRIPTION
------------------------------------------------------------------------
-- Revision History:
-- 06/14/04 (Created) KenN
--07/01/04 (Optomized) DanP
------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Keyboard is
Port ( CLK, RST, KD, KC: in std_logic;
an: out std_logic_vector (3 downto 0);
ssg: out std_logic_vector (6 downto 0));
end Keyboard;
architecture Behavioral of Keyboard is
------------------------------------------------------------------------
-- Component Declarations
------------------------------------------------------------------------
------------------------------------------------------------------------
-- Signal Declarations
------------------------------------------------------------------------
signal clkDiv : std_logic_vector (12 downto 0);
signal pclk : std_logic;
signal sclk:std_logic_vector(1 downto 0);
signal KDI, KCI : std_logic;
signal DFF1, DFF2 : std_logic;
signal shiftRegSig1: std_logic_vector(10 downto 0);
signal shiftRegSig2: std_logic_vector(10 downto 1);
signal MUXOUT: std_logic_vector (3 downto 0);
signal WaitReg: std_logic_vector (7 downto 0);
signal DisReg0,DisReg1,DisReg2,DisReg3:std_logic_vector (3 downto 0);
signal Dis:bit;
------------------------------------------------------------------------
-- Module Implementation
------------------------------------------------------------------------
begin
--Divide the master clock down to a lower frequency--
CLKDivider: Process (CLK)
begin
if (CLK = '1' and CLK'Event) then
clkDiv <= clkDiv +1;
end if;
end Process;
sclk <= clkDiv(11 downto 10);
pclk <= clkDiv(3);
--Flip Flops used to condition siglans coming from PS2--
Process (pclk, RST, KC, KD)
begin
if(RST = '1') then
DFF1 <= '0'; DFF2 <= '0'; KDI <= '0'; KCI <= '0';
else
if (pclk = '1' and pclk'Event) then
DFF1 <= KD; KDI <= DFF1; DFF2 <= KC; KCI <= DFF2;
end if;
end if;
end process;
--Shift Registers used to clock in scan codes from PS2--
Process(KDI, KCI, RST) --DFF2 carries KD and DFF4, and DFF4 carries KC
begin
if (RST = '1') then
ShiftRegSig1 <= "00000000000";
ShiftRegSig2 <= "0000000000";
else
if (KCI = '0' and KCI'Event) then
ShiftRegSig1(10 downto 0) <= KDI & ShiftRegSig1(10 downto 1);
ShiftRegSig2(10 downto 1) <= ShiftRegSig1(0) & ShiftRegSig2(10 downto 2);
end if;
end if;
end process;
--Wait Register
process(ShiftRegSig1, ShiftRegSig2, RST, KCI)
begin
if(RST = '1')then
WaitReg <= "00000000";
else
if(KCI'event and KCI = '1' and ShiftRegSig2(8 downto 1) = "11110000")then
WaitReg <= ShiftRegSig1(8 downto 1);
--case WaitReg is
--when "01000101"=> DisReg<="0000";--0
--when "00010110"=> DisReg<="0001";--1
--when "00011110"=> DisReg<="0010";--2
--when "00100110"=> DisReg<="0011";--3
--when "00100101"=> DisReg<="0100";--4
--when "00101110"=> DisReg<="0101";--5
--when "00110110"=> DisReg<="0110";--6
--when "00111101"=> DisReg<="0111";--7
--when "00111110"=> DisReg<="1000";--8
--when "01000110"=> DisReg<="1001";--9
--when "00011100"=> DisReg<="1010";--A
--when "00110010"=> DisReg<="1011";--B
--when "00100001"=> DisReg<="1100";--C
--when "00100011"=> DisReg<="1101";--D
--when "00100100"=> DisReg<="1110";--E
--when "00101011"=> DisReg<="1111";--F
--when others=>null;
--end case;
DisReg1<=DisReg0;
DisReg2<=DisReg1;
DisReg3<=DisReg2;
end if;
end if;
end Process;
DisReg0<="0000" when WaitReg="01000101" else --45 0
"0001"when WaitReg="00010110" else --16 1
"0010"when WaitReg="00011110" else --1E 2
"0011"when WaitReg="00100110" else --26 3
"0100"when WaitReg="00100101" else --25 4
"0101"when WaitReg="00101110" else --2E 5
"0110"when WaitReg="00110110" else --36 6
"0111"when WaitReg="00111101" else --3D 7
"1000"when WaitReg="00111110" else --3E 8
"1001"when WaitReg="01000110" else --46 9
"1010"when WaitReg="00011100" else --1C A
"1011"when WaitReg="00110010" else --32 B
"1100"when WaitReg="00100001" else --21 C
"1101"when WaitReg="00100011" else --23 D
"1110"when WaitReg="00100100" else --24 E
"1111"when WaitReg="00101011" else --2B F
"ZZZZ";
Dis<='1'when WaitReg="01000101" else
'1'when WaitReg="00010110" else
'1'when WaitReg="00011110" else --1E 2
'1'when WaitReg="00100110" else --26 3
'1'when WaitReg="00100101" else --25 4
'1'when WaitReg="00101110" else --2E 5
'1'when WaitReg="00110110" else --36 6
'1'when WaitReg="00111101" else --3D 7
'1'when WaitReg="00111110" else --3E 8
'1'when WaitReg="01000110" else --46 9
'1'when WaitReg="00011100" else --1C A
'1'when WaitReg="00110010" else --32 B
'1'when WaitReg="00100001" else --21 C
'1'when WaitReg="00100011" else --23 D
'1'when WaitReg="00100100" else --24 E
'1'when WaitReg="00101011" else --2B F
'0';
--Multiplexer
MUXOUT <=DisReg0 when sclk = "00" else
DisReg1 when sclk = "01" else
DisReg2 when sclk = "10" else
DisReg3 when sclk = "11";
--Seven Segment Decoder--
ssg <= "1000000" when MUXOUT = "0000" else
"1111001" when MUXOUT = "0001" else
"0100100" when MUXOUT = "0010" else
"0110000" when MUXOUT = "0011" else
"0011001" when MUXOUT = "0100" else
"0010010" when MUXOUT = "0101" else
"0000010" when MUXOUT = "0110" else
"1111000" when MUXOUT = "0111" else
"0000000" when MUXOUT = "1000" else
"0010000" when MUXOUT = "1001" else
"0001000" when MUXOUT = "1010" else
"0000011" when MUXOUT = "1011" else
"1000110" when MUXOUT = "1100" else
"0100001" when MUXOUT = "1101" else
"0000110" when MUXOUT = "1110" else
"0001110" when MUXOUT = "1111" else
"1111111";
--Anode Driver--
an<="1110" when sclk = "00" and Dis='1' else
"1101" when sclk = "01" and Dis='1' else
"1011" when sclk = "10" and Dis='1' else
"0111" when sclk = "11" and Dis='1' else
"1111";
end Behavioral; 上面是PS键盘的代码,可以参考一下 想读PS2手柄的话,用SPI正好 zkf0100007 发表于 2015-1-22 19:19
上面是PS键盘的代码,可以参考一下
多谢多谢,我研究一下 putty 发表于 2015-1-23 10:00
想读PS2手柄的话,用SPI正好
SPI是接口还是个协议?协议听说过I2C。 本帖最后由 liyang53719 于 2015-1-23 17:45 编辑
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity handset is
generic(divdelay:integer :=99999);
port(busclk :in std_logic; --shizhong
sclk :in std_logic; --
reset :in std_logic;
handdata :in std_logic;
command :out std_logic_vector(2 downto 0);
IDcheck1 :out std_logic_vector(7 downto 0);
IDcheck2 :out std_logic_vector(7 downto 0);
IDcheck3 :out std_logic_vector(7 downto 0);
recAnalogData1 :out std_logic_vector(7 downto 0);
recAnalogData2 :out std_logic_vector(7 downto 0);
recAnalogData3 :out std_logic_vector(7 downto 0);
recAnalogData4 :out std_logic_vector(7 downto 0);
recDigitalData1 :out std_logic_vector(7 downto 0);
recDigitalData2 :out std_logic_vector(7 downto 0));
endhandset;
architecture Behavioral of handset is
signal count :integerrange 0 to 8 := 0;
signal comdcount :integerrange 0 to 10 ;
signal temp_data : std_logic_vector(7 downto 0) :="11111111";
signal temp_command : std_logic_vector(2 downto 0) := "111";
signal comdstate :std_logic := '0';
signal comdstate1 :std_logic := '0';
signal comdstate2 :std_logic := '0';
signal comdstate3 :std_logic := '0';
signal comdstate4 :std_logic := '0';
signal delaystate :std_logic := '0';
signal delaystate1 :std_logic := '0';
signal delaystate2 :std_logic := '0';
signal result : std_logic_vector(8 downto 0) :="000000000";
signal HandsetMode :std_logic;
--signal comdstate1,comdstate2 : std_logic := '0';
begin
process(comdcount,temp_data(7 downto 0))
begin
case comdcount is
when 0 => temp_data(7 downto 0) <= "00000001";
when 1 => temp_data(7 downto 0) <= "01000010";
when 2 => temp_data(7 downto 0) <= "11111111";
when 3 => temp_data(7 downto 0) <= "11111111";
when 4 => temp_data(7 downto 0) <= "11111111";
when 5 => temp_data(7 downto 0) <= "11111111";
when 6 => temp_data(7 downto 0) <= "11111111";
when 7 => temp_data(7 downto 0) <= "11111111";
when 8 => temp_data(7 downto 0) <= "11111111";
when 9 => temp_data(7 downto 0) <= "11111111";
when others => null;
end case;
end process;
command(2 downto 0) <= temp_command(2 downto 0);
process(sclk,comdcount)
begin
if(comdcount = 9) then
temp_command(2) <= '1';--拉高ATT
comdstate <= '0';
elsif(sclk'EVENT and sclk = '1')then
comdstate <= '1';
temp_command(2) <= '0';--拉低ATT
end if;
end process;
process(busclk,temp_data(7 downto 0),comdstate,comdstate1,comdstate2,comdstate3,delaystate1,delaystate2,handdata,count,comdcount)
variable tempcount :integer range 0 to 99999 :=0;
variable count1 :integer range 0 to 9 :=0;
begin
--if(sclk'EVENT and sclk = '1')then
--comdstate1 <= '1';
--end if;
if(busclk'EVENT and busclk = '1')then
if(comdstate = '1')then
if(tempcount = 99999)then
tempcount := 0;
comdstate1 <= '1';
else
tempcount := tempcount + 1;
if(count1 = 8)then
--count <= 0;
case comdcount is
when 0 => null;
IDcheck1(7 downto 0)<= result(7 downto 0);
when 1 => null;
IDcheck2(7 downto 0)<= result(7 downto 0);
when 2 => null;IDcheck3(7 downto 0)<= result(7 downto 0);
when 3 =>
recDigitalData1(7 downto 0)<= result(7 downto 0);
when 4 =>
recDigitalData2(7 downto 0)<= result(7 downto 0);
when 5 =>
recAnalogData1(7 downto 0)<= result(7 downto 0);
when 6 =>
recAnalogData2(7 downto 0)<= result(7 downto 0);
when 7 =>
recAnalogData3(7 downto 0)<= result(7 downto 0);
when 8 =>
recAnalogData4(7 downto 0)<= result(7 downto 0);
when others => comdcount <= 0;
end case;
if (delaystate = '1')then
comdcount <= comdcount + 1;
comdstate1 <= '1';
comdstate4 <= '0';
count1 := 0;
end if;
elsif(comdstate1 = '1')then
temp_command(0) <= temp_data(count);
temp_command(1) <= '1';
comdstate1 <= '0';
comdstate2 <= '1';
elsif(delaystate1 = '1')then
temp_command(1) <= '0';
comdstate2 <= '0';
comdstate3 <= '1';
result(count) <= handdata;
elsif(delaystate2 = '1')then
--result(count) <= handdata;
comdstate3 <= '0';
count1 := count1 + 1;
if (count1 = 8) then
comdstate1 <= '0';
comdstate4 <= '1';
temp_command(1) <= '1';
count <= 0;
else
temp_command(1) <= '1';
comdstate1 <= '1';
count <= count1;
end if;
end if;
end if;
else
comdcount <= 0;
tempcount := 99999;
comdstate1 <= '0';
comdstate2 <= '0';
comdstate3 <= '0';
temp_command(1 downto 0) <= "11";
end if;
end if;
end process;
--process(busclk,count,handdata)
--begin
--if(busclk'EVENT and busclk = '1')then
-- result(count) <= handdata;
--end if;
--end process;
process(busclk,comdstate2,comdstate3)
variable delaycount: integerrange 0 to 3999 := 499;
begin
if(busclk'EVENT and busclk = '1')then
if(comdstate4 = '1') then
delaycount := delaycount + 1;
if(delaycount = 2*divdelay - 1)then
delaystate <= '1';
elsif(delaycount = 2*divdelay)then
delaystate <= '0';
delaycount := 0;
end if;
elsif(comdstate2 = '1') then
delaycount := delaycount + 1;
if(delaycount = divdelay-1)then
delaystate1 <= '1';
elsif(delaycount = divdelay)then
delaystate1 <= '0';
delaycount := 0;
end if;
elsif(comdstate3 = '1') then
delaycount := delaycount + 1;
if(delaycount = divdelay-1)then
delaystate2 <= '1';
elsif(delaycount = divdelay )then
delaystate2 <= '0';
delaycount := 0;
end if;
else
delaystate2 <= '0';
delaystate1 <= '0';
delaycount := 0;
end if;
end if;
end process;
end Behavioral; 找到一个VHDL写的程序,看起来有些吃力,大家一起来分析分析 本帖最后由 liyang53719 于 2015-1-23 22:50 编辑
经过测试这段程序完全可用!
//-------------------------------------------------------------------
//
// PLAYSTATION CONTROLLER(DUALSHOCK TYPE) INTERFACE TOP
//
// Version : 2.00
//
// Copyright(c) 2003 - 2004 Katsumi Degawa , All rights reserved
//
// Important !
//
// This program is freeware for non-commercial use.
// An author does no guarantee about this program.
// You can use this under your own risk.
//
// 2003.10.30It is optimized . by K Degawa
//
//-------------------------------------------------------------------
`timescale 100ps/10ps
//--------- SIMULATION ----------------------------------------------
//`define SIMULATION_1
`ifdef SIMULATION_1
`define Timer_siz 18
`else
`define Timer_siz 12
`endif
//-------------------------------------------------------------------
`define Dualshock
module psPAD_top(
I_CLK250K, //MAIN CLK 250KHz
I_RSTn, //MAIN RESET
O_psCLK, //psCLK CLK OUT
O_psSEL, //psSEL OUT
O_psTXD, //psTXD OUT
I_psRXD, //psRXD IN
O_RXD_1, //RX DATA 1 (8bit)
O_RXD_2, //RX DATA 2 (8bit)
O_RXD_3, //RX DATA 3 (8bit)
O_RXD_4, //RX DATA 4 (8bit)
O_RXD_5, //RX DATA 5 (8bit)
O_RXD_6, //RX DATA 6 (8bit)
I_CONF_SW, //Dualshook ConfigACTIVE-HI
I_MODE_SW, //Dualshook Mode Set DEGITAL PAD 0: ANALOG PAD 1:
I_MODE_EN, //Dualshook Mode ControlOFF 0: ON 1:
I_VIB_SW, //Vibration SWVIB_SW Small Moter OFF 0:ON1:
// VIB_SW Bic Moter OFF 0:ON1(Dualshook Only)
I_VIB_DAT //Vibration(Bic Moter)Data 8'H00-8'HFF (Dualshook Only)
);
inputI_CLK250K,I_RSTn;
inputI_CONF_SW;
inputI_MODE_SW,I_MODE_EN;
inputI_VIB_SW;
inputI_VIB_DAT;
inputI_psRXD;
output O_psCLK;
output O_psSEL;
output O_psTXD;
output O_RXD_1;
output O_RXD_2;
output O_RXD_3;
output O_RXD_4;
output O_RXD_5;
output O_RXD_6;
wire W_scan_seq_pls;
wire W_type;
wire W_byte_cnt;
wire W_RXWT;
wire W_TXWT;
wire W_TXSET;
wire W_TXEN;
wire W_TXD_DAT;
wire W_RXD_DAT;
wire W_conf_ent;
ps_pls_gan pls(
.I_CLK(I_CLK250K),
.I_RSTn(I_RSTn),
.I_TYPE(W_type), // DEGITAL PAD 0: ANALOG PAD 1:
.O_SCAN_SEQ_PLS(W_scan_seq_pls),
.O_RXWT(W_RXWT),
.O_TXWT(W_TXWT),
.O_TXSET(W_TXSET),
.O_TXEN(W_TXEN),
.O_psCLK(O_psCLK),
.O_psSEL(O_psSEL),
.O_byte_cnt(W_byte_cnt),
//.Timer(O_Timer)
.Timer()
);
`ifdef Dualshock
txd_commnd cmd(
.I_CLK(W_TXSET),
.I_RSTn(I_RSTn),
.I_BYTE_CNT(W_byte_cnt),
.I_MODE({I_CONF_SW,~I_MODE_EN,I_MODE_SW}),
.I_VIB_SW(I_VIB_SW),
.I_VIB_DAT(I_VIB_DAT),
.I_RXD_DAT(W_RXD_DAT),
.O_TXD_DAT(W_TXD_DAT),
.O_TYPE(W_type),
.O_CONF_ENT(W_conf_ent)
);
`else
txd_commnd_EZ cmd(
.I_CLK(W_TXSET),
.I_RSTn(I_RSTn),
.I_BYTE_CNT(W_byte_cnt),
.I_MODE(),
.I_VIB_SW(I_VIB_SW),
.I_VIB_DAT(),
.I_RXD_DAT(),
.O_TXD_DAT(W_TXD_DAT),
.O_TYPE(W_type),
.O_CONF_ENT(W_conf_ent)
);
`endif
ps_txd txd(
.I_CLK(I_CLK250K),
.I_RSTn(I_RSTn),
.I_WT(W_TXWT),
.I_EN(W_TXEN),
.I_TXD_DAT(W_TXD_DAT),
.O_psTXD(O_psTXD)
);
ps_rxd rxd(
.I_CLK(O_psCLK),
.I_RSTn(I_RSTn),
.I_WT(W_RXWT),
.I_psRXD(I_psRXD),
.O_RXD_DAT(W_RXD_DAT)
);
//---------- RXD DATA DEC----------------------------------------
reg O_RXD_1;
reg O_RXD_2;
reg O_RXD_3;
reg O_RXD_4;
reg O_RXD_5;
reg O_RXD_6;
reg W_rxd_mask;
always@(posedge W_scan_seq_pls)
W_rxd_mask <= ~W_conf_ent;
always@(negedge W_RXWT)
begin
if(W_rxd_mask)begin
case(W_byte_cnt)
3: O_RXD_1 <= W_RXD_DAT;
4: O_RXD_2 <= W_RXD_DAT;
5: O_RXD_3 <= W_RXD_DAT;
6: O_RXD_4 <= W_RXD_DAT;
7: O_RXD_5 <= W_RXD_DAT;
8: O_RXD_6 <= W_RXD_DAT;
default:;
endcase
end
end
endmodule
`ifdef Dualshock
module txd_commnd_EZ(
I_CLK,
I_RSTn,
I_BYTE_CNT,
I_MODE,
I_VIB_SW,
I_VIB_DAT,
I_RXD_DAT,
O_TXD_DAT,
O_TYPE,
O_CONF_ENT
);
inputI_CLK,I_RSTn;
inputI_BYTE_CNT;
inputI_MODE;
inputI_VIB_SW;
inputI_VIB_DAT;
inputI_RXD_DAT;
output O_TXD_DAT;
output O_TYPE;
output O_CONF_ENT;
reg O_TXD_DAT;
assign O_TYPE = 1'b1;
assign O_CONF_ENT = 1'b0;
always@(posedge I_CLK or negedge I_RSTn)
begin
if(! I_RSTn)begin
O_TXD_DAT <= 8'h00;
end
else begin
case(I_BYTE_CNT)
0:O_TXD_DAT <= 8'h01;
1:O_TXD_DAT <= 8'h42;
3:begin
if(I_VIB_SW) O_TXD_DAT <= 8'h40;
else O_TXD_DAT <= 8'h00;
end
4:begin
if(I_VIB_SW) O_TXD_DAT <= 8'h01;
else O_TXD_DAT <= 8'h00;
end
default: O_TXD_DAT <= 8'h00;
endcase
end
end
endmodule
`endif
module txd_commnd(
I_CLK,
I_RSTn,
I_BYTE_CNT,
I_MODE,
I_VIB_SW,
I_VIB_DAT,
I_RXD_DAT,
O_TXD_DAT,
O_TYPE,
O_CONF_ENT
);
inputI_CLK,I_RSTn;
inputI_BYTE_CNT;
inputI_MODE;
inputI_VIB_SW;
inputI_VIB_DAT;
inputI_RXD_DAT;
output O_TXD_DAT;
output O_TYPE;
output O_CONF_ENT;
wire pad_mode = I_MODE;
wire ds_sw= I_MODE;
reg O_TXD_DAT;
reg conf_state;
reg conf_entry;
reg conf_ent_reg;
reg conf_done;
reg pad_status;
reg pad_id;
assign O_TYPE = pad_id;
assign O_CONF_ENT = conf_entry;
always@(posedge I_CLK or negedge I_RSTn)
begin
if(! I_RSTn) pad_id <= 1'b0;
else begin
if(I_BYTE_CNT==2)begin
case(I_RXD_DAT) //------GET TYPE(Byte_SEQ)
8'h23: pad_id <= 1'b1;
8'h41: pad_id <= 1'b0;
8'h53: pad_id <= 1'b1;
8'h73: pad_id <= 1'b1;
8'hE3: pad_id <= 1'b1;
8'hF3: pad_id <= 1'b1;
default: pad_id <= 1'b0;
endcase
end
end
end
always@(posedge I_CLK or negedge I_RSTn)
begin
if(! I_RSTn)begin
O_TXD_DAT <= 8'h00;
conf_entry <= 1'b0;
conf_ent_reg <= 1'b0;
conf_done <= 1'b1;
conf_state <= 0;
pad_status <= 0;
end
else begin
//---------- nomal mode --------------------------------------------------------
//----------------- read_data_and_vibrate_ex 01,42,00,WW,PP(,00,00,00,00)
// --,ID,SS,XX,XX(,XX,XX,XX,XX)
if(~conf_entry)begin
case(I_BYTE_CNT)
0:O_TXD_DAT <= 8'h01;
1:O_TXD_DAT <= 8'h42;
3:begin
if(I_RXD_DAT==8'h00) conf_ent_reg <= 1'b1;
if(pad_status)begin
if(I_VIB_SW) O_TXD_DAT <= 8'h01;
else O_TXD_DAT <= 8'h00;
end
else begin
if(I_VIB_SW | I_VIB_SW) O_TXD_DAT <= 8'h40;
else O_TXD_DAT <= 8'h00;
end
end
4:begin
if(pad_status)begin
if(I_VIB_SW) O_TXD_DAT <= I_VIB_DAT;
else O_TXD_DAT <= 8'h00;
end
else begin
if(I_VIB_SW | I_VIB_SW) O_TXD_DAT <= 8'h01;
else O_TXD_DAT <= 8'h00;
end
if(pad_id==0)begin
if(conf_state == 0 && ds_sw)
conf_entry <= 1'b1;
if(conf_state == 7 && (pad_status&conf_ent_reg))begin
conf_state <= 0;
conf_entry <= 1'b1;
end
end
end
8:begin
O_TXD_DAT <= 8'h00;
if(pad_id==1)begin
if(conf_state == 0 && ds_sw)
conf_entry <= 1'b1;
if(conf_state == 7 && (pad_status&conf_ent_reg))begin
conf_state <= 0;
conf_entry <= 1'b1;
end
end
end
default: O_TXD_DAT <= 8'h00;
endcase
end
//---------- confg mode --------------------------------------------------------
else begin
case(conf_state)
//-------- config_mode_enter (43): 01,43,00,01,00(,00 x 4 or XX x 16)
// --,ID,SS,XX,XX(,XX x 4 or XX x 16)
0:begin
case(I_BYTE_CNT)
0:begin
O_TXD_DAT <= 8'h01;
conf_done <= 1'b0;
end
1:O_TXD_DAT <= 8'h43;
3:O_TXD_DAT <= 8'h01;
4:begin
O_TXD_DAT <= 8'h00;
if(pad_id==0)begin
if(pad_status) conf_state <= 3;
else conf_state <= 1;
end
end
8:begin
O_TXD_DAT <= 8'h00;
if(pad_id==1)begin
if(pad_status) conf_state <= 3;
else conf_state <= 1;
end
end
default:O_TXD_DAT <= 8'h00;
endcase
end
//-------- query_model_and_mode (45):01,45,00,5A,5A,5A,5A,5A,5A
// FF,F3,5A,TT,02,MM,VV,01,00
1:begin
case(I_BYTE_CNT)
0:O_TXD_DAT <= 8'h01;
1:O_TXD_DAT <= 8'h45;
2:begin
O_TXD_DAT <= 8'h00;
conf_done <= (I_RXD_DAT == 8'hF3)? 1'b0:1'b1;
end
4:begin
O_TXD_DAT <= 8'h00;
if(I_RXD_DAT==8'h01 || I_RXD_DAT==8'h03) pad_status <= 1;
if(pad_id==0 && conf_done==1'b1)begin
conf_state <= 7;
conf_entry <= 1'b0;
end
end
8:begin
O_TXD_DAT <= 8'h00;
conf_state <= 2;
if(pad_id==1 && conf_done==1'b1)begin
conf_state <= 7;
conf_entry <= 1'b0;
end
end
default:O_TXD_DAT <= 8'h00;
endcase
end
//-------- set_mode_and_lock (44): 01,44,00,XX,YY,00,00,00,00
// --,F3,5A,00,00,00,00,00,00
2:begin
case(I_BYTE_CNT)
0:O_TXD_DAT <= 8'h01;
1:O_TXD_DAT <= 8'h44;
3:O_TXD_DAT <= pad_mode ? 8'h01:8'h00;
4:O_TXD_DAT <= pad_mode ? 8'h03:8'h00;
8:begin
O_TXD_DAT <= 8'h00;
conf_state<= 3;
end
default:O_TXD_DAT <= 8'h00;
endcase
end
//-------- vibration_enable (4D): 01,4D,00,00,01,FF,FF,FF,FF
// --,F3,5A,XX,YY,FF,FF,FF,FF
3:begin
case(I_BYTE_CNT)
0:O_TXD_DAT <= 8'h01;
1:O_TXD_DAT <= 8'h4D;
2,3:O_TXD_DAT <= 8'h00;
4:O_TXD_DAT <= 8'h01;
8:begin
O_TXD_DAT <= 8'hFF;
conf_state<= 6;
end
default:O_TXD_DAT <= 8'hFF;
endcase
end
//-------- config_mode_exit (43): 01,43,00,00,5A,5A,5A,5A,5A
// --,F3,5A,00,00,00,00,00,00
6:begin
case(I_BYTE_CNT)
0:O_TXD_DAT <= 8'h01;
1:O_TXD_DAT <= 8'h43;
2,3:O_TXD_DAT <= 8'h00;
8:begin
O_TXD_DAT <= 8'h5A;
conf_state<= 7;
conf_entry<= 1'b0;
conf_done <= 1'b1;
conf_ent_reg<= 1'b0;
end
default:O_TXD_DAT <= 8'h5A;
endcase
end
default:;
endcase
end
end
end
endmodule
module ps_pls_gan(
I_CLK,
I_RSTn,
I_TYPE,
O_SCAN_SEQ_PLS,
O_RXWT,
O_TXWT,
O_TXSET,
O_TXEN,
O_psCLK,
O_psSEL,
O_byte_cnt,
Timer
);
parameter Timer_size = `Timer_siz;
inputI_CLK,I_RSTn;
inputI_TYPE;
output O_SCAN_SEQ_PLS;
output O_RXWT;
output O_TXWT;
output O_TXSET;
output O_TXEN;
output O_psCLK;
output O_psSEL;
output O_byte_cnt;
output Timer;
reg Timer;
reg O_SCAN_SEQ_PLS;
reg RXWT;
reg TXWT;
reg TXSET;
reg psCLK_gate;
reg psSEL;
reg O_byte_cnt;
always@(posedge I_CLK or negedge I_RSTn)
begin
if(! I_RSTn) Timer <= 0;
else Timer <= Timer+1;
end
always@(posedge I_CLK or negedge I_RSTn)
begin
if(! I_RSTn)
O_SCAN_SEQ_PLS <= 0;
else begin
if(Timer == 0) O_SCAN_SEQ_PLS <= 1;
else O_SCAN_SEQ_PLS <= 0;
end
end
always@(posedge I_CLK or negedge I_RSTn)
begin
if(! I_RSTn)
begin
psCLK_gate <= 1;
RXWT <= 0;
TXWT <= 0;
TXSET <= 0;
end
else begin
case(Timer)
6: TXSET <= 1;
8: TXSET <= 0;
9: TXWT <= 1;
11: TXWT <= 0;
12: psCLK_gate <= 0;
20: psCLK_gate <= 1;
21: RXWT <= 1;
23: RXWT <= 0;
default:;
endcase
end
end
always@(posedge I_CLK or negedge I_RSTn)
begin
if(! I_RSTn)
psSEL <= 1;
else begin
if(O_SCAN_SEQ_PLS == 1)
psSEL <= 0;
else if((I_TYPE == 0)&&(Timer == 158))
psSEL <= 1;
else if((I_TYPE == 1)&&(Timer == 286))
psSEL <= 1;
end
end
always@(posedge I_CLK or negedge I_RSTn)
begin
if(! I_RSTn)
O_byte_cnt <= 0;
else begin
if( O_SCAN_SEQ_PLS == 1)
O_byte_cnt <= 0;
else begin
if( Timer == 5'b11111)begin
if(I_TYPE == 0 && O_byte_cnt == 5)
O_byte_cnt <= O_byte_cnt;
else if(I_TYPE == 1 && O_byte_cnt == 9)
O_byte_cnt <= O_byte_cnt;
else
O_byte_cnt <= O_byte_cnt+1;
end
end
end
end
assign O_psCLK = psCLK_gate | I_CLK | psSEL;
assign O_psSEL = psSEL;
assign O_RXWT= ~psSEL&RXWT;
assign O_TXSET = ~psSEL&TXSET;
assign O_TXWT= ~psSEL&TXWT;
assign O_TXEN= ~psSEL&(~psCLK_gate);
endmodule
module ps_rxd(
I_CLK,
I_RSTn,
I_WT,
I_psRXD,
O_RXD_DAT
);
input I_CLK,I_RSTn,I_WT;
input I_psRXD;
output O_RXD_DAT;
reg O_RXD_DAT;
reg sp;
always@(posedge I_CLK or negedge I_RSTn)
if(! I_RSTn) sp <= 1;
else sp <= { I_psRXD, sp};
always@(posedge I_WT or negedge I_RSTn)
if(! I_RSTn) O_RXD_DAT <= 1;
else O_RXD_DAT <= sp;
endmodule
module ps_txd(
I_CLK,
I_RSTn,
I_WT,
I_EN,
I_TXD_DAT,
O_psTXD
);
input I_CLK,I_RSTn;
input I_WT,I_EN;
input I_TXD_DAT;
output O_psTXD;
reg O_psTXD;
reg ps;
always@(negedge I_CLK or negedge I_RSTn)
begin
if(! I_RSTn)begin
O_psTXD <= 1;
ps <= 0;
end
else begin
if(I_WT)
ps<= I_TXD_DAT;
else begin
if(I_EN)begin
O_psTXD <= ps;
ps <= {1'b1, ps};
end
else begin
O_psTXD <= 1'd1;
ps<= ps;
end
end
end
end
endmodule 这是刚找到的另一个verilog的代码,光看引脚名称感觉这个更靠谱一点。这个应该是最核心的模块,我们分析分析吧! liyang53719 发表于 2015-1-23 17:41
经过测试这段程序完全可用!
楼主,这个可以直接用吗,ps手柄与开发板如何连接呢,能详细说说具体测试过程吗,{:loveliness:} 测试结果如何呢 PS2手柄的接口比SPI多了一个ACK线,用SPI在加一根ACK线就可以了,具体的协议可以公布吗,我不知道啊 steinwai 发表于 2015-3-11 19:25
楼主,这个可以直接用吗,ps手柄与开发板如何连接呢,能详细说说具体测试过程吗, 测试结 ...
可以直接用 具体接口网上应该有 我现在不在学校了 东西都不在了 funnybow 发表于 2015-3-11 22:45
PS2手柄的接口比SPI多了一个ACK线,用SPI在加一根ACK线就可以了,具体的协议可以公布吗,我不知道啊 ...
网上可以搜到,搜PSX试试 liyang53719 发表于 2015-3-14 21:15
可以直接用 具体接口网上应该有 我现在不在学校了 东西都不在了
已经搜了好几天了,各种实在是搜不到{:cry:} ,lz能给点线索吗,提示一下关键字也行啊 steinwai 发表于 2015-3-15 22:50
已经搜了好几天了,各种实在是搜不到 ,lz能给点线索吗,提示一下关键字也行啊 ...
PS2 PSX 接口时序 通信协议 之类的你试试。我记得有个英文的最全 steinwai 发表于 2015-3-15 22:50
已经搜了好几天了,各种实在是搜不到 ,lz能给点线索吗,提示一下关键字也行啊 ...
看这个
http://www.amobbs.com/thread-947324-1-1.html 十三楼的那几个IO和手柄的管脚如何对应呢?名字都不一样看起来好费力 steinwai 发表于 2015-3-16 23:39
十三楼的那几个IO和手柄的管脚如何对应呢?名字都不一样看起来好费力
DATA -to I_psRXD
CLK -to O_psCLK
COMMAND -to O_psTXD
ATT -to O_psSEL
原来的资料找不到了。这是我之前做的笔记。你们看看能否有帮助 本帖最后由 steinwai 于 2015-3-19 20:30 编辑
补充:用之前还得先分个250k的频给I_CLK250K 找到了完整的工程文件,来分享一下{:smile:}{:victory:} att command clk 在示波器中显示都好,但data在按键时完全没图像 steinwai 发表于 2015-3-20 20:36
att command clk 在示波器中显示都好,但data在按键时完全没图像
有红灯模式绿灯模式,你按一下mode键试试,或者动摇干 lz能否共享一下你的工程呢?搞了好久都没成功{:sleepy:}{:cry:} lz请求帮助,please{:3_60:} steinwai 发表于 2015-4-5 10:28
lz请求帮助,please
工程原文件都在学校了没带出来。我现在也只有13楼那个代码。
你先搞清楚PS2接口的定义,就是名字。然后用RTL视图找代码接口。
按照下面这种方法接
DATA -to I_psRXD
CLK -to O_psCLK
COMMAND -to O_psTXD
ATT -to O_psSEL
还有你需要给代码一个时钟信号,具体数值我忘了,10M,50M你都试一下。
手柄和FPGA接好之后,打开signaltap II监测每个输出引脚电平变化。然后上电。你要做的就是按下手柄上的一个键去Signaltap II里找电平变化的对应脚。高变低还是低变高我也忘了。总之会有变化(注意采样深度太大可能会有延时)。如果没反应,按下mode键再试,或者按两次再试。找到按键和对应脚记下来。将来可以做个顶层打包的东西用。
过程大概就是这样。这个代码是没问题的,我也抱着怀疑的心态试了很久。但是是可以用的。你要工程的话我这里是没有了,现在也没时间再弄这个了。
希望可以帮到你。 I_CLK250K, //MAIN CLK 250KH这句不是表示需要一个250khz的时钟给顶层吗,于是我就先写了个分频器给他,是直接用板子的50m时钟就好了 吗{:3_49:} 非常感谢lz耐心指教 看了一篇文章解释的data与按键对应,还想再请教一下,如何在signaltap中让时间轴变长一点呢?得到第4和5byte才能判断按键呐{:3_57:} 我的系统时钟是50m的,不会分10m,于是只好对半分了,也就是25m
steinwai 发表于 2015-4-5 11:08
I_CLK250K, //MAIN CLK 250KH这句不是表示需要一个250khz的时钟给顶层吗,于是我就先写了个分频器 ...
分个频是对的,可能是我记错了 steinwai 发表于 2015-4-5 15:37
看了一篇文章解释的data与按键对应,还想再请教一下,如何在signaltap中让时间轴变长一点呢?得到第4和5byt ...
让时间轴变长一点
这个没理解 liyang53719 发表于 2015-4-5 22:29
让时间轴变长一点
这个没理解
就是想让波形多显示一点, 不然图像太短了显示不到第4,5个byte steinwai 发表于 2015-4-6 19:16
不然图像太短了显示不到第4,5个byte
采样深度大一点。改成2k或以上试试 liyang53719 发表于 2015-4-6 21:14
采样深度大一点。改成2k或以上试试
4k都显示不到第四个byte,8k就没反应了{:3_60:} steinwai 发表于 2015-4-11 19:22
4k都显示不到第四个byte,8k就没反应了
8k好像因为采集的点太多,没法实时显示你可以采集一会停止应该就有了。但是明显不应该是8k这么大的。你可以试试换个采样时钟。用O_psCLK做采样时钟。或者自己分个频。25M、10M、1M的试一下。 直接接在板子的extra pin上面就可以了吗,对io的类型有要求吗? 终于可以显示完5个byte了,可是按键后没看出data有变化呢
页:
[1]