纯verilog手写,电赛队友主C,感谢佩祺,感谢小猫,感谢林老师
通过百度网盘分享的文件:plus_keypadblink.zip
链接:https://pan.baidu.com/s/18zJWWp7405V37NI4FpR0bw?pwd=1111
提取码:1111
–来自百度网盘超级会员V2的分享
`timescale 1ns / 1ps
module processor(
input sys_clk,
input reset,
input mode,
input clockwise,
input pulse,
input [2:0] col, // Input from the keypad columns
output [5:0] digit,
output reg [3:0] number,
output reg [4:0] led,
output [2:0] row // Output to the keypad rows
);
wire p;
wire mod;
wire key_pressed;
wire [3:0] key_value;
reg [2:0] target;
reg [3:0] tenthousand, thousand, hundred, ten, one;
// Submodule instantiations
choose insta(.clk(sys_clk), .target(target), .reset(reset), .digit(digit), .mod_clk(mod), .modify(mod));
pulse_detector instb(.clk(sys_clk), .rst(reset), .signal_in(pulse), .pulse_out(p));
divide instc(.clk(sys_clk), .rst(reset), .mod_clk(mod));
keypad_scan instd(.clk(sys_clk), .reset(reset), .row(row), .col(col), .key_value(key_value), .key_pressed(key_pressed));
always @(posedge sys_clk or negedge reset) begin
if (~reset) begin
tenthousand <= 4'b0000;
thousand <= 4'b0000;
hundred <= 4'b0000;
ten <= 4'b0000;
one <= 4'b0000;
target <= 3'b000;
end else begin
case ({mode, clockwise})
2'b00: begin // Cursor right move
if (p & target == 3'b000)
target <= 3'b100;
else if (p)
target <= target - 3'b001;
end
2'b01: begin // Cursor left move
if (p & target == 3'b100)
target <= 3'b000;
else if (p)
target <= target + 3'b001;
end
2'b10: begin // Add number at target position
if (key_pressed) begin
case (target)
3'b000: one <= (key_value <= 4'd9) ? key_value : one;
3'b001: ten <= (key_value <= 4'd9) ? key_value : ten;
3'b010: hundred <= (key_value <= 4'd9) ? key_value : hundred;
3'b011: thousand <= (key_value <= 4'd9) ? key_value : thousand;
3'b100: tenthousand <= (key_value <= 4'd1) ? key_value : tenthousand;
endcase
end else if (p) begin
case (target)
3'b000: if (one < 4'd9) begin
one <= one + 4'd1;end
else if (tenthousand == 4'd1 && thousand == 4'd9 && hundred == 4'd9 && ten == 4'd9) begin
one <= 4'd9; // 个位数锁定为9
end else begin
one <= 4'd0;
if (ten < 4'd9) begin
ten <= ten + 4'd1;
end else begin
ten <= 4'd0;
if (hundred < 4'd9) begin
hundred <= hundred + 4'd1;
end else begin
hundred <= 4'd0;
if (thousand < 4'd9) begin
thousand <= thousand + 4'd1;
end else begin
thousand <= 4'd0;
if (tenthousand < 4'd1) begin
tenthousand <= tenthousand + 4'd1;
end
end
end
end
end
3'b001: if (ten < 4'd9) begin
ten <= ten + 4'd1;
end
else if (tenthousand == 4'd1 && thousand == 4'd9 && hundred == 4'd9) begin
ten <= 4'd9; // 十位数锁定为9
end else begin
ten <= 4'd0;
if (hundred < 4'd9) begin
hundred <= hundred + 4'd1;
end else begin
hundred <= 4'd0;
if (thousand < 4'd9) begin
thousand <= thousand + 4'd1;
end else begin
thousand <= 4'd0;
if (tenthousand < 4'd1) begin
tenthousand <= tenthousand + 4'd1;
end
end
end
end
3'b010: if (hundred < 4'd9) begin
hundred <= hundred + 4'd1;
end
else if (tenthousand == 4'd1 && thousand == 4'd9) begin
hundred <= 4'd9; // 百位数锁定为9
end else begin
hundred <= 4'd0;
if (thousand < 4'd9) begin
thousand <= thousand + 4'd1;
end else begin
thousand <= 4'd0;
if (tenthousand < 4'd1) begin
tenthousand <= tenthousand + 4'd1;
end
end
end
3'b011: begin // 针对千位数的操作
// 如果千位是 9 且万位是 1,保持千位不变
if (thousand == 4'd9 && tenthousand == 4'd1)
thousand <= 4'd9; // 千位保持为 9,不进行进位
else if (thousand < 4'd9)
thousand <= thousand + 4'd1;
end
3'b100: if (tenthousand < 4'd1) tenthousand <= tenthousand + 4'd1;
endcase
end
end
2'b11: begin // Subtract number at target position
if (p || key_pressed) begin
case (target)
3'b000: if (one > 4'd0) begin
one <= one - 4'd1;
end else if (ten > 4'd0) begin
one <= 4'd9;
ten <= ten - 4'd1;
end else if (hundred > 4'd0) begin
one <= 4'd9;
ten <= 4'd9;
hundred <= hundred - 4'd1;
end else if (thousand > 4'd0) begin
one <= 4'd9;
ten <= 4'd9;
hundred <= 4'd9;
thousand <= thousand - 4'd1;
end else if (tenthousand > 4'd0) begin
one <= 4'd9;
ten <= 4'd9;
hundred <= 4'd9;
thousand <= 4'd9;
tenthousand <= tenthousand - 4'd1;
end
3'b001: if (ten > 4'd0) begin
ten <= ten - 4'd1;
end else if (hundred > 4'd0) begin
ten <= 4'd9;
hundred <= hundred - 4'd1;
end else if (thousand > 4'd0) begin
ten <= 4'd9;
hundred <= 4'd9;
thousand <= thousand - 4'd1;
end else if (tenthousand > 4'd0) begin
ten <= 4'd9;
hundred <= 4'd9;
thousand <= 4'd9;
tenthousand <= tenthousand - 4'd1;
end
3'b010: if (hundred > 4'd0) begin
hundred <= hundred - 4'd1;
end else if (thousand > 4'd0) begin
hundred <= 4'd9;
thousand <= thousand - 4'd1;
end else if (tenthousand > 4'd0) begin
hundred <= 4'd9;
thousand <= 4'd9;
tenthousand <= tenthousand - 4'd1;
end
3'b011: if (thousand > 4'd0) begin
thousand <= thousand - 4'd1;
end else if (tenthousand > 4'd0) begin
thousand <= 4'd9;
tenthousand <= tenthousand - 4'd1;
end
3'b100: if (tenthousand > 4'd0) tenthousand <= tenthousand - 4'd1;
endcase
end
end
endcase
end
end
// Current target LED indicator
always @(*) begin
led = 5'b00001 << target;
end
// Display the number at the current digit position
always @(*) begin
case (digit)
6'b111110: number = one;
6'b111101: number = ten;
6'b111011: number = hundred;
6'b110111: number = thousand;
6'b101111: number = tenthousand;
default: number = 4'd0;
endcase
end
endmodule
// Keypad Scan Module
module keypad_scan(
input clk,
input reset,
output reg [2:0] row, // Row output
input [2:0] col, // Column input
output reg [3:0] key_value, // Encoded key value, 1-9
output reg key_pressed // Key pressed signal
);
reg [1:0] current_row;
always @(posedge clk or negedge reset) begin
if (~reset) begin
current_row <= 2'b00;
key_value <= 4'b0000;
key_pressed <= 1'b0;
end else begin
// Sequential row scanning
current_row <= current_row + 2'b01;
if (current_row == 2'b11)
current_row <= 2'b00; // Return to first row
// Set the current row output
row <= ~(1 << current_row); // Set current row to low, others to high
// Detect key press
if (col != 3'b111) begin
key_pressed <= 1'b1;
case ({current_row, col})
5'b01_110: key_value <= 4'd1; // First row, first column
5'b01_101: key_value <= 4'd2; // First row, second column
5'b01_011: key_value <= 4'd3; // First row, third column
5'b10_110: key_value <= 4'd4; // Second row, first column
5'b10_101: key_value <= 4'd5; // Second row, second column
5'b10_011: key_value <= 4'd6; // Second row, third column
5'b11_110: key_value <= 4'd7; // Third row, first column
5'b11_101: key_value <= 4'd8; // Third row, second column
5'b11_011: key_value <= 4'd9; // Third row, third column
default: key_value <= 4'd0; // Default value
endcase
end else begin
key_pressed <= 1'b0;
end
end
end
endmodule
// Choose module with blinking logic
module choose(
input clk,
input modify,
input mod_clk, // 新增的mod_clk用于闪烁
input reset,
input [2:0] target,
output reg [5:0] digit
);
reg [2:0] cnt;
initial begin
cnt <= 3'b0;
end
always@(posedge clk or negedge reset) begin
if(~reset)
cnt <= 3'b000;
else if(cnt == 3'b100)
cnt <= 3'b000;
else
cnt <= cnt + 3'b1;
end
always@(*) begin
case(cnt)
3'b000: begin
if(target == 3'b000)
digit = {5'b11111, modify & mod_clk}; // 闪烁逻辑
else
digit = 6'b111110;
end
3'b001: begin
if(target == 3'b001)
digit = {4'b1111, modify & mod_clk, 1'b1}; // 闪烁逻辑
else
digit = 6'b111101;
end
3'b010: begin
if(target == 3'b010)
digit = {3'b111, modify & mod_clk, 2'b11}; // 闪烁逻辑
else
digit = 6'b111011;
end
3'b011: begin
if(target == 3'b011)
digit = {2'b11, modify & mod_clk, 3'b111}; // 闪烁逻辑
else
digit = 6'b110111;
end
3'b100: begin
if(target == 3'b100)
digit = {1'b1, modify & mod_clk, 4'b1111}; // 闪烁逻辑
else
digit = 6'b101111;
end
endcase
end
endmodule
// Pulse Detector Module
module pulse_detector (
input wire clk,
input wire rst,
input wire signal_in,
output reg pulse_out
);
reg prev_signal;
always @(posedge clk or negedge rst) begin
if (~rst)
prev_signal <= 1'b0;
else
prev_signal <= signal_in;
end
always @(posedge clk or negedge rst) begin
if (~rst)
pulse_out <= 1'b0;
else
pulse_out <= (~prev_signal) & signal_in; // 只在上升沿输出脉冲
end
endmodule
// Divide module for clock division
module divide(
input wire clk,
input wire rst,
output mod_clk
);
reg [11:0] cnt;
initial begin
cnt = 12'b0;
end
always@(posedge clk or negedge rst) begin
if(~rst)
cnt <= 12'b0;
else if(cnt == 12'd1000)
cnt <= 12'b0;
else
cnt <= cnt + 12'b1;
end
assign mod_clk = (cnt >= 12'd500);
endmodule