wenyangzeng 进程贴 数字频率计

1、购买器件,PCB板焊接
2、开发环境 QII9.0和谐:7楼
3、流水灯、跑马灯、闪烁灯
4、LED数码显示
5、字符型LCD显示
6、PS2键盘
7、按键控制LED
8、LED数码管显示DIP开关状态
9、串口通讯
10、DS1302数字时钟
11、交通灯
12、TLC549ADC
13、VGA彩条
14、音乐彩灯、警笛声、电子琴
15、DS18B20
16、可逆计数器
17、LCD数码时钟
18、I2C
19、数字频率计
关键词: wenyangzeng 进程 数字 频率计

我申请的是方式二,购买PCB板和零件加USB Blaster下载器。收到包裹后开始焊接,焊接工具是30W外热式尖头电烙铁。这次的板比上次ARM DIY的PCB板布线和做工都好很多。但是核心板的过孔都没有阻焊,确实是一憾事,焊接过程很容易造成短路。比如C6电容焊盘附近就有2个过孔挨得很近,稍不注意就会出现短路。焊接后花了不少时间来检查焊盘和过孔间的短路,居然找出了3个短路点。PCB板加工成黑色确实漂亮,但是如果要查看布线情况却很费事。
EP2C5Q208C8N暂时不焊接。先接通5V电源,测量3.3V和1.2V供电正常,最后才焊接该芯片,完成结果见图1(跑马灯已挂上)。
图1

听说QuatusII 9.0以上使用不稳定,于是就安装9.0版的QuatusII 和NiosII 。
Quartus II 9.0
Nosii 9.0
USB Blaster
连接USB Blaster试下载.SOF文件到FPGA成功,开发准备工作就绪。



刚入门学习FPGA,遇到的困难主要是如何熟练使用Quaturesii软件工具生成最后的.SOF文件。经过几天刻苦练习,才稍稍学会软件工具的使用方法,就以跑马灯作为第一个进程,与各位共享生成.SOF的方法。
进入QUARTUSII9.0,建立一个新工程ledwalk; 点击File→NEW→Verilog HDL File,在文件编辑窗口中输入代码。 点击File→Create/Updata→Create Symbol Files for Current File见图1:1、2、3、4
图1
点击File→NEW→Block Diagram/Schematic file建立Block1.bdf;
图2
双击Block1.bdf编辑窗口,见图2:1、2、3;
图3
出现图3 窗口,选择ledwalk,点击OK;
图4
双击Block1.bdf编辑窗口,再分别添加输入和输出端口:图4
图5
连接好输入和输出端口到模块I/O口,分别双击图5中箭头所示之处,为端口修改名称clk和led[7..0]。
图6
点击:Tools →Tcl Scripts
选择eepwempty_pin.tcl文件(该文件必须预先存放在本项目文件夹)。点击Run(图6),消息窗口显示图6红线提示。
图7
点击:Start→Start Analysis & Synthesis执行一次确保无Error警告出现;
点击:Start→Start I/O Assigment Analysis执行管脚分配。图7
图8
点击Assignments→Pin Planner查看所分配的管脚的名称、方向、引脚编号已激活。见图8红色方框中。
点击Start compilation三角形箭头,进行最后编译生成ledwalk.sof就可以通过JTAG下载到FPGA片内了。

ledwalk.V:
module ledwalk(led,clk);
input clk;
output [7:0] led;
reg[7:0]led_out;
reg[25:0]buffer;
always@(posedge clk)
begin
buffer<=buffer+1'b1;
if(buffer==26'd25000000)
begin
led_out=led_out<<1;
if(led_out==8'b00000000)
led_out=8'b00000001;
end
end
assign led=led_out;
endmodule
//----------------------------
ledwater.V
module ledwater(clk,led);
output [7:0] led;
input clk;
reg[8:0] led_out;
reg[8:0] led_out1;
reg[25:0]buffer;
always@(posedge clk)
begin
buffer<=buffer+1'b1;
if (buffer==26'd25000000)
begin
led_out=led_out<<1;
if(led_out==9'b000000000)
led_out=9'b111111111;
led_out1=~led_out;
end
end
assign led=led_out1[7:0];
endmodule
//-------------------------------
led1.V
module led1 (clk ,led);
input clk;
output [7:0]led;
reg [7:0]led;
reg [25:0] buffer;
always@(posedge clk)
begin
buffer<=buffer+1;
if(buffer==26'd25000000)
begin
led<=~led;
buffer<=0;
end
end
endmodule
上一幅图就好了。

进程4 LED动态、静态显示
动态显示:
module scan_led(clk,rst,sm_seg,sm_bit);
input clk,rst;
output[7:0] sm_seg;
output[7:0] sm_bit;
reg[7:0] sm_seg;
reg[7:0] sm_bit;
reg[15:0] cnt_scan;
reg[4:0] dataout_buf;
always@(posedge clk or negedge rst)
begin
if(!rst) begin
cnt_scan<=0;
end
else begin
cnt_scan<=cnt_scan+1'b1;
end
end
always @(cnt_scan)
begin
case(cnt_scan[15:13])
3'b000 :
sm_bit = 8'b1111_1110;
3'b001 :
sm_bit = 8'b0111_1111;
3'b010 :
sm_bit = 8'b1011_1111;
3'b011 :
sm_bit = 8'b1101_1111;
3'b100 :
sm_bit = 8'b1110_1111;
3'b101 :
sm_bit = 8'b1111_0111;
3'b110 :
sm_bit = 8'b1111_1011;
3'b111 :
sm_bit = 8'b1111_1101;
default :
sm_bit = 8'b1111_1110;
endcase
end
always@(sm_bit)
begin
case(sm_bit)
8'b1111_1110:
dataout_buf=8;
8'b1111_1101:
dataout_buf=7;
8'b1111_1011:
dataout_buf=6;
8'b1111_0111:
dataout_buf=5;
8'b1110_1111:
dataout_buf=4;
8'b1101_1111:
dataout_buf=3;
8'b1011_1111:
dataout_buf=2;
8'b0111_1111:
dataout_buf=1;
default:
dataout_buf=0;
endcase
end
always@(dataout_buf)
begin
case(dataout_buf)
4'h0 : sm_seg = 8'hc0; // "0"
4'h1 : sm_seg = 8'hf9; // "1"
4'h2 : sm_seg = 8'ha4; // "2"
4'h3 : sm_seg = 8'hb0; // "3"
4'h4 : sm_seg = 8'h99; // "4"
4'h5 : sm_seg = 8'h92; // "5"
4'h6 : sm_seg = 8'h82; // "6"
4'h7 : sm_seg = 8'hf8; // "7"
4'h8 : sm_seg = 8'h80; // "8"
4'h9 : sm_seg = 8'h90; // "9"
4'ha : sm_seg = 8'h88; // "a"
4'hb : sm_seg = 8'h83; // "b"
4'hc : sm_seg = 8'hc6; // "c"
4'hd : sm_seg = 8'ha1; // "d"
4'he : sm_seg = 8'h86; // "e"
4'hf : sm_seg = 8'h8e; // "f"
endcase
end
endmodule
图1 生成的顶层原理图
图2 运行结果
静态显示:
module led_display(sm_seg,sm_bit,clk,);
input clk;
output [7:0] sm_seg; //
output [7:0] sm_bit; //
reg [7:0] sm_seg;
reg [7:0] sm_bit;
reg [3:0] disp_dat;
reg [36:0] count;
always @ (posedge clk )
begin
count = count + 1'b1;
sm_bit = 8'b00000000;
end
always @ (count[24])
begin
disp_dat = {count[28:25]};
end
always @ (disp_dat)
begin
case (disp_dat)
4'h0 : sm_seg = 8'hc0; // "0"
4'h1 : sm_seg = 8'hf9; // "1"
4'h2 : sm_seg = 8'ha4; // "2"
4'h3 : sm_seg = 8'hb0; // "3"
4'h4 : sm_seg = 8'h99; // "4"
4'h5 : sm_seg = 8'h92; // "5"
4'h6 : sm_seg = 8'h82; // "6"
4'h7 : sm_seg = 8'hf8; // "7"
4'h8 : sm_seg = 8'h80; // "8"
4'h9 : sm_seg = 8'h90; // "9"
4'ha : sm_seg = 8'h88; // "a"
4'hb : sm_seg = 8'h83; // "b"
4'hc : sm_seg = 8'hc6; // "c"
4'hd : sm_seg = 8'ha1; // "d"
4'he : sm_seg = 8'h86; // "e"
4'hf : sm_seg = 8'h8e; // "f"
endcase
end
endmodule
生成顶层原理图(图1)与动态式相同
图3 运行结果
tcl_script.tcl文件
#Pin_Setup.tcl
# Setup pin setting
set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED"
set_global_assignment -name ENABLE_INIT_DONE_OUTPUT ON
set_location_assignment PIN_129 -to clk
set_location_assignment PIN_191 -to sm_seg[0]
set_location_assignment PIN_197 -to sm_seg[1]
set_location_assignment PIN_205 -to sm_seg[2]
set_location_assignment PIN_200 -to sm_seg[3]
set_location_assignment PIN_198 -to sm_seg[4]
set_location_assignment PIN_193 -to sm_seg[5]
set_location_assignment PIN_206 -to sm_seg[6]
set_location_assignment PIN_201 -to sm_seg[7]
set_location_assignment PIN_188 -to sm_bit[7]
set_location_assignment PIN_189 -to sm_bit[6]
set_location_assignment PIN_192 -to sm_bit[5]
set_location_assignment PIN_195 -to sm_bit[4]
set_location_assignment PIN_199 -to sm_bit[3]
set_location_assignment PIN_203 -to sm_bit[2]
set_location_assignment PIN_207 -to sm_bit[1]
set_location_assignment PIN_208 -to sm_bit[0]

进程5、字符型LCD
DIV16.V
module div16(clk,rst,clk_16);
input clk,rst;
output clk_16;
reg[3:0] count;
always @(posedge clk or negedge rst)
begin
if (!rst)
count <= 'b0;
else
count <= count +1;
end
assign clk_16 = count[3];
endmodule
//-----------------
.//LCD.V
//----------------
module lcd(clk,rst,lcd_e,lcd_rw,lcd_rs,data);
input clk,rst;
output lcd_e,lcd_rw,lcd_rs;
output [7:0] data;
reg lcd_e,lcd_rw,lcd_rs;
reg [7:0] data;
reg [9:0] state;
reg [5:0] address;
parameter IDLE =10'b0000000000;
parameter CLEAR =10'b0000000001;
parameter RETURNCURSOR =10'b0000000010;
parameter SETMODE =10'b0000000111;
parameter SWITCHMODE =10'b0000001111;
parameter SHIFT =10'b0000011100;
parameter SETFUNCTION =10'b0000111100;
parameter SETCGRAM =10'b0001000000;
parameter SETDDRAM1 =10'b0010000001;
parameter SETDDRAM2 =10'b0010000010;
parameter READFLAG =10'b0100000000;
parameter WRITERAM2 =10'b1000000010;
parameter READRAM =10'b1100000000;
parameter cur_inc =1;
parameter cur_dec =0;
parameter cur_shift =1;
parameter cur_noshift =0;
parameter open_display =1;
parameter open_cur =0;
parameter blank_cur =0;
parameter shift_display =1;
parameter shift_cur =0;
parameter right_shift =1;
parameter left_shift =0;
parameter datawidth8 =1;
parameter datawidth4 =0;
parameter twoline =1;
parameter oneline =0;
parameter font5x10 =1;
parameter font5x7 =0;
function [7:0] ddram; input [5:0] n;
begin
case(n)
6'b000_000:ddram=8'b0010_0000;//
6'b000_001:ddram=8'b0010_0000;//
6'b000_010:ddram=8'b0100_0101;//E
6'b000_011:ddram=8'b0100_0101;//E
6'b000_100:ddram=8'b0101_0000;//P
6'b000_101:ddram=8'b0101_0111;//w
6'b000_110:ddram=8'b0010_1110;//.
6'b000_111:ddram=8'b0110_0011;//c
6'b010_000:ddram=8'b0110_1111;//o
6'b010_001:ddram=8'b0110_1101;//m
6'b010_010:ddram=8'b0010_1110;//.
6'b010_011:ddram=8'b0110_0011;//c
6'b010_100:ddram=8'b0110_1110;//n
6'b010_101:ddram=8'b0010_0000;//
6'b010_110:ddram=8'b0010_0000;//
6'b010_111:ddram=8'b0010_0000;//
endcase
end
endfunction
reg [15:0] clkcnt;
always @ (posedge clk)
if(!rst)
clkcnt<=16'b0000_0000_0000_0000;
else
begin
if(clkcnt==16'b0110_0001_1010_1000) //16'b1001_1100_0100_0000
clkcnt<=16'b0000_0000_0000_0000;
else
clkcnt<=clkcnt+1;
end
wire tc_clkcnt;
assign tc_clkcnt=(clkcnt==16'b0110_0001_1010_1000)?1:0;//16'b1001_1100_0100_0000:40000
reg clkdiv; //T 为50000个clk
always @ (posedge tc_clkcnt)
if(!rst)
clkdiv<=0;
else
clkdiv<=~clkdiv;
reg clk_int;
always @ (posedge clkdiv) //原为clkdiv
if(!rst)
clk_int<=0;
else
clk_int<=~clk_int;
always @ (negedge clkdiv)
if(!rst)
lcd_e<=0;
else
lcd_e<=~lcd_e;
always @ (posedge clk_int or negedge rst)
if(!rst)
begin
state<=IDLE;
address<=6'b000000;
data<=8'b00000000;
lcd_rs<=0;
lcd_rw<=0;
end
else
begin
case(state)
IDLE :begin
data<=8'bzzzz_zzzz;
state<=CLEAR;
end
CLEAR :begin lcd_rs<=0;lcd_rw<=0;data<=8'b0000_0001;
state<=SETFUNCTION;end
SETFUNCTION :begin lcd_rs<=0;lcd_rw<=0;data[7:5]<=3'b001;
data[4]<=datawidth8;data[3]<=twoline;
data[2]<=font5x10;data[1:0]<=2'b00;
state<=SWITCHMODE;end
SWITCHMODE :begin lcd_rs<=0;lcd_rw<=0;data[7:3]<=5'b00001;
data[2]<=open_display;data[1]<=open_cur;
data[0]<=blank_cur;
state<=SETMODE;end
SETMODE :begin lcd_rs<=0;lcd_rw<=0;data[7:2]<=6'b000001;
data[1]<=cur_inc;data[0]<=cur_noshift;
state<=SHIFT;end
SHIFT :begin lcd_rs<=0;lcd_rw<=0;data[7:4]<=4'b0001;
data[3]<=shift_cur;data[2]<=left_shift;data[1:0]<=2'b00;
state<=SETDDRAM1;end
RETURNCURSOR :begin lcd_rs<=0;lcd_rw<=0;data<=8'b00000010; state<=WRITERAM;end
SETCGRAM :begin lcd_rs<=0;lcd_rw<=0;data<=8'b01000000; state<=SETDDRAM;end*/
SETDDRAM1 :begin lcd_rs<=0;lcd_rw<=0;data<=8'b10000000; state<=WRITERAM1;end
SETDDRAM2 :begin lcd_rs<=0;lcd_rw<=0;data<=8'b11000000;
80+40
state<=WRITERAM2;end
WRITERAM1 :begin
if(address<=6'b001_111)
begin
lcd_rs<=1;
lcd_rw<=0;
data<=ddram(address);
address<=address+1;
state<=WRITERAM1;
end
else
begin
lcd_rs<=0;
lcd_rw<=0;
state<=SETDDRAM2;
end
end
WRITERAM2 :begin
if(address<=6'b011_100)
begin
lcd_rs<=1;
lcd_rw<=0;
data<=ddram(address);
address<=address+1;
state<=WRITERAM2;
end
else
begin
lcd_rs<=0;
lcd_rw<=0;
state<=SHIFT;
address<=6'b000000;
end
end
endcase
end
endmodule
图1 原理图
图2 运行结果
我的字符型液晶使用单行字符型,字符方向也倒了180度。呵呵!

进程6 LCD显示PS2键盘键值
尊照51FPGA提供的演示程序练习了PS2键盘输入键值在LCD上进行显示。
新建工程ps2_lcd\top.qpf
//---------------------------
//PS2_KEYBOARD.V
//---------------------------
`resetall
`timescale 1ns/100ps
`define TOTAL_BITS 11
`define EXTEND_CODE 16'hE0
`define RELEASE_CODE 16'hF0
`define LEFT_SHIFT 16'h12
`define RIGHT_SHIFT 16'h59
module ps2_keyboard_interface (
clk,
reset,
ps2_clk,
ps2_data,
rx_extended,
rx_released,
rx_shift_key_on,
rx_scan_code,
rx_ascii,
rx_data_ready, // rx_read_o
rx_read, // rx_read_ack_i
tx_data,
tx_write,
tx_write_ack_o,
tx_error_no_keyboard_ack
);
parameter TIMER_60USEC_VALUE_PP = 2950; // Number of sys_clks for 60usec.
parameter TIMER_60USEC_BITS_PP = 12; // Number of bits needed for timer
parameter TIMER_5USEC_VALUE_PP = 186; // Number of sys_clks for debounce
parameter TIMER_5USEC_BITS_PP = 8; // Number of bits needed for timer
parameter TRAP_SHIFT_KEYS_PP = 0; // Default: No shift key trap.
parameter m1_rx_clk_h = 1;
parameter m1_rx_clk_l = 0;
parameter m1_rx_falling_edge_marker = 13;
parameter m1_rx_rising_edge_marker = 14;
parameter m1_tx_force_clk_l = 3;
parameter m1_tx_first_wait_clk_h = 10;
parameter m1_tx_first_wait_clk_l = 11;
parameter m1_tx_reset_timer = 12;
parameter m1_tx_wait_clk_h = 2;
parameter m1_tx_clk_h = 4;
parameter m1_tx_clk_l = 5;
parameter m1_tx_wait_keyboard_ack = 6;
parameter m1_tx_done_recovery = 7;
parameter m1_tx_error_no_keyboard_ack = 8;
parameter m1_tx_rising_edge_marker = 9;
parameter m2_rx_data_ready = 1;
parameter m2_rx_data_ready_ack = 0;
input clk;
input reset;
inout ps2_clk;
inout ps2_data;
output rx_extended;
output rx_released;
output rx_shift_key_on;
output [7:0] rx_scan_code;
output [7:0] rx_ascii;
output rx_data_ready;
input rx_read;
input [7:0] tx_data;
input tx_write;
output tx_write_ack_o;
output tx_error_no_keyboard_ack;
reg rx_extended;
reg rx_released;
reg [7:0] rx_scan_code;
reg [7:0] rx_ascii;
reg rx_data_ready;
reg tx_error_no_keyboard_ack;
wire timer_60usec_done;
wire timer_5usec_done;
wire extended;
wire released;
wire shift_key_on;
wire rx_output_event;
wire rx_output_strobe;
wire tx_parity_bit;
wire rx_shifting_done;
wire tx_shifting_done;
wire [11:0] shift_key_plus_code;
reg [`TOTAL_BITS-1:0] q;
reg [3:0] m1_state;
reg [3:0] m1_next_state;
reg m2_state;
reg m2_next_state;
reg [3:0] bit_count;
reg enable_timer_60usec;
reg enable_timer_5usec;
reg [TIMER_60USEC_BITS_PP-1:0] timer_60usec_count;
reg [TIMER_5USEC_BITS_PP-1:0] timer_5usec_count;
reg [7:0] ascii;
reg left_shift_key;
reg right_shift_key;
reg hold_extended;
reg hold_released;
reg ps2_clk_s;
reg ps2_data_s;
reg ps2_clk_hi_z;
reg ps2_data_hi_z;
assign ps2_clk = ps2_clk_hi_z?1'bZ:1'b0;
assign ps2_data = ps2_data_hi_z?1'bZ:1'b0;
always @(posedge clk)
begin
ps2_clk_s <= ps2_clk;
ps2_data_s <= ps2_data;
end
always @(posedge clk)
begin : m1_state_register
if (!reset) m1_state <= m1_rx_clk_h;
else m1_state <= m1_next_state;
end
always @(m1_state
or q
or tx_shifting_done
or tx_write
or ps2_clk_s
or ps2_data_s
or timer_60usec_done
or timer_5usec_done
)
begin : m1_state_logic
ps2_clk_hi_z <= 1;
ps2_data_hi_z <= 1;
tx_error_no_keyboard_ack <= 0;
enable_timer_60usec <= 0;
enable_timer_5usec <= 0;
case (m1_state)
m1_rx_clk_h :
begin
enable_timer_60usec <= 1;
if (tx_write) m1_next_state <= m1_tx_reset_timer;
else if (~ps2_clk_s) m1_next_state <= m1_rx_falling_edge_marker;
else m1_next_state <= m1_rx_clk_h;
end
m1_rx_falling_edge_marker :
begin
enable_timer_60usec <= 0;
m1_next_state <= m1_rx_clk_l;
end
m1_rx_rising_edge_marker :
begin
enable_timer_60usec <= 0;
m1_next_state <= m1_rx_clk_h;
end
m1_rx_clk_l :
begin
enable_timer_60usec <= 1;
if (tx_write) m1_next_state <= m1_tx_reset_timer;
else if (ps2_clk_s) m1_next_state <= m1_rx_rising_edge_marker;
else m1_next_state <= m1_rx_clk_l;
end
m1_tx_reset_timer:
begin
enable_timer_60usec <= 0;
m1_next_state <= m1_tx_force_clk_l;
end
m1_tx_force_clk_l :
begin
enable_timer_60usec <= 1;
ps2_clk_hi_z <= 0; // Force the ps2_clk line low.
if (timer_60usec_done) m1_next_state <= m1_tx_first_wait_clk_h;
else m1_next_state <= m1_tx_force_clk_l;
end
m1_tx_first_wait_clk_h :
begin
enable_timer_5usec <= 1;
ps2_data_hi_z <= 0; // Start bit.
if (~ps2_clk_s && timer_5usec_done)
m1_next_state <= m1_tx_clk_l;
else
m1_next_state <= m1_tx_first_wait_clk_h;
end
m1_tx_first_wait_clk_l :
begin
ps2_data_hi_z <= 0;
if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l;
else m1_next_state <= m1_tx_first_wait_clk_l;
end
m1_tx_wait_clk_h :
begin
enable_timer_5usec <= 1;
ps2_data_hi_z <= q[0];
if (ps2_clk_s && timer_5usec_done)
m1_next_state <= m1_tx_rising_edge_marker;
else
m1_next_state <= m1_tx_wait_clk_h;
end
m1_tx_rising_edge_marker :
begin
ps2_data_hi_z <= q[0];
m1_next_state <= m1_tx_clk_h;
end
m1_tx_clk_h :
begin
ps2_data_hi_z <= q[0];
if (tx_shifting_done) m1_next_state <= m1_tx_wait_keyboard_ack;
else if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l;
else m1_next_state <= m1_tx_clk_h;
end
m1_tx_clk_l :
begin
ps2_data_hi_z <= q[0];
if (ps2_clk_s) m1_next_state <= m1_tx_wait_clk_h;
else m1_next_state <= m1_tx_clk_l;
end
m1_tx_wait_keyboard_ack :
begin
if (~ps2_clk_s && ps2_data_s)
m1_next_state <= m1_tx_error_no_keyboard_ack;
else if (~ps2_clk_s && ~ps2_data_s)
m1_next_state <= m1_tx_done_recovery;
else m1_next_state <= m1_tx_wait_keyboard_ack;
end
m1_tx_done_recovery :
begin
if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h;
else m1_next_state <= m1_tx_done_recovery;
end
m1_tx_error_no_keyboard_ack :
begin
tx_error_no_keyboard_ack <= 1;
if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h;
else m1_next_state <= m1_tx_error_no_keyboard_ack;
end
default : m1_next_state <= m1_rx_clk_h;
endcase
end
always @(posedge clk)
begin : m2_state_register
if (!reset) m2_state <= m2_rx_data_ready_ack;
else m2_state <= m2_next_state;
end
always @(m2_state or rx_output_strobe or rx_read)
begin : m2_state_logic
case (m2_state)
m2_rx_data_ready_ack:
begin
rx_data_ready <= 1'b0;
if (rx_output_strobe) m2_next_state <= m2_rx_data_ready;
else m2_next_state <= m2_rx_data_ready_ack;
end
m2_rx_data_ready:
begin
rx_data_ready <= 1'b1;
if (rx_read) m2_next_state <= m2_rx_data_ready_ack;
else m2_next_state <= m2_rx_data_ready;
end
default : m2_next_state <= m2_rx_data_ready_ack;
endcase
end
always @(posedge clk)
begin
if ( !reset
|| rx_shifting_done
|| (m1_state == m1_tx_wait_keyboard_ack) // After tx is done.
) bit_count <= 0; // normal reset
else if (timer_60usec_done
&& (m1_state == m1_rx_clk_h)
&& (ps2_clk_s)
) bit_count <= 0; // rx watchdog timer reset
else if ( (m1_state == m1_rx_falling_edge_marker) // increment for rx
||(m1_state == m1_tx_rising_edge_marker) // increment for tx
)
bit_count <= bit_count + 1;
end
assign rx_shifting_done = (bit_count == `TOTAL_BITS);
assign tx_shifting_done = (bit_count == `TOTAL_BITS-1);
assign tx_write_ack_o = ( (tx_write && (m1_state == m1_rx_clk_h))
||(tx_write && (m1_state == m1_rx_clk_l))
);
assign tx_parity_bit = ~^tx_data;
always @(posedge clk)
begin
if (!reset) q <= 0;
else if (tx_write_ack_o) q <= {1'b1,tx_parity_bit,tx_data,1'b0};
else if ( (m1_state == m1_rx_falling_edge_marker)
||(m1_state == m1_tx_rising_edge_marker) )
q <= {ps2_data_s,q[`TOTAL_BITS-1:1]};
end
always @(posedge clk)
begin
if (~enable_timer_60usec) timer_60usec_count <= 0;
else if (~timer_60usec_done) timer_60usec_count <= timer_60usec_count + 1;
end
assign timer_60usec_done = (timer_60usec_count == (TIMER_60USEC_VALUE_PP - 1));
always @(posedge clk)
begin
if (~enable_timer_5usec) timer_5usec_count <= 0;
else if (~timer_5usec_done) timer_5usec_count <= timer_5usec_count + 1;
end
assign timer_5usec_done = (timer_5usec_count == TIMER_5USEC_VALUE_PP - 1);
assign extended = (q[8:1] == `EXTEND_CODE) && rx_shifting_done;
assign released = (q[8:1] == `RELEASE_CODE) && rx_shifting_done;
always @(posedge clk)
begin
if (!reset || rx_output_event)
begin
hold_extended <= 0;
hold_released <= 0;
end
else
begin
if (rx_shifting_done && extended) hold_extended <= 1;
if (rx_shifting_done && released) hold_released <= 1;
end
end
always @(posedge clk)
begin
if (!reset) left_shift_key <= 0;
else if ((q[8:1] == `LEFT_SHIFT) && rx_shifting_done && ~hold_released)
left_shift_key <= 1;
else if ((q[8:1] == `LEFT_SHIFT) && rx_shifting_done && hold_released)
left_shift_key <= 0;
end
always @(posedge clk)
begin
if (!reset) right_shift_key <= 0;
else if ((q[8:1] == `RIGHT_SHIFT) && rx_shifting_done && ~hold_released)
right_shift_key <= 1;
else if ((q[8:1] == `RIGHT_SHIFT) && rx_shifting_done && hold_released)
right_shift_key <= 0;
end
assign rx_shift_key_on = left_shift_key || right_shift_key;
always @(posedge clk)
begin
if (!reset)
begin
rx_extended <= 0;
rx_released <= 0;
rx_scan_code <= 0;
rx_ascii <= 0;
end
else if (rx_output_strobe)
begin
rx_extended <= hold_extended;
rx_released <= hold_released;
rx_scan_code <= q[8:1];
rx_ascii <= ascii;
end
end
assign rx_output_event = (rx_shifting_done
&& ~extended
&& ~released
);
assign rx_output_strobe = (rx_shifting_done
&& ~extended
&& ~released
&& ( (TRAP_SHIFT_KEYS_PP == 0)
|| ( (q[8:1] != `RIGHT_SHIFT)
&&(q[8:1] != `LEFT_SHIFT)
)
)
);
assign shift_key_plus_code = {3'b0,rx_shift_key_on,q[8:1]};
always @(shift_key_plus_code)
begin
casez (shift_key_plus_code)
//字符库省略
..........
endcase
end
endmodule
//------------------------
//LCD代码省略
//------------------------
图1 配置成功的管脚图
图2 从PS2键盘输入"0123456789abcdef ",运行结果
回复
有奖活动 | |
---|---|
【EEPW电子工程师创研计划】技术变现通道已开启~ | |
发原创文章 【每月瓜分千元赏金 凭实力攒钱买好礼~】 | |
【EEPW在线】E起听工程师的声音! | |
“我踩过的那些坑”主题活动——第001期 | |
高校联络员开始招募啦!有惊喜!! | |
【工程师专属福利】每天30秒,积分轻松拿!EEPW宠粉打卡计划启动! | |
送您一块开发板,2025年“我要开发板活动”又开始了! | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
【我踩过的那些坑】电感选型错误导致的处理器连接不上被打赏50分 | |
【我踩过的那些坑】工作那些年踩过的记忆深刻的坑被打赏10分 | |
【我踩过的那些坑】DRC使用位置错误导致的问题被打赏100分 | |
我踩过的那些坑之混合OTL功放与落地音箱被打赏50分 | |
汽车电子中巡航控制系统的使用被打赏10分 | |
【我踩过的那些坑】工作那些年踩过的记忆深刻的坑被打赏100分 | |
分享汽车电子中巡航控制系统知识被打赏10分 | |
分享安全气囊系统的检修注意事项被打赏10分 | |
分享电子控制安全气囊计算机知识点被打赏10分 | |
【分享开发笔记,赚取电动螺丝刀】【OZONE】使用方法总结被打赏20分 |