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.
