网上关于键盘的程序很多了,可这次我打算用CPLD:XC9536。设想是3行8列的键盘,行为输出,列为读入,3X8=24个按键可编码为5 bits,那就再用5个CPLD的I/O口线将键值送给单片机。要求是如果有按键则将此键值数据锁存起来,单片机发出读按键的信号则CPLD键值数据送到那5个I/O口线上,平时单片机没发出读按键信号则CPLD的5个I/O口线上是高阻的。CPLD的时钟采用单片机的ALE脚,频率约是1.84MHz。 我的程序是: module kpad3L8(keyOUT,Yin,Xout,clk,MCU_HgAdr,WR,RD); input WR,RD,clk; //时钟源 input [1:0]MCU_HgAdr; //单片机高位地址 input [7:0] Yin; //输入,行坐标 output [2:0] Xout; //输出,列坐标 output [4:0]keyOUT; reg [4:0] keyval; //最高位作为键值有效的指示 reg [2:0] Xout; wire GET_KV; // = wire CLR_KV; reg [7:0]cutn; reg scan_en; reg [2:0]scan; reg [23:0]keyvalue; reg [4:0]Hold_key; assign GET_KV=RD|(~MCU_HgAdr[1]) | (~MCU_HgAdr[0]); assign CLR_KV=WR|(~MCU_HgAdr[1]) | (~MCU_HgAdr[0]); //CLOCK source is MCU ALE pin,11.0592MHz/6=1.8432MHz always @(posedge clk) begin cutn=cutn+1; end always @(posedge clk) begin if(~cutn[0]&&cutn[4]) scan_en=1; else scan_en=0; end always @(posedge cutn[4]) begin scan=scan+1; end always @(posedge clk) begin if(scan_en) case(scan) 0:Xout=4'b110; 1:keyvalue[7:0]=Yin; 2:Xout=4'b101; 3:keyvalue[15:8]=Yin; 4:Xout=4'b011; 5:keyvalue[23:16]=Yin; default: Xout=4'b110; endcase end always @(posedge cutn[5] or negedge CLR_KV) // begin //Key value read OK,must clear if (CLR_KV==0) keyval=5'h00; else begin if(&keyvalue) //无按键 begin //全是1 keyval=5'h00; // end else begin if(~&keyvalue[7:0]) begin case(keyvalue[7:0]) 8'b0111_1111:keyval=5'h08; 8'b1011_1111:keyval=5'h07; 8'b1101_1111:keyval=5'h06; 8'b1110_1111:keyval=5'h05; 8'b1111_0111:keyval=5'h04; 8'b1111_1011:keyval=5'h03; 8'b1111_1101:keyval=5'h02; 8'b1111_1110:keyval=5'h01; endcase end else if(~&keyvalue[15:8]) begin case(keyvalue[15:8]) 8'b0111_1111:keyval=5'h10; 8'b1011_1111:keyval=5'h0f; 8'b1101_1111:keyval=5'h0e; 8'b1110_1111:keyval=5'h0d; 8'b1111_0111:keyval=5'h0c; 8'b1111_1011:keyval=5'h0b; 8'b1111_1101:keyval=5'h0a; 8'b1111_1110:keyval=5'h09; endcase end else begin case(keyvalue[23:16]) 8'b0111_1111:keyval=5'h18; 8'b1011_1111:keyval=5'h17; 8'b1101_1111:keyval=5'h16; 8'b1110_1111:keyval=5'h15; 8'b1111_0111:keyval=5'h14; 8'b1111_1011:keyval=5'h13; 8'b1111_1101:keyval=5'h12; 8'b1111_1110:keyval=5'h11; endcase end end end end always @(posedge clk) begin if(keyval) Hold_key=keyval; end assign keyOUT=!GET_KV ? Hold_key : 5'bzzzzz; endmodule
各位看官,以上程序综合结果是不通过,改用器件XC9572也不行,只有改成95108才行,就这么个按键就要老大的一个95108,不太浪费了吗? 我想到的一个办法将时钟改成慢的1000Hz,但也要9572。其它您有什么建议么?尽量只用9536就能实现。 |