FPGA学习: Verilog刷题记录(15)

FPGA学习: Verilog刷题记录(14-1)

更新一些内容:部分题目另解 2023年2月13日

网站 : HDLBits

第三章 : Circuits

第二节 :Sequential Logic
第一节:Finite State Machines(2)
  • Lemmings1

    • 题目描述:The game Lemmings involves critters with fairly simple brains. So simple that we are going to model it using a finite state machine.

      In the Lemmings’ 2D world, Lemmings can be in one of two states: walking left or walking right. It will switch directions if it hits an obstacle. In particular, if a Lemming is bumped on the left, it will walk right. If it’s bumped on the right, it will walk left. If it’s bumped on both sides at the same time, it will still switch directions.

      Implement a Moore state machine with two states, two inputs, and one output that models this behaviour.

    • 题目分析:其实官网也给出了提示如下图,这样一来状态图已经有啦,只需要按步骤编写即可

    在这里插入图片描述

    • 解答1:

      /*我的解答*/
      module top_module(
          input clk,
          input areset,    // Freshly brainwashed Lemmings walk left.
          input bump_left,
          input bump_right,
          output walk_left,
          output walk_right); 
      
          reg     c_state     ;    //current state
          reg     n_state     ;    //next state
      
          parameter LEFT  = 1'b0  ,    //LEFT
                    RIGHT = 1'b1  ;    //RIGHT
      
          always @(posedge clk or posedge areset) begin
              if (areset == 1'b1)
                  c_state <= LEFT ;
              else
                  c_state <= n_state;
          end 
      
          always @(*) begin
              case(c_state)
                 LEFT : begin       //向左走
                      if(bump_left == 1'b1)
                          n_state = RIGHT;
                      else if(bump_left == 1'b0)
                          n_state = LEFT;
                      else
                          n_state = n_state;
                  end
                 RIGHT : begin     //向右走
                      if(bump_right == 1'b1)
                          n_state = LEFT;
                      else if (bump_right == 1'b0)
                          n_state = RIGHT;
                      else
                          n_state = n_state;
                  end
              default: n_state = LEFT;
              endcase
          end
      
          always @(posedge clk or posedge areset) begin
              if(areset == 1'b1) begin
                  walk_left <= 1'b1;
                  walk_right <= 1'b0;
              end
              else begin
                  case(n_state)
                     LEFT : begin
                          walk_left <= 1'b1;
                          walk_right <= 1'b0;
                      end
                     RIGHT : begin
                          walk_left <= 1'b0;
                          walk_right <= 1'b1; 
                      end
                  default: begin
      					walk_left <= 1'b1;
                          walk_right <= 1'b0;                
                  	end
                  endcase
              end
      
          end
      
      endmodule
      /*官网解答*/
      module top_module (
      	input clk,
      	input areset,
      	input bump_left,
      	input bump_right,
      	output walk_left,
      	output walk_right
      );
      
      	// Give state names and assignments. I'm lazy, so I like to use decimal numbers.
      	// It doesn't really matter what assignment is used, as long as they're unique.
      	parameter WL=0, WR=1;
      	reg state;
      	reg next;
          
          
          // Combinational always block for state transition logic. Given the current state and inputs,
          // what should be next state be?
          // Combinational always block: Use blocking assignments.    
          always@(*) begin
      		case (state)
      			WL: next = bump_left  ? WR : WL;
      			WR: next = bump_right ? WL : WR;
      		endcase
          end
          
          
          // Combinational always block for state transition logic. Given the current state and inputs,
          // what should be next state be?
          // Combinational always block: Use blocking assignments.    
          always @(posedge clk, posedge areset) begin
      		if (areset) state <= WL;
              else state <= next;
      	end
      		
      		
      	// Combinational output logic. In this problem, an assign statement are the simplest.
      	// In more complex circuits, a combinational always block may be more suitable.		
      	assign walk_left = (state==WL);
      	assign walk_right = (state==WR);
      
      	
      endmodule
      
      • 解答2:
      module top_module(
      input clk,
      input areset,    // Freshly brainwashed Lemmings walk left.
      input bump_left,
      input bump_right,
      output walk_left,
      output walk_right); //  
      
      //parameter list
      parameter LEFT = 2'b01;
      parameter RIGHT = 2'b10;
      //reg list
      reg [1:0] c_state;
      reg [1:0] n_state;
      
      // State transition logic
      always @(*) begin
        case(c_state)
            LEFT : n_state = bump_left ? RIGHT : LEFT;
            RIGHT : n_state = bump_right ? LEFT : RIGHT;
            default : n_state = LEFT;
        endcase
      end
      
      // State flip-flops with asynchronous reset
      always @(posedge clk or posedge areset) begin
        if (areset == 1'b1)
            c_state <= LEFT;
        else
            c_state <= n_state;
      end
      
      // Output logic
      assign walk_left = (c_state == RIGHT);
      assign walk_right = (c_state == LEFT);
      
      endmodule
      
  • Lemmings2

    • 题目描述:In addition to walking left and right, Lemmings will fall (and presumably go “aaah!”) if the ground disappears underneath them.

      In addition to walking left and right and changing direction when bumped, when ground=0, the Lemming will fall and say “aaah!”. When the ground reappears (ground=1), the Lemming will resume walking in the same direction as before the fall. Being bumped while falling does not affect the walking direction, and being bumped in the same cycle as ground disappears (but not yet falling), or when the ground reappears while still falling, also does not affect the walking direction.

      Build a finite state machine that models this behaviour.

    • 题目分析:这题是在前一题基础上的扩展,添加了一个ground信号,当ground=0时表明地面塌陷,aaah此时置1,当ground=1时表明地面恢复原状,此时行进的方向应当是地面塌陷前的行进方向,即如果塌陷前是向左走的,那恢复后也应该是向左走。另外官网也给出了响应的提示,如下状态图

      Lemmings2.png

      作者将其分成了4个状态分别叙述它所代表的情况,下图是我将其补全后的状态转移图

      在这里插入图片描述

      LEFTRIGHT状态和上一题类似,关键是FALL_LFALL_R首先我们得清楚这两个状态所表示的情况,FALL_L表示说塌陷前是向左行进的,而FALL_R则表示说塌陷前是向右行进的,弄清楚这个后状态图就比较好画了,ground=0LEFTRIGHT分别跳转至相应状态即可。

      另外需要弄清楚的是,每个状态具体是做什么事情,比如说FALL_L当处在这个状态时除了aaah=1外,walk_left要将其置为0,我开始没有注意这一点,所以一直无法通过验证FALL_R也是类似。除此之外,在状态转移那一块,特别需要注意优先级的问题,ground的优先级是最高的,用if-else书写代码时尤其需要注意这点。

    • 解答1:

      /*我的解答*/
      module top_module(
          input clk,
          input areset,    // Freshly brainwashed Lemmings walk left.
          input bump_left,
          input bump_right,
          input ground,
          output reg  walk_left,
          output reg  walk_right,
          output reg  aaah 
      ); 
      
          reg   [1:0]  c_state     ;
          reg   [1:0]  n_state     ;
      
          parameter LEFT   = 2'b00  ,    
                    RIGHT  = 2'b01  ,    
                    FALL_L = 2'b10  ,    
                    FALL_R = 2'b11  ;    
      
          always @(posedge clk or posedge areset) begin
              if (areset == 1'b1)
                  c_state <= LEFT ;
              else
                  c_state <= n_state;
          end
       
          always @(*) begin
              case(c_state)
                  LEFT : begin       //向左走
                      if(ground == 1'b0)     //ground的优先级最高
                          n_state = FALL_L;
                      else if(bump_left == 1'b1)
                          n_state = RIGHT;
                      else
                          n_state = LEFT;
                  end
                  RIGHT : begin     //向右走
                      if(ground == 1'b0)    //ground的优先级最高
                          n_state = FALL_R;
                      else if(bump_right == 1'b1)
                          n_state = LEFT;
                      else
                          n_state = RIGHT;
                  end
                  FALL_R : begin
                      if(ground == 1'b1)
                          n_state = RIGHT;
                      else
                          n_state = FALL_R;
                  end
                  FALL_L : begin
                      if(ground == 1'b1)
                          n_state = LEFT;
                      else
                          n_state = FALL_L;
                  end
              default: n_state = LEFT;
              endcase
          end
      
          always @(posedge clk or posedge areset) begin
              if(areset == 1'b1) begin
                  walk_left  <= 1'b1;
                  walk_right <= 1'b0;
                  aaah       <= 1'b0;
              end
              else begin
                  case(n_state)
                      LEFT : begin
                          walk_left  <= 1'b1;
                          walk_right <= 1'b0;
                          aaah       <= 1'b0;
                      end
                      RIGHT : begin
                          walk_left  <= 1'b0;
                          walk_right <= 1'b1;
                          aaah       <= 1'b0; 
                      end
                      FALL_R : begin
                          aaah <= 1'b1;
                          walk_right <= 1'b0;
                      end
                      FALL_L : begin
                          aaah <= 1'b1;
                          walk_left <= 1'b0; 
                      end
                  default: begin
      					walk_left  <= 1'b1;
                          walk_right <= 1'b0;  
                          aaah       <= 1'b0;              
                  	end
                  endcase
              end
          end
      
      endmodule
      /*官网解答*/
    • 解答2:

    	module top_module(
     input clk,
     input areset,    // Freshly brainwashed Lemmings walk left.
     input bump_left,
     input bump_right,
     input ground,
     output walk_left,
     output walk_right,
     output aaah ); 
    
    
     //--------parameter list--------------//
     parameter LEFT   = 4'b0001;
     parameter RIGHT  = 4'b0010;
     parameter FALL_L = 4'b0100;
     parameter FALL_R = 4'b1000;
    
     //----------reg list-----------------//
     reg  [3:0] c_state;
     reg  [3:0] n_state;
    
     //State transition logic 
     always @(*) begin
         case(c_state)
             LEFT    :   
                 if (bump_left == 1'b1 && ground == 1'b1)
                     n_state  =  RIGHT;
                 else if(ground == 1'b0)
                     n_state = FALL_L;
                 else
                     n_state = LEFT;   
             RIGHT   :   
                 if (bump_right == 1'b1 && ground == 1'b1)
                     n_state = LEFT;
                 else if(ground == 1'b0)
                     n_state = FALL_R;
                 else
                     n_state = RIGHT;
             FALL_L  :   n_state  = ground ? LEFT : FALL_L;
             FALL_R  :   n_state  = ground ? RIGHT : FALL_R;
         endcase
     end 
    
     //State Flip-Flops with asynchronous reset
     always @(posedge clk or posedge areset) begin
         if (areset == 1'b1)
             c_state <= LEFT;
         else
             c_state <= n_state; 
     end
    
     //Moore Finite State Machine Output logic
     assign walk_left = (c_state == LEFT);
     assign walk_right = (c_state == RIGHT);
     assign aaah = (c_state == FALL_L | c_state == FALL_R);
     
    
     endmodule
    
    
  • Lemmings3

    • 题目描述:In addition to walking and falling, Lemmings can sometimes be told to do useful things, like dig (it starts digging when dig=1). A Lemming can dig if it is currently walking on ground (ground=1 and not falling), and will continue digging until it reaches the other side (ground=0). At that point, since there is no ground, it will fall (aaah!), then continue walking in its original direction once it hits ground again. As with falling, being bumped while digging has no effect, and being told to dig when falling or when there is no ground is ignored.

      (In other words, a walking Lemming can fall, dig, or switch directions. If more than one of these conditions are satisfied, fall has higher precedence than dig, which has higher precedence than switching directions.)

      Extend your finite state machine to model this behaviour.

    • 题目分析:如果上一题弄清楚了,这一题也是依葫芦画瓢,仅是多了一个dig信号,状态转换图如下
      在这里插入图片描述

      这里仍需要清楚,每个状态所代表的事件是什么,谁的优先级高

    • 解答:

      /*我的解答*/
      module top_module(
          input clk,
          input areset,    // Freshly brainwashed Lemmings walk left.
          input bump_left,
          input bump_right,
          input ground,
          input dig,
          output reg  walk_left,
          output reg  walk_right,
          output reg  aaah,
          output reg  digging 
      );
      
          reg   [5:0]  c_state     ;
          reg   [5:0]  n_state     ;
      
          parameter LEFT   = 6'b000001  ,    //LEFT
                    RIGHT  = 6'b000010  ,    //RIGHT
                    FALL_L = 6'b000100  ,    //FALL_L
                    FALL_R = 6'b001000  ,    //FALL_R
                    DIG_L  = 6'b010000  ,    //DIG_L
                    DIG_R  = 6'b100000  ;
      
          always @(posedge clk or posedge areset) begin
              if (areset == 1'b1)
                  c_state <= LEFT ;
              else
                  c_state <= n_state;
          end
       
          always @(*) begin
              case(c_state)
                  LEFT : begin       //向左走
                      if(ground == 1'b0)
                          n_state = FALL_L;
                      else if(dig == 1'b1)
                          n_state = DIG_L;
                      else if(bump_left == 1'b1)
                          n_state = RIGHT;
                      else
                          n_state = LEFT;
                  end
                  RIGHT : begin     //向右走
                      if(ground == 1'b0)
                          n_state = FALL_R;
                      else if(dig == 1'b1)
                          n_state = DIG_R;
                      else if(bump_right == 1'b1)
                          n_state = LEFT;
                      else
                          n_state = RIGHT;
                  end
                  FALL_R : begin
                      if(ground == 1'b1)
                          n_state = RIGHT;
                      else
                          n_state = FALL_R;
                  end
                  FALL_L : begin
                      if(ground == 1'b1)
                          n_state = LEFT;
                      else
                          n_state = FALL_L;
                  end
                  DIG_R : begin
                      if(ground == 1'b0)
                          n_state = FALL_R;
                      else
                          n_state = DIG_R;
                  end
                  DIG_L : begin
                      if(ground == 1'b0)
                          n_state = FALL_L;
                      else
                          n_state = DIG_L;
                  end
              default: n_state = LEFT;
              endcase
          end
      
          always @(posedge clk or posedge areset) begin
              if(areset == 1'b1) begin
                  walk_left  <= 1'b1;
                  walk_right <= 1'b0;
                  aaah       <= 1'b0;
                  digging    <= 1'b0;
              end
              else begin
                  case(n_state)
                      LEFT : begin
                          walk_left  <= 1'b1;
                          walk_right <= 1'b0;
                          aaah       <= 1'b0;
                          digging    <= 1'b0;
                      end
                      RIGHT : begin
                          walk_left  <= 1'b0;
                          walk_right <= 1'b1;
                          aaah       <= 1'b0; 
                          digging    <= 1'b0;
                      end
                      FALL_R : begin
                          aaah       <= 1'b1;
                          walk_right <= 1'b0;
                          digging    <= 1'b0;
                      end
                      FALL_L : begin
                          aaah      <= 1'b1;
                          walk_left <= 1'b0;
                          digging   <= 1'b0; 
                      end
                      DIG_R : begin
                          digging    <= 1'b1;
                          aaah       <= 1'b0;
                          walk_right <= 1'b0;
                      end
                      DIG_L : begin
                          digging    <= 1'b1;
                          aaah       <= 1'b0;
                          walk_left  <= 1'b0;                   
                      end
                  default: begin
      					walk_left  <= 1'b1;
                          walk_right <= 1'b0;  
                          aaah       <= 1'b0;   
                          digging    <= 1'b0;           
                  	end
                  endcase
              end
          end
      
      endmodule
      /*官网解答*/
    • 解答2

module top_module(
   input clk,
   input areset,    // Freshly brainwashed Lemmings walk left.
   input bump_left,
   input bump_right,
   input ground,
   input dig,
   output walk_left,
   output walk_right,
   output aaah,
   output digging ); 


   //-------------parameter list-----------------//
   localparam  LEFT   = 6'b000_001;
   localparam  RIGHT  = 6'b000_010;
   localparam  FALL_L = 6'b000_100;
   localparam  FALL_R = 6'b001_000;
   localparam  DIG_L  = 6'b010_000;
   localparam  DIG_R  = 6'b100_000;

   //--------------reg_list----------------------//
   reg [5:0] c_state;
   reg [5:0] n_state;

   //State transition logic
   always @(*) begin
       case(c_state)
           LEFT : 
               if (ground == 1'b0)
                   n_state = FALL_L;
               else if(dig == 1'b1)
                   n_state = DIG_L;
               else if(bump_left == 1'b1)
                   n_state = RIGHT;
               else
                   n_state = LEFT;
           RIGHT :
               if (ground == 1'b0)
                   n_state = FALL_R;
               else if(dig == 1'b1)
                   n_state = DIG_R;
               else if(bump_right == 1'b1)
                   n_state = LEFT;
               else
                   n_state = RIGHT;

           DIG_L : n_state = (~ground) ? FALL_L : DIG_L;
           DIG_R : n_state = (~ground) ? FALL_R : DIG_R;
           FALL_L : n_state = (~ground) ? FALL_L : LEFT;
           FALL_R : n_state = (~ground) ? FALL_R : RIGHT;
           default : n_state = LEFT;
       endcase
   end 

   //State Flip-Flops with asynchronous reset
   always @(posedge clk or posedge areset) begin
       if (areset == 1'b1)
           c_state <= LEFT;
       else
           c_state <= n_state; 
   end

   //Moore Finite State Machine Output logic
   assign walk_left = (c_state == LEFT);
   assign walk_right = (c_state == RIGHT);
   assign aaah = (c_state == FALL_L | c_state == FALL_R);
   assign digging = (c_state == DIG_L | c_state == DIG_R);

endmodule

  • Lemmings4

    • 题目描述:

      Although Lemmings can walk, fall, and dig, Lemmings aren’t invulnerable. If a Lemming falls for too long then hits the ground, it can splatter. In particular, if a Lemming falls for more than 20 clock cycles then hits the ground, it will splatter and cease walking, falling, or digging (all 4 outputs become 0), forever (Or until the FSM gets reset). There is no upper limit on how far a Lemming can fall before hitting the ground. Lemmings only splatter when hitting the ground; they do not splatter in mid-air.

      Extend your finite state machine to model this behaviour.

      在这里插入图片描述

    • 题目分析:Lemming系列的最后一题。当下落时间超过20个周期,并且撞击地面旅鼠死亡。状态转换图如下所示,此题的要点是计数器的位宽,因为题目也说可以无限下落,为了防止位宽过小,在下落的过程中计数器溢出,所以应该把计数器设的大一点,其他部分和前三题基本一致,所以只是在上面几题的基础上做出的修改

      在这里插入图片描述

    • 解答:

      /*我的解答*/
      module top_module(
          input clk,
          input areset,    // Freshly brainwashed Lemmings walk left.
          input bump_left,
          input bump_right,
          input ground,
          input dig,
          output reg  walk_left,
          output reg  walk_right,
          output reg  aaah,
          output reg  digging 
      );
      
          reg   [6:0]  c_state     ;
          reg   [6:0]  n_state     ;
          reg   [7:0]  cnt_clk     ;
      
      	//采用独热编码
          parameter LEFT   = 7'b0000001  ,    
                    RIGHT  = 7'b0000010  ,    
                    FALL_L = 7'b0000100  ,    
                    FALL_R = 7'b0001000  ,    
                    DIG_L  = 7'b0010000  ,    
                    DIG_R  = 7'b0100000  ,    
                    SPLAT  = 7'b1000000  ;
      
      	//状态转移
          always @(posedge clk or posedge areset) begin
              if (areset == 1'b1)
                  c_state <= LEFT ;
              else
                  c_state <= n_state;
          end
       
       	//转移条件
          always @(*) begin
              case(c_state)
                  LEFT : begin       //向左走
                      if(ground == 1'b0)
                          n_state = FALL_L;
                      else if(dig == 1'b1)
                          n_state = DIG_L;
                      else if(bump_left == 1'b1)
                          n_state = RIGHT;
                      else
                          n_state = LEFT;
                  end
                  RIGHT : begin     //向右走
                      if(ground == 1'b0)
                          n_state = FALL_R;
                      else if(dig == 1'b1)
                          n_state = DIG_R;
                      else if(bump_right == 1'b1)
                          n_state = LEFT;
                      else
                          n_state = RIGHT;
                  end
                  FALL_R : begin
                      if(ground == 1'b1) begin
                          if(cnt_clk >= 8'd21)
                              n_state = SPLAT;
                          else
                              n_state = RIGHT;
                      end
                      else
                          n_state = FALL_R;
                  end
                  FALL_L : begin
                      if(ground == 1'b1) begin
                          if(cnt_clk >= 8'd21)
                              n_state = SPLAT;
                          else
                              n_state = LEFT;
                      end
                      else
                          n_state = FALL_L;
                  end
                  DIG_R : begin
                      if(ground == 1'b0)
                          n_state = FALL_R;
                      else
                          n_state = DIG_R;
                  end
                  DIG_L : begin
                      if(ground == 1'b0)
                          n_state = FALL_L;
                      else
                          n_state = DIG_L;
                  end
                  SPLAT : begin
                      n_state = SPLAT;
                  end
              default: n_state = LEFT;
              endcase
          end
      	
      	//状态输出
          always @(posedge clk or posedge areset) begin
              if(areset == 1'b1) begin
                  walk_left  <= 1'b1;
                  walk_right <= 1'b0;
                  aaah       <= 1'b0;
                  digging    <= 1'b0;
                  cnt_clk    <= 8'd0;
              end
              else begin
                  case(n_state)
                      LEFT : begin
                          walk_left  <= 1'b1;
                          walk_right <= 1'b0;
                          aaah       <= 1'b0;
                          digging    <= 1'b0;
                          cnt_clk    <= 8'd0;
                      end
                      RIGHT : begin
                          walk_left  <= 1'b0;
                          walk_right <= 1'b1;
                          aaah       <= 1'b0; 
                          digging    <= 1'b0;
                          cnt_clk    <= 8'd0;
                      end
                      FALL_R : begin
                          aaah       <= 1'b1;
                          walk_right <= 1'b0;
                          digging    <= 1'b0;
                          cnt_clk    <= cnt_clk + 1'b1;
                      end
                      FALL_L : begin
                          aaah      <= 1'b1;
                          walk_left <= 1'b0;
                          digging   <= 1'b0; 
                          cnt_clk   <= cnt_clk + 1'b1;
                      end
                      DIG_R : begin
                          digging    <= 1'b1;
                          aaah       <= 1'b0;
                          walk_right <= 1'b0;
                          cnt_clk    <= 8'd0;
                      end
                      DIG_L : begin
                          digging    <= 1'b1;
                          aaah       <= 1'b0;
                          walk_left  <= 1'b0;    
                          cnt_clk    <= 8'd0;               
                      end
                      SPLAT : begin
                          walk_left  <= 1'b0;
                          walk_right <= 1'b0;
                          aaah       <= 1'b0;
                          digging    <= 1'b0;
                      end
                  default: begin
      					walk_left  <= 1'b1;
                          walk_right <= 1'b0;  
                          aaah       <= 1'b0;   
                          digging    <= 1'b0;    
                          cnt_clk    <= 8'd0;       
                  	end
                  endcase
              end
          end
      
      endmodule
      /*官网解答*/
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值