蜂鸣器视频
视频地址:http://union.bokecc.com/flash/single/290666218ACBA694_1C1141743420B2CE_false_EEA982EE6B20F4D1_1/player.swf
PS2键盘控制程序:
顶层程序:
module keyboard(clk,rst_n,sm_cs,sm_db,ps2_clk,ps2_data,key);
//功能说明:根据PS2协议,将 PS2键盘上按键的信息提取处理,并转换为asic码,将asic码输出到LED和数码管上显示出来。。
input clk,rst_n,ps2_clk,ps2_data;
output [3:0] sm_cs;
output [6:0] sm_db;
output [7:0] key;
wire [7:0] ps2_byte;
// 实例化数码管
digitron digitron
(
.clk(clk),
.rst_n(rst_n),
.sm_cs(sm_cs),
.sm_db(sm_db),
.ps2_byte(ps2_byte)
);
// 实例化键盘
ps2 instance_name
(
.clk(clk),
.rst_n(rst_n),
.ps2_clk(ps2_clk),
.ps2_data(ps2_data),
.ps2_byte(ps2_byte)
);
assign key = ps2_byte;
endmodule
PS2协议程序:
module ps2(clk,rst_n,ps2_clk,ps2_data,ps2_byte);
input clk,rst_n,ps2_clk,ps2_data;
output [7:0] ps2_byte;
//捕捉下降沿
reg ps2_clk0,ps2_clk1,ps2_clk2;
wire neg_ps2_clk;
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
ps2_clk0 <= 1'b0;
ps2_clk1 <= 1'b0;
ps2_clk2 <= 1'b0;
end
else
begin
ps2_clk0 <= ps2_clk;
ps2_clk1 <= ps2_clk0;
ps2_clk2 <= ps2_clk1;
end
assign neg_ps2_clk = ps2_clk2 & ~ps2_clk1;
//按照时序进行取数
reg [7:0] ps2_byte_r; //ouput ps2_byte对应的寄存器变量
reg [7:0] temp_data; //数??缓冲变量
reg [3:0] num;
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
temp_data <= 8'b0;
num <= 1'b0;
end
else if(neg_ps2_clk) //当下降沿时,出发事件
begin
case(num)
4'd0: num <= num + 1; //开始状态
4'd1:
begin
num <= num + 1;
temp_data[0] <= ps2_data;
end
4'd2:
begin
num <= num + 1;
temp_data[1] <= ps2_data;
end
4'd3:
begin
num <= num + 1;
temp_data[2] <= ps2_data;
end
4'd4:
begin
num <= num + 1;
temp_data[3] <= ps2_data;
end
4'd5:
begin
num <= num + 1;
temp_data[4] <= ps2_data;
end
4'd6:
begin
num <= num + 1;
temp_data[5] <= ps2_data;
end
4'd7:
begin
num <= num + 1;
temp_data[6] <= ps2_data;
end
4'd8:
begin
num <= num + 1;
temp_data[7] <= ps2_data;
end
4'd9: num <= num + 1;
4'd10: num <= 0;
default: ;
endcase
end
//检测是否松手
reg key_f0;
always @(posedge clk or negedge rst_n)
if(!rst_n)
key_f0 <= 0;
else if(num == 4'd10) //刚传完一个字节的数据
begin
if(temp_data == 8'hf0)
key_f0 <= 1;
else
begin
if(!key_f0) //??
ps2_byte_r <= temp_data;
else //??
key_f0 <= 0;
end
end
//找出对应的ASCII码
reg [7:0] ps2_asc;
always @(ps2_byte_r)
case(ps2_byte_r)
8'h15: ps2_asc <= 8'h51; //Q
8'h1d: ps2_asc <= 8'h57; //W
8'h24: ps2_asc <= 8'h45; //E
8'h2d: ps2_asc <= 8'h52; //R
8'h2c: ps2_asc <= 8'h54; //T
8'h35: ps2_asc <= 8'h59; //Y
8'h3c: ps2_asc <= 8'h55; //U
8'h43: ps2_asc <= 8'h49; //I
8'h44: ps2_asc <= 8'h4f; //O
8'h4d: ps2_asc <= 8'h50; //P
8'h1c: ps2_asc <= 8'h41; //A
8'h1b: ps2_asc <= 8'h53; //S
8'h23: ps2_asc <= 8'h44; //D
8'h2b: ps2_asc <= 8'h46; //F
8'h34: ps2_asc <= 8'h47; //G
8'h33: ps2_asc <= 8'h48; //H
8'h3b: ps2_asc <= 8'h4a; //J
8'h42: ps2_asc <= 8'h4b; //K
8'h4b: ps2_asc <= 8'h4c; //L
8'h1a: ps2_asc <= 8'h5a; //Z
8'h22: ps2_asc <= 8'h58; //X
8'h21: ps2_asc <= 8'h43; //C
8'h2a: ps2_asc <= 8'h56; //V
8'h32: ps2_asc <= 8'h42; //B
8'h31: ps2_asc <= 8'h4e; //N
8'h3a: ps2_asc <= 8'h4d; //M
endcase
//将对应的ASCII码送出
assign ps2_byte = ps2_asc;
endmodule
数码管显示程序
module digitron(clk,rst_n,sm_cs,sm_db,ps2_byte);
input clk,rst_n;
input [7:0] ps2_byte;
output [3:0] sm_cs;
output [6:0] sm_db;
//计数,2^24=16*10^6;即16*10^6*20ns=0.32s=320ms
reg [24:0] cnt;
always @(posedge clk or negedge rst_n)
if(!rst_n) cnt<=25'b0;
else cnt<=cnt+1'b1;
reg [3:0] shi,ge;
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
shi = 4'd0;
ge = 4'd0;
end
else if(cnt==25'h1ff_ffff)
begin
shi = ps2_byte/16;
ge = ps2_byte%16;
end
parameter
seg0 = 7'hc0,
seg1 = 7'hf9,
seg2 = 7'ha4,
seg3 = 7'hb0,
seg4 = 7'h99,
seg5 = 7'h92,
seg6 = 7'h82,
seg7 = 7'hf8,
seg8 = 7'h80,
seg9 = 7'h90,
sega = 7'h88,
segb = 7'h83,
segc = 7'hc6,
segd = 7'ha1,
sege = 7'h86,
segf = 7'h8e;
//segf =7'hff;
reg [3:0] num;
reg [6:0] sm_dbr;
always @(num)
case(num)
4'h0:sm_dbr<=seg0;
4'h1:sm_dbr<=seg1;
4'h2:sm_dbr<=seg2;
4'h3:sm_dbr<=seg3;
4'h4:sm_dbr<=seg4;
4'h5:sm_dbr<=seg5;
4'h6:sm_dbr<=seg6;
4'h7:sm_dbr<=seg7;
4'h8:sm_dbr<=seg8;
4'h9:sm_dbr<=seg9;
4'hA:sm_dbr<=sega;
4'hB:sm_dbr<=segb;
4'hC:sm_dbr<=segc;
4'hD:sm_dbr<=segd;
4'hE:sm_dbr<=sege;
4'hF:sm_dbr<=segf;
default:;
endcase
reg sm_cs2_r,sm_cs1_r;
always @(clk or shi or ge)
begin
if(cnt[20])
begin
sm_cs2_r = 0;
sm_cs1_r = 1;
num = shi;
end
else
begin
sm_cs2_r = 1;
sm_cs1_r = 0;
num = ge;
end
end
assign sm_db = sm_dbr;
assign sm_cs[1:0] = 2'b11;
assign sm_cs[3] = sm_cs1_r;
assign sm_cs[2] = sm_cs2_r;
endmodule
管教配置程序:
#------------------GLOBAL--------------------#
set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED"
set_global_assignment -name ENABLE_INIT_DONE_OUTPUT OFF
set_location_assignment PIN_27 -to clk
set_location_assignment PIN_112 -to rst_n
set_location_assignment PIN_5 -to ps2_data
set_location_assignment PIN_3 -to ps2_clk
set_location_assignment PIN_195 -to sm_cs[3]
set_location_assignment PIN_192 -to sm_cs[2]
set_location_assignment PIN_189 -to sm_cs[1]
set_location_assignment PIN_188 -to sm_cs[0]
#set_location_assignment PIN_201 -to sm_db[7]
set_location_assignment PIN_206 -to sm_db[6]
set_location_assignment PIN_193 -to sm_db[5]
set_location_assignment PIN_198 -to sm_db[4]
set_location_assignment PIN_200 -to sm_db[3]
set_location_assignment PIN_205 -to sm_db[2]
set_location_assignment PIN_197 -to sm_db[1]
set_location_assignment PIN_191 -to sm_db[0]
set_location_assignment PIN_128 -to key[0]
set_location_assignment PIN_127 -to key[1]
set_location_assignment PIN_134 -to key[2]
set_location_assignment PIN_133 -to key[3]
set_location_assignment PIN_137 -to key[4]
set_location_assignment PIN_135 -to key[5]
set_location_assignment PIN_139 -to key[6]
set_location_assignment PIN_138 -to key[7]
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
vscode+cmake搭建雅特力AT32L021开发环境被打赏30分 | |
【换取逻辑分析仪】自制底板并驱动ArduinoNanoRP2040ConnectLCD扩展板被打赏47分 | |
【分享评测,赢取加热台】RISC-V GCC 内嵌汇编使用被打赏38分 | |
【换取逻辑分析仪】-基于ADI单片机MAX78000的简易MP3音乐播放器被打赏48分 | |
我想要一部加热台+树莓派PICO驱动AHT10被打赏38分 | |
【换取逻辑分析仪】-硬件SPI驱动OLED屏幕被打赏36分 | |
换逻辑分析仪+上下拉与多路选择器被打赏29分 | |
Let'sdo第3期任务合集被打赏50分 | |
换逻辑分析仪+Verilog三态门被打赏27分 | |
换逻辑分析仪+Verilog多输出门被打赏24分 |