从按钮中保留输入以进行进一步的时钟周期(Verilog FPGA)

发布于 2025-01-21 22:20:59 字数 3061 浏览 0 评论 0原文

在我当前的FPGA Verilog项目中,我需要在FPGA板上使用按钮,并使其在按下按钮后,即使在释放按钮后,输入仍保留1直到满足特定条件。

但是,我正在努力理解这将如何在逻辑上起作用。在硬件上,由于每个时钟周期都在检查按钮的输入,我将如何使其制作,以使在按钮的初始按钮按下输入1后,Verilog使用1用于可预见的时钟周期直到满足条件?

上下文:对于Verilog FPGA VGA游戏项目,我正在尝试复制从几何仪表仪中复制跳转,其中块在初始输入1之后完成了全部跳跃(点击屏幕上)并保留1(无论是否持有屏幕还是屏幕释放),直到跳跃完成,块触摸地板。以下是我设法实现的代码。

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

窝囊感情。 2025-01-28 22:20:59

不要直接使用“按下按钮”信号来表示此状态。相反,它应由另一个reg表示。

如果在一个时钟周期中,“按下按钮”信号为1,则该状态应设置为1。

直到满足特定条件。

如果在时钟周期中,“按下按钮”信号为0,并且满足了“某些条件”,则该状态应设置为0。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文