In my current FPGA Verilog project, I am required to use a button on the FPGA board and make it such that once the button has been pressed the input remains 1 even after the button has been released until a certain condition is met.
However, I'm struggling to understand how this would work logically. On hardware since the input of the button is being checked every clock cycle how would I make it such that after the initial button press of producing an input of 1 from the button, Verilog uses 1 for the foreseeable clock cycles until a condition is met?
Context: For a Verilog FPGA VGA game project I'm trying to replicate the jump from geometry dash where the block does the full jump after an initial input 1 (tap on the screen) and remains 1 (regardless of whether the screen is held or released) until the jump is complete and the block is touching the floor. Below is a code for what I've managed to achieve.
module game_top #(parameter
FLR_POS = 11'd696,
BLK_HGT = 11'd32,
MAX_JMP = 11'd164)(
input clk,
input [4:0] btn,
output [3:0] pix_r,
output [3:0] pix_g,
output [3:0] pix_b,
output hsync,
output vsync);
wire pix_clk; //internal wires and regs
wire [3:0] draw_r; //has to be a wire because combinational logic not using a clock in drawcon
wire [3:0] draw_g; //has to be a wire because combinational logic not using a clock in drawcon
wire [3:0] draw_b; //has to be a wire because combinational logic not using a clock in drawcon
wire [10:0] curr_x; //current location on screen x pos
wire [10:0] curr_y; //current location on screen x pos
wire [10:0] obspos_x;
wire [10:0] obspos_y;
wire flag_1;
reg game_clk = 0;
reg [20:0] clk_div = 0;
reg [10:0] blkpos_x = 11'd703; //center of screen
reg [10:0] blkpos_y = 11'd424;
reg top = 0;
always@(posedge clk) begin
if(clk_div == 100000000/120) begin //clk divider
clk_div <= 20'd0;
game_clk <= !game_clk; //60hz produced
end else begin
clk_div <= clk_div 1;
end
end
always@(posedge game_clk) begin //button inputs, jump logic
if(btn[0]) begin // resets block to starting position
blkpos_x <= 11'd503;
blkpos_y <= FLR_POS - BLK_HGT;
end
// if the button is pressed block keeps raising and if released the block falls
// But if the block raises too high then it automatically starts falling to the floor ignoring button
else if(btn[1]) begin
blkpos_x <= blkpos_x;
if (blkpos_y > MAX_JMP) begin
blkpos_y <= blkpos_y - 11'd10;
end
else begin
top <= 11'd1;
end
end
else if (top == 1 || (btn[1] && top == 1)) begin
blkpos_x <= blkpos_x;
if (blkpos_y BLK_HGT <= FLR_POS) begin
blkpos_y <= blkpos_y 11'd10;
end
else begin
blkpos_y <= blkpos_y;
top <= 11'd0;
end
end
else begin
blkpos_x <= blkpos_x;
if (blkpos_y BLK_HGT >= FLR_POS) begin
blkpos_y <= blkpos_y;
end
else begin
blkpos_y <= blkpos_y 11'd10;
end
end
end
CodePudding user response:
Don't use the "button pressed" signal directly to represent this state. Instead, it should be represented by another reg
.
If in one clock cycle the "button pressed" signal is 1, the state should be set to 1.
until a certain condition is met.
If in a clock cycle the "button pressed" signal is 0 and this "certain condition" is met, the state should be set to 0.