#1楼主:求助 ps2 键盘 在LCD 上的显示 [fpga]
文章发表于:2008-07-11 12:02
小弟最近在搞ps2 这一块, 发现仿真通过了,但是还是不能通过实测。
很郁闷。。想请大家帮忙,是不是我哪一个部位出现了错误。
主要的目的是:键盘上敲下a、b 时 LCD上显示 而 其他则显示 !
代码如下所示:
module MYPS2(clk,ps_clk,ps_data,data);
input clk, ps_clk, ps_data; //定义的输入接口
output [7:0] data; //ps2的数据输出口
reg [7:0] data;
reg [4:0] cnt = 0;
reg check = 1; //定义的奇校验
reg [10:0] fifo = 0 ; //data 的缓存
reg stop = 0; // 停止进行读取 并传输数据的标志)(1)
reg [9:0] count_cnt = 0;
always @ ( negedge ps_clk ) //主要的循环 在ps2时钟 低电平时读取
begin
if ( count_cnt == 0)
begin
fifo[cnt] <= ps_data;
check <= check ^ ps_data;
end
if( cnt == 10 ) //十一位数据的读取
begin
cnt <= 0;
stop <= 1;
end
else
cnt <= cnt+1;
if( stop == 1 ) //读取完毕 进行 缓存胧涑龅?交换
begin
if( (!check) && (fifo[10] == 1) &&(fifo[0] == 0))
begin
data <= fifo[ 8:1 ];
stop <= 0;
check <= 0;
end
else
begin
stop <= 0;
check <= 0;
end
count_cnt <= 10'b1111111111; \\每次信号读取的延时
end
if(count_cnt != 0)
count_cnt <= count_cnt - 1;
end
endmodule
下面是主top文件 (我不做重要解释了)
module total_top(clk, ps_clk, ps_data, LCD_DB, LCD_RS, LCD_RW, LCD_E);
input clk,ps_clk,ps_data;
output [7:0] LCD_DB;
output LCD_RS;
output LCD_RW;
output LCD_E;
wire [7:0]data;
wire [7:0] LCD_DB;
wire LCD_RS;
wire LCD_RW;
wire LCD_E;
MYPS2 ps2( .clk(clk),
.ps_clk(ps_clk),
.ps_data(ps_data),
.data(data)
);
LCD_TOP LCD(.clk(clk),
.data_ps(data),
.LCD_DB(LCD_DB),
.LCD_RS(LCD_RS),
.LCD_RW(LCD_RW),
.LCD_E(LCD_E)
);
endmodule
下面是LCD 的显示模块
module LCD_TOP(clk, data_ps, LCD_DB, LCD_RS, LCD_RW, LCD_E);
input clk;
input [7:0]data_ps;
output [7:0] LCD_DB;
output LCD_RS;
output LCD_RW;
output LCD_E;
wire [7:0] LCD_DB;
wire LCD_RS;
wire LCD_RW;
wire LCD_E;
parameter S0 = 9'b000000001;
parameter S1 = 9'b000000010;
parameter S2 = 9'b000000100;
parameter S3 = 9'b000001000;
parameter S4 = 9'b000010000;
parameter S5 = 9'b000100000;
parameter S6 = 9'b001000000;
parameter S7 = 9'b010000000;
parameter S8 = 9'b100000000;
//inner reg
reg [15:0] count_16 = 16'h0000;
reg [7:0] count_ms = 8'h00;
reg count_en = 1'b0;
// ms timer
always @( posedge clk or negedge count_en )
begin
if( count_en == 1'b0 )
begin
count_16 <= 16'h0000;
count_ms <= 8'h00;
end
else
if( count_16 == 16'hC350 )
begin
count_16 <= 16'h0000;
count_ms <= count_ms + 1;
end
else
count_16 <= count_16 + 1;
end
reg [15:0] curr_state = S0;
reg [15:0] next_state;
reg [7:0] data = 0;
reg rs = 0;
reg issue = 0;
reg [7:0] cntdata;
always @(posedge clk)
begin
case(data_ps)
16'h1c: cntdata <= 8'h41;
16'h32: cntdata <= 8'h42;
default : cntdata <= 8'h21;
endcase
end
// Main FSM
(* FSM_ENCODING="ONE-HOT", SAFE_IMPLEMENTATION="NO" *)
always @( posedge clk )
begin
curr_state <= next_state;
end
// Main FSM control
always @( curr_state or count_ms )
begin
case( curr_state )
// Power On
S0: if( count_ms == 8'd40 ) next_state = S1;
else next_state = S0;
// Function Set
S1: if( count_ms == 8'd1 ) next_state = S2;
else next_state = S1;
// Function Set again
S2: if( count_ms == 8'd1 ) next_state = S3;
else next_state = S2;
// Display On/Off control
S3: if( count_ms == 8'd1 ) next_state = S4;
else next_state = S3;
// Display clear
S4: if( count_ms == 8'd2 ) next_state = S5;
else next_state = S4;
// Entry mode set
S5: if( count_ms == 8'd2 ) next_state = S6;
else next_state = S5;
// Set DDRAM Address
S6: if( count_ms == 8'd2 ) next_state = S7;
else next_state = S6;
S7: if( count_ms == 8'd2 ) next_state = S8;
else next_state = S7;
default: next_state = S8;
endcase
end
// Main FSM output
always @( posedge clk)
begin
case ( next_state )
S0 : // Wait PowerOn 40ms
begin count_en <= 1'b1; data <= 8'h00; rs <= 1'b0; issue <= 1'b0; end
S1 :
if ( curr_state == S0 ) // Prepare "Function Set" issue
begin count_en <= 1'b0; data <= 8'h38; rs <= 1'b0; issue <= 1'b0; end
else // wait 1ms
begin count_en <= 1'b1; data <= 8'h38; rs <= 1'b0; issue <= 1'b1; end
S2 :
if ( curr_state == S1 ) // Prepare "Function Set" issue
begin count_en <= 1'b0; data <= 8'h38; rs <= 1'b0; issue <= 1'b0; end
else // wait 1ms
begin count_en <= 1'b1; data <= 8'h38; rs <= 1'b0; issue <= 1'b1; end
S3 :
if ( curr_state == S2 ) // Prepare "Display On/Off control" issue
begin count_en <= 1'b0; data <= 8'h0C; rs <= 1'b0; issue <= 1'b0; end
else // wait 1ms
begin count_en <= 1'b1; data <= 8'h0C; rs <= 1'b0; issue <= 1'b1; end
S4 :
if ( curr_state == S3 ) // Prepare "Display clear" issue
begin count_en <= 1'b0; data <= 8'h01; rs <= 1'b0; issue <= 1'b0; end
else // wait 2ms
begin count_en <= 1'b1; data <= 8'h01; rs <= 1'b0; issue <= 1'b1; end
S5 :
if ( curr_state == S4 ) // Prepare "Entry mode set" issue
begin count_en <= 1'b0; data <= 8'h03; rs <= 1'b0; issue <= 1'b0; end
else // wait 2ms
begin count_en <= 1'b1; data <= 8'h03; rs <= 1'b0; issue <= 1'b1; end
S6 :
if ( curr_state == S5 ) // Prepare "Set DDRAM address" issue
begin count_en <= 1'b0; data <= 8'h84; rs <= 1'b0; issue <= 1'b0; end
else // wait 2ms
begin count_en <= 1'b1; data <= 8'h84; rs <= 1'b0; issue <= 1'b1; end
S7 :
if ( curr_state == S6 ) // Prepare "data_ps" issue
begin count_en <= 1'b0; data <= cntdata ; rs <= 1'b1; issue <= 1'b0; end
else // wait 2ms
begin count_en <= 1'b1; data <= cntdata ; rs <= 1'b1; issue <= 1'b1; end
S8 :
begin count_en <= 1'b0; data <= 8'h00; rs <= 1'b0; issue <= 1'b0; end
endcase
end
// WrLCD unit
WrLCD U_WrLCD( .clk( clk), .data(data), .rs(rs), .ce(issue),
.LCD_DB(LCD_DB), .LCD_E(LCD_E), .LCD_RS(LCD_RS), .LCD_RW(LCD_RW)) ;
endmodule
下面则为LCD的底层驱动模块
module WrLCD( clk, data, rs, ce,
LCD_DB, LCD_E, LCD_RS, LCD_RW );
// input
input clk;
input [7:0] data;
input rs;
input ce;
// output
output [7:0] LCD_DB;
output LCD_E;
output LCD_RS;
output LCD_RW;
// output reg
reg [7:0] LCD_DB = 8'h00;
reg LCD_E = 0;
reg LCD_RS = 0;
wire LCD_RW;
parameter S1 = 5'b00001;
parameter S2 = 5'b00010;
parameter S3 = 5'b00100;
parameter S4 = 5'b01000;
parameter S5 = 5'b10000;
// inner sign
reg [3:0] counter;
reg counter_run;
// (* INIT = "5'b00001" *)
reg [4:0] curr_state = 5'b00001;
reg [4:0] next_state;
// LCD_RW
assign LCD_RW = 1'b0;
// LCD_DB, LCD_RS
always @( posedge clk )
begin
if( ce == 1'b0 )
begin
LCD_DB <= 8'b0;
LCD_RS <= 1'b0;
end
else
begin
LCD_DB <= data;
LCD_RS <= rs;
end
end
// Main FSM
(* FSM_ENCODING="ONE-HOT", SAFE_IMPLEMENTATION="NO" *)
always @( posedge clk )
begin
if( ce == 1'b0 )
curr_state <= S1;
else
curr_state <= next_state;
end
// Main FSM control
always @( curr_state or counter or ce )
begin
case( curr_state )
S1: if( ce == 1'b1 ) next_state = S2;
else next_state = S1;
S2: if( counter == 4'h3 ) next_state = S3;
else next_state = S2;
S3: next_state = S4;
S4: if( counter == 4'hB ) next_state = S5;
else next_state = S4;
S5: if( ce == 1'b1 ) next_state = S5;
else next_state = S1;
default: next_state = S1;
endcase
end
// Main FSM out
always @( posedge clk or negedge ce )
begin
if( ce == 1'b0 )
begin
counter_run <= 1'b0;
LCD_E <= 1'b0;
end
else if( next_state == S2 ) // 建立时间
begin
counter_run <= 1'b1;
LCD_E <= 1'b0;
end
else if( next_state == S3 ) // CE Hight
begin
counter_run <= 1'b0;
LCD_E <= 1'b1;
end
else if( next_state == S4 ) // 保持时间
begin
counter_run <= 1'b1;
LCD_E <= 1'b1;
end
else if( next_state == S5 ) // CE Low
begin
counter_run <= 1'b0;
LCD_E <= 1'b0;
end
else
begin
counter_run <= 1'b0;
LCD_E <= 1'b0;
end
end
// Timer counter
always @( posedge clk )
begin
if( counter_run == 1'b1 )
counter <= counter + 1;
else
counter <= 4'h0;
end
endmodule
下面是我的波形图:第一张为data图 可以看到此时的data为 b 时候的键盘码

第二张为LCD的显示

黄线标记的位置为结果输出的位置 是16进制的42 为LCD上“B”的
显示。
自我感觉通过了仿真调试
经过调试后,板子上只是显示
“!” 键盘敲a、b都没 反应 ····
求助啊啊啊啊啊啊 各位大侠