分享

FPGA verilog PS2 鼠标控制LED

 南风jun 2013-06-12
//方法一://FPGA verilog PS2 鼠标控制LED

//*********************************************************************************************
/*************************  PS2接收模块(电脑接收,鼠标发送)*********************************/
/* PS2_CLK信号由PS2设备产生,即鼠标在产生时钟的同时向主机送出数据,主机在PS2_CLK信号的下降沿读取(锁存)每个位。*/

`timescale 1ns / 1ps
///////////////////////////////////
module ps2_rx
(
input wire CLOCK, RESET,
input wire PS2_DAT_in, //*ps2 DATA
input wire PS2_CLK_in, //*ps2 CLOCK
input wire rx_en,

output  reg rx_done_sig,
output wire [7:0] d_rec
);

/******************************PS2_CLK下降沿检测*****************************/
reg H2L_F1;
reg H2L_F2;
 
always @ ( posedge CLOCK or negedge RESET )
    if( !RESET )
            begin
      H2L_F1 <= 1'b1;
H2L_F2 <= 1'b1;
     end
 else
     begin
   H2L_F1 <= PS2_CLK_in;
H2L_F2 <= H2L_F1;
end
/****************************/
 assign fall_edge = H2L_F2 & !H2L_F1;
//**************************************************************************
reg [3:0]i,j;
reg [8:0]rData;

always @ ( posedge CLOCK or negedge RESET )
if( !RESET )
begin
i <= 4'd0;
j <= 4'd0;
   rData <= 8'd0;
   rx_done_sig <= 1'b0;
end
else  

 case( i )
 
0:  if (fall_edge & rx_en ) i<=i+1'b1;  //0; bit-start
1:  if(j==9) begin i<=i+1'b1;j<=0; end
   else 
    begin 
      if (fall_edge) begin  rData[j]<=PS2_DAT_in ;j<=j+1'b1; end//1-8; bit-data and 9:bit-parity
       end
 
2:  if (fall_edge) i<=i+1'b1;  //10; bit-stop

3: begin  rx_done_sig <= 1'b1; i <= i + 1'b1; end
 
4: begin rx_done_sig <= 1'b0; i <= 4'd0; end
    endcase

assign d_rec = rData[7:0];

endmodule

//*************************************************************************************************************
/********************************** 发送模块(电脑发送,鼠标接受)***********************************************/
/****************************************************************************************************
**由于PS/2设备提供串行同步时钟,因此,如果主机发送数据,则主机要先把时钟线和数据线置为
请求发送的状态。主机通过下拉时钟线大于100us来抑制通讯,并且通过下拉数据线发出请求发送数据
的信号,然后释放时钟,PS/2设备检测到需要接收的数据时,它会产生时钟信号并记录8个数据位
和一个停止位。主机在时钟线变为低时准备数据到数据线。
******************************************************************************************************/

`timescale 1ns / 1ps
/////////////////////////////////////
module ps2_tx
(
input wire CLOCK, RESET,
input wire send_en,
input wire [7:0] d_sen,

inout wire PS2_DAT, PS2_CLK,

output reg  tx_done_sig
);

//**************************
    reg H2L_F1;
reg H2L_F2;
 
always @ ( posedge CLOCK or negedge RESET )
    if( !RESET )
            begin
      H2L_F1 <= 1'b1;
H2L_F2 <= 1'b1;
     end
 else
     begin
   H2L_F1 <= PS2_CLK;
H2L_F2 <= H2L_F1;
end
/****************************/
 assign fall_edge = H2L_F2 & !H2L_F1;

//=================================================
// state declaration
parameter [2:0]  idle = 3'b000,
 rts = 3'b001,
start = 3'b010,
            send_data = 3'b011,
stop = 3'b100;
 
reg [2:0] state_reg;

reg [3:0] i;
reg [8:0] sdata;
reg [12:0]count;

reg PS2_CLK_out, PS2_DAT_out;
reg tri_c, tri_d;
// odd parity bit 奇校验位
wire odd_par;
 assign odd_par = ~(^d_sen);  // (归约异或^)如果操作数(d_sen)中有偶数个1,那么^d_sen结果为0;否则结果为1 ,再取反即为奇校验位应设置的值  
///////////////////////////////////////

always @(posedge CLOCK)
if (!RESET)
  begin
  state_reg <= idle;
  count <= 0;
  sdata <= 0;
  i <= 0;
  
  PS2_CLK_out <= 1'b1;
  PS2_DAT_out <= 1'b1;
  
  tx_done_sig <= 1'b0;
  tri_c <= 1'b0;
  tri_d <= 1'b0;

  end
else
  begin 
     tx_done_sig<= 1'b0;
tri_c <= 1'b0;
    tri_d <= 1'b0;
  PS2_CLK_out <= 1'b1;
  PS2_DAT_out <= 1'b1;
/****************************************************************************************************************/
/********************* PS2控制器必须进入主机发送请的状态。这可以通过以下动作实现:********************************/
//1·PS2_CLK线首先被拉低至少在一个时钟周期(进入禁止传输Inhibit Transmission状态)
//2·PS2_DATA线随后被拉低(提供的起始位帧传送)
//3·PS2CLK线随后被释放(仍然保持PS2DATA低)。
//4·PS/2设备定期检查数据和时钟线是否为这种状态,当检测到,鼠标开始产生PS2_CLK信号,以便主机发送数据。*/
/****************************************************************************************************************/
case (state_reg)
idle:
  begin
if (send_en)
begin
sdata <= {odd_par, d_sen};
count <= 13'd4000; //  to delay 200us
state_reg <= rts;
end
  end
rts: // request to send 请求发送
if (count==0)state_reg <= start;
else 
begin 
PS2_CLK_out <= 1'b0; 
count <= count-1'b1;tri_c <= 1'b1;  
end   
start: 
  begin 
PS2_DAT_out <= 1'b0;
tri_d <= 1'b1;
if (fall_edge)
 begin
 i <= 4'h0;
 state_reg <= send_data;
   end
  end
send_data: // 8bits data + 1bit parity
      if(i==9)  state_reg <= stop; 
        else
begin           
PS2_DAT_out<=sdata[i];
tri_d <= 1'b1;
 if(fall_edge)
           begin
           i<=i+1'b1;
           end
 else  state_reg <=state_reg;
     end
stop: 
if (fall_edge)
begin
state_reg <= idle;
tx_done_sig<= 1'b1;
 
end
endcase
end
// tri-state buffers
/* inout在具体实现上一般用三态门来实现。三态门的第三个状态就是高阻'Z'。 
当inout端口不输出时,将三态门置高阻。*/
assign PS2_CLK = (tri_c) ? PS2_CLK_out : 1'bz;
assign PS2_DAT = (tri_d) ? PS2_DAT_out : 1'bz;

endmodule
/*******************************************************************************************************/

//////////////////////////////////////////////////////////////////////////////////////////////////////
/******************************************双向通信模块********************************************/
`timescale 1ns / 1ps
////////////////////////////////////
module ps2_rxtx
(
input wire CLOCK, RESET,
input wire send_en,
input wire rxen,
inout wire PS2_DAT, PS2_CLK,//@@@@@

input wire [7:0] d_sen,

output wire rx_done_sig, tx_done_sig,
output wire [7:0] d_rec
);


// instantiate ps2 receiver
ps2_rx ps2_rx_unit(.CLOCK(CLOCK), .RESET(RESET), .rx_en(rxen),
         .PS2_DAT_in(PS2_DAT), .PS2_CLK_in(PS2_CLK),.rx_done_sig(rx_done_sig), .d_rec(d_rec));
// 实例化 ps2 transmitter
ps2_tx ps2_tx_unit(.CLOCK(CLOCK), .RESET(RESET), .send_en(send_en),
  .d_sen(d_sen), .PS2_DAT(PS2_DAT), .PS2_CLK(PS2_CLK),.tx_done_sig(tx_done_sig));

endmodule

//*************************************************************************************************************
/*在Stream模式中,一旦鼠标检测到位移或发现一个或多个鼠标键的状态改变了,就发送位移数据包。数据报
告的最大速率被认为是采样速率。参数的范围从10采样点/秒到200采样点/秒。这个参数的缺省值是100采样点
/秒,主机可以用“设置采样速率”(OxF3)命令来改变它。Stream模式是操作的缺省模式。*/

/*******************************鼠标接口电路模块************************************************/
`timescale 1ns / 1ps
////////////////////////////////
module mouse
(
input wire CLOCK, RESET,
inout wire PS2_DAT, PS2_CLK, //@@@
output wire [8:0] x_pos, y_pos,
output wire [2:0] button,
output reg done_sig,
output wire rxen,
output wire send_en_sig
);

////////////////////////////////////////////////////////////////////////////////////////////////////
parameter STRM=8'hf4; // stream command F4
/******** OxF4(Enable Data Reporting) ,鼠标用“应答”(OxFA)回应命令,然后使能数据报告并复位它的位移计数器。************/

parameter [2:0] init1 = 3'b000,
       init2 = 3'b001,
       init3 = 3'b010,
       pack1 = 3'b011,
       pack2 = 3'b100,
       pack3 = 3'b101,
          done = 3'b110;

reg [2:0] state_reg, state_next;
wire[7:0] rx_data;
reg send_en;
reg rx_en;

wire rx_done_sig, tx_done_sig;

reg [8:0]  x_reg, y_reg;

reg [2:0]  butn_reg;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//*************************************************************************************************************
/*标准的鼠标有两个计数器保持位移的跟踪:X位移计数器和Y位移计数器。
**可存放9位的2进制补码,并且每个计数器都有相关的溢出标志。
**它们的内容连同三个鼠标按钮的状态一起以三字节移动数据包的形式发送给主机。
**位移计数器表示从最后一次位移数据包被送往主机后有位移量发生。
**位移计数器是一个9位2的补码整数。它的最高位作为符号位出现在位移数据包的第一个字节里。
**********************************************************************************************************
bit   *       7            6              5           4          3        2            1           0     *
**********************************************************************************************************
Byte1 *   Y_overflow    X_overflow    Y_sign_bit   X_sign_bit    1    Butn_Middle  Butn_right  Butn_left *
**********************************************************************************************************
Byte2 *                                       X_movement                                                 *
**********************************************************************************************************
Byte3 *                                       Y_movement                                                 *
**********************************************************************************************************/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

ps2_rxtx ps2_unit(.CLOCK(CLOCK), .RESET(RESET), .send_en(send_en_sig),.rxen(rxen),
                 .d_sen(STRM), .d_rec(rx_data), .PS2_DAT(PS2_DAT), .PS2_CLK(PS2_CLK),
        .rx_done_sig(rx_done_sig),.tx_done_sig(tx_done_sig));

////////////////////////////////
always @(posedge CLOCK)
if (!RESET)
 begin
 state_reg <= init1;
 x_reg <= 0;
 y_reg <= 0;

 butn_reg <= 0;
 
 rx_en<=1'b0;
 send_en <= 1'b0;
 done_sig <= 1'b0;
 end
else
 begin

send_en <= 1'b0;
done_sig <= 1'b0;
   case (state_reg)
init1:
begin
send_en <= 1'b1;
state_reg <= init2;
end
init2: // wait for send to complete
if (tx_done_sig)
begin 
     state_reg <= init3;
         rx_en<=1'b1;  
end
init3: // wait for acknowledge packet
if (rx_done_sig)
state_reg <= pack1;

pack1: // wait for 1st data packet
if (rx_done_sig)
begin

state_reg <= pack2;
y_reg[8] <= rx_data[5];   ///坐标值的符号
x_reg[8] <= rx_data[4];   
butn_reg <= rx_data[2:0];  //中  右   左
end
pack2: // wait for 2nd data packet
if (rx_done_sig)
begin
state_reg <= pack3;
x_reg[7:0] <= rx_data;
end
pack3: // wait for 3rd data packet
if (rx_done_sig)
begin
state_reg <= done;
y_reg[7:0] <= rx_data;
end
done:
begin
done_sig <= 1'b1;
state_reg <= pack1;
end
   endcase
end

/////////////////////////////////////////
// output
assign x_pos = x_reg;
assign y_pos = y_reg;

assign button = butn_reg;
assign send_en_sig = send_en;
assign rxen = rx_en;

endmodule

//*****************************************************************************************************************
/**************************************鼠标控制LED模块******************************************/
`timescale 1ns / 1ps
///////////////////////////////////
module mouse_LED
(
input wire CLOCK, RESET,
inout wire PS2_DAT, PS2_CLK,  //@@@@
output reg [5:0] LED
);
// signal declaration

reg  [9:0] p_reg;
wire [2:0] button;
wire [8:0] x;

wire done_sig;
////////////////////////////////////////////////////////////////////////////////////////////

mouse mouse_unit(.CLOCK(CLOCK), .RESET(RESET), .PS2_DAT(PS2_DAT), .PS2_CLK(PS2_CLK),
          .x_pos(x), .y_pos(), .button(button),.done_sig(done_sig));

////////////////////////////////////////////////////////////////////////////////////////////
always @(posedge CLOCK)
if (!RESET)
p_reg <= 0;
else
begin
if(done_sig)
begin 
if(button)p_reg<= {7'b0,button};
else p_reg <= {1'b0,x} ;
end
case (p_reg[2:0])
3'b000: LED = 6'b001100;
3'b001: LED = 6'b000011;
3'b010: LED = 6'b110000;
3'b011: LED = 6'b111111;
3'b100: LED = 6'b001111;
3'b101: LED = 6'b111000;
3'b110: LED = 6'b000111;
default: LED = 6'b010101;
endcase
end
endmodule
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************************************************************************/




//方法二://FPGA verilog PS2 鼠标控制LED

//*********************************************************************************************
//PS2接收模块(鼠标发送,电脑接收)
`timescale 1ns / 1ps
///////////////////////////////////
module ps2_rx
(
input wire clk, reset,
input wire ps2d, //ps2 data
input wire ps2c, //ps2 clk
input wire rx_en,

output reg rx_done_sig,
output wire [7:0] d_rec
);

// symbolic state declaration
 reg [7:0] filter_reg;
wire [7:0] filter_next;
reg  ps2count_reg;
wire ps2count_next;

wire fall_edge;
//=================================================
// filter and falling-edge check for ps2c
//=================================================
always @(posedge clk)
if (!reset)
begin
filter_reg <= 0;
ps2count_reg <= 0;
end
else
begin
filter_reg <= filter_next;
ps2count_reg <= ps2count_next;
end

assign filter_next = {ps2c, filter_reg[7:1]};
assign ps2count_next = (filter_reg==8'b11111111) ? 1'b1 :(filter_reg==8'b00000000) ? 1'b0 :ps2count_reg;
assign fall_edge = ps2count_reg & ~ps2count_next;
/**************************************************************************************/
/*相当于一个8位的移位寄存器,将PS_CLK的输入移入其中,即对PS_CLK连续采样超过8次,采样值都为1,
**则此时PS_CLK处于稳定高电平,反之处于稳定的低电平,若由高到低变化,说明PS2时钟下降沿到来.
/**************************************************************************************/

localparam [1:0] idle = 2'b00,
             receive = 2'b01,
             done = 2'b10;
reg [1:0] state_reg, state_next;
reg [3:0]  num_reg, num_next;
reg [10:0] data_reg, data_next;
///////////////////////////////////////////
always @(posedge clk)
if (!reset)
begin
state_reg <= idle;
num_reg <= 0;
data_reg <= 0;
end
else
begin
    state_reg <= state_next;
    num_reg <= num_next;
    data_reg <= data_next;
end
// FSMD next-state logic
always @*
begin
state_next = state_reg;
num_next = num_reg;
data_next = data_reg;

rx_done_sig = 1'b0;

case (state_reg)
idle: if (fall_edge & rx_en)
      begin
      // shift in start bit
      data_next = {ps2d, data_reg[10:1]};
      num_next = 4'd9;
      state_next = receive;
      end
receive: // 8 data + 1 odd_parity + 1 stop
      if (fall_edge)
begin
data_next = {ps2d, data_reg[10:1]};
if (num_reg==0)
         state_next = done;
  else
num_next = num_reg - 1;
end
done: // 1 extra clock to complete the last shift
begin
state_next = idle;
rx_done_sig = 1'b1;
end
endcase
end
// output
assign d_rec = data_reg[8:1]; // 接收到的数据

endmodule

//*******************************************************************************
//发送模块(电脑发送,鼠标接受)
`timescale 1ns / 1ps
/////////////////////////////////////
module ps2_tx
(
input wire clk, reset,
input wire send_en,//****
input wire [7:0] d_send,
inout wire ps2d, ps2c,
output reg rxen_out, tx_done_sig
);
// symbolic state declaration
localparam [2:0] idle = 3'b000,
 rts = 3'b001,
start = 3'b010,
data = 3'b011,
stop = 3'b100;
// signal declaration
reg [2:0] state_reg, state_next;

reg [3:0] num_reg, num_next;
reg [8:0] data_reg, data_next;
reg [12:0] count_reg, count_next;

reg ps2c_out, ps2d_out;
reg tri_c, tri_d;
wire odd_par;   //奇校验
// body
//=================================================
// filter and falling-edge tick generation for ps2c
//=================================================
/*****************************************************************/
reg H2L_F1;
reg H2L_F2;
 
always @ ( posedge clk or negedge reset )
    if( !reset )
     begin
      H2L_F1 <= 1'b1;
H2L_F2 <= 1'b1;
     end
 else
     begin
   H2L_F1 <= ps2c;
H2L_F2 <= H2L_F1;
end
/****************************/
 
assign fall_edge = H2L_F2 & !H2L_F1;
//=================================================
//*************************************************
/**********1. XX_reg ---> XX_next *****************
***********2. XX_next = .......   *****************
***********3. XX_next ---> XX_reg *****************
**************************************************/
//=================================================
// FSMD state & data registers
always @(posedge clk)
if (!reset)
begin
state_reg <= idle;
count_reg <= 0;
num_reg <= 0;
data_reg <= 0;
end
else
begin
state_reg <= state_next;
count_reg <= count_next;
num_reg <= num_next;
data_reg <= data_next;
end
//  odd_parity bit   计算所发送数据的校验位
assign odd_par = ~(^d_send);  // (归约异或^)如果操作数中有偶数个1,那么结果为0;否则结果为1  

// FSMD next-state logic
always @*
begin
state_next = state_reg;

count_next = count_reg;
num_next = num_reg;
data_next = data_reg;

ps2c_out = 1'b1;
ps2d_out = 1'b1;
tri_c = 1'b0;
tri_d = 1'b0;

rxen_out = 1'b0;
tx_done_sig = 1'b0;
case (state_reg)
idle:
begin
rxen_out = 1'b1;//@@@@@@@@@@@@@@@@@@@@@@@
if (send_en)//****
begin
data_next = {odd_par, d_send};
count_next = 13'h1fff; // 2^13-1 to delay 164us
state_next = rts;   //请求发送
end
end
rts: // request to send
begin
ps2c_out = 1'b0;
tri_c = 1'b1;
count_next = count_reg - 1;
if (count_reg==0) //FPGA拉低PS2C 164us
state_next = start;
end
start: 
begin 
ps2d_out = 1'b0;
tri_d = 1'b1;
if (fall_edge)
begin
num_next = 4'h8;
state_next = data;  
end
end
data: // 8 data + 1 odd_parity
//*************************************
begin
ps2d_out = data_reg[0];
tri_d = 1'b1;
if (fall_edge)
begin
data_next = {1'b0, data_reg[8:1]};
if (num_reg == 0)
state_next = stop;
else
num_next = num_reg - 1;
end
end
//**************************************
stop: // assume floating high for ps2d
if (fall_edge)
begin
state_next = idle;
tx_done_sig = 1'b1;
end
endcase
end
// tri-state buffers
assign ps2c = (tri_c) ? ps2c_out : 1'bz;
assign ps2d = (tri_d) ? ps2d_out : 1'bz;
endmodule


//******************************************************************************************************
//双向通信模块
`timescale 1ns / 1ps
////////////////////////////////////
module ps2_rxtx
(
input wire clk, reset,
input wire send_en,//****
inout wire ps2d, ps2c,
input wire [7:0] d_send,

output wire rx_done_sig, tx_done_sig,
output wire [7:0] d_rec
);
// signal declaration
wire rxen_out;

// body
// instantiate ps2 receiver
ps2_rx ps2_rx_unit(.clk(clk), .reset(reset), .rx_en(rxen_out),
         .ps2d(ps2d), .ps2c(ps2c),.rx_done_sig(rx_done_sig), .d_rec(d_rec));
// instantiate ps2 transmitter
ps2_tx ps2_tx_unit(.clk(clk), .reset(reset), .send_en(send_en),
  .d_send(d_send), .ps2d(ps2d), .ps2c(ps2c),.rxen_out(rxen_out), .tx_done_sig(tx_done_sig));

endmodule

//*************************************************************************************************************
//**************************************鼠标接口电路模块**********************************
`timescale 1ns / 1ps
////////////////////////////////
module mouse
(
input wire clk, reset,
inout wire ps2d, ps2c,
output wire [8:0] xm, ym,
output wire [2:0] button,
output reg done_sig,
output wire send_en_out
);
// constant declaration
localparam STRM=8'hf4; // stream command F4
// symbolic state declaration
localparam [2:0]
init1 = 3'b000,
init2 = 3'b001,
init3 = 3'b010,
pack1 = 3'b011,
pack2 = 3'b100,
pack3 = 3'b101,
done = 3'b110;
// signal declaration
reg [2:0] state_reg, state_next;
wire [7:0] rx_data;
reg send_en;//**
wire rx_done_sig, tx_done_sig;
reg [8:0] x_reg, y_reg, x_next, y_next;
reg [2:0] button_reg, button_next;

// body
// instantiation
ps2_rxtx ps2_unit(.clk(clk), .reset(reset), .send_en(send_en_out),
                 .d_send(STRM), .d_rec(rx_data), .ps2d(ps2d), .ps2c(ps2c),
        .rx_done_sig(rx_done_sig),.tx_done_sig(tx_done_sig));
// body
// FSMD state and data registers
always @(posedge clk)
if (!reset)
begin
state_reg <= init1;
x_reg <= 0;
y_reg <= 0;
button_reg <= 0;
end
else
begin
state_reg <= state_next;
x_reg <= x_next;
y_reg <= y_next;
button_reg <= button_next;
end
// FSMD next-state logic
always @*
begin
state_next = state_reg;

send_en = 1'b0;     //@@@@
done_sig = 1'b0;

x_next = x_reg;
y_next = y_reg;
button_next = button_reg;

case (state_reg)
init1:
begin
send_en = 1'b1;      //@@@@@
state_next = init2;
end
init2: // wait for send to complete
if (tx_done_sig)
state_next = init3;
init3: // wait for acknowledge packet
if (rx_done_sig)
state_next = pack1;
pack1: // wait for 1st data packet
if (rx_done_sig)
begin
state_next = pack2;
y_next[8] = rx_data[5];
x_next[8] = rx_data[4];
button_next = rx_data[2:0];
end
pack2: // wait for 2nd data packet
if (rx_done_sig)
begin
state_next = pack3;
x_next[7:0] = rx_data;
end
pack3: // wait for 3rd data packet
if (rx_done_sig)
begin
state_next = done;
y_next[7:0] = rx_data;
end
done:
begin
done_sig = 1'b1;
state_next = pack1;
end
endcase
end


// output
assign xm = x_reg;
assign ym = y_reg;
assign button = button_reg;
assign send_en_out=send_en;
endmodule

//*****************************************************************************************************************
//鼠标控制led测试模块
`timescale 1ns / 1ps
///////////////////////////////////
module mouse_led
(
input wire clk, reset,
inout wire ps2d, ps2c,
output reg [5:0] led
);
// signal declaration
reg [9:0] p_reg;
wire [9:0] p_next;
wire [8:0] xm;
wire [2:0] button;
wire done_sig;
// body
// instantiation
mouse mouse_unit(.clk(clk), .reset(reset), .ps2d(ps2d), .ps2c(ps2c),
                .xm(xm), .ym(), .button(button),.done_sig(done_sig));

// counter
always @(posedge clk)
if (!reset)
p_reg <= 0;
else
p_reg <= p_next;
assign p_next = (~done_sig) ? p_reg : // no activity
(button[0]) ? 10'b0 : // left button
(button[1]) ? 10'h3ff : // right button
p_reg + {xm[8], xm}; // x movement

always @*
case (p_reg[9:7])
3'b000: led = 6'b001100;
3'b001: led = 6'b111111;
3'b010: led = 6'b100000;
3'b011: led = 6'b010000;
3'b100: led = 6'b001111;
3'b101: led = 6'b110000;
3'b110: led = 6'b000011;
default: led = 6'b000001;
endcase

endmodule


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多