如何使用 case 语句在 verilog 中编写更短的代码

How can write code in verilog shorter using case sentence

我是 Verilog 的新手,但在基础知识方面仍有一些问题。下面的代码是模块之一,可以按我想要的方式工作,但我想知道是否可以将它编写得更高效、更短,以及如何完成。 感谢您的帮助!

`timescale 1ns / 1ps


module COUNTER
  (
    input A_i,
    input B_i,
    input ENABLE_i,
    input CLK,
    input RESET,
    input R_i,
    input UP_DOWN_i, // za realno stanje se UP_DOWN_o prepisuje v UP_DOWN_i
    output reg signed [7:0] VALUE_o,
    output reg UP_DOWN_o  
  );



  reg A;
  reg B;
  reg signed [7:0] VALUE_cmp;
  wire [1:0] A_B={A,B};

  initial VALUE_o = 8'b00000000;
  initial VALUE_cmp = 8'b00000000;
  initial A = 1'b0;
  initial B = 1'b0;
  initial UP_DOWN_o = 1'b1;


  always@ (posedge CLK or posedge RESET)
  begin
    A <= A_i;
    B <= B_i;
    VALUE_cmp <= VALUE_o; 

    if (RESET || R_i)
    begin
      VALUE_o<= 8'b0;
      VALUE_cmp <=8'b0;  
    end

    else if (ENABLE_i)
    begin

//up or down
      if (UP_DOWN_i)
      begin 
//up
        if ((A == 1'b0) && (A_i == 1'b0) && (B == 1'b0) && (B_i == 1'b1))
          VALUE_o <= VALUE_o+1;  
        else if ((A == 1'b0) && (A_i == 1'b1) && (B == 1'b1) && (B_i == 1'b1))
          VALUE_o <= VALUE_o+1;  
        else if ((A == 1'b1) && (A_i == 1'b1) && (B == 1'b1) && (B_i == 1'b0))
          VALUE_o <= VALUE_o+1;  
        else if ((A == 1'b1) && (A_i == 1'b0) && (B == 1'b0) && (B_i == 1'b0))
          VALUE_o <= VALUE_o+1;
// change
        if ((A == 1'b0) && (A_i == 1'b1) && (B == 1'b0) && (B_i == 1'b0))
            VALUE_o <= VALUE_o+1;
        else if ((A == 1'b1) && (A_i == 1'b1) && (B == 1'b0) && (B_i == 1'b1))
            VALUE_o <= VALUE_o+1;  
        else if ((A == 1'b1) && (A_i == 1'b0) && (B == 1'b1) && (B_i == 1'b1))
            VALUE_o <= VALUE_o+1;
        else if ((A == 1'b0) && (A_i == 1'b0) && (B == 1'b1) && (B_i == 1'b0))
            VALUE_o <= VALUE_o+1;
// after  
        else if (A == A_i ==B == B_i )
            VALUE_o <= VALUE_o+1;              
      end

      else
      begin
 //down  
        if ((A == 1'b0) && (A_i == 1'b1) && (B == 1'b0) && (B_i == 1'b0))
            VALUE_o <= VALUE_o-1;
        else if ((A == 1'b1) && (A_i == 1'b1) && (B == 1'b0) && (B_i == 1'b1))
            VALUE_o <= VALUE_o-1;  
        else if ((A == 1'b1) && (A_i == 1'b0) && (B == 1'b1) && (B_i == 1'b1))
            VALUE_o <= VALUE_o-1;
        else if ((A == 1'b0) && (A_i == 1'b0) && (B == 1'b1) && (B_i == 1'b0))
            VALUE_o <= VALUE_o-1;         
//change     
        else if ((A == 1'b1) && (A_i == 1'b1) && (B == 1'b1) && (B_i == 1'b0))
                VALUE_o <= VALUE_o-1;
        else if ((A == 1'b0) && (A_i == 1'b1) && (B == 1'b1) && (B_i == 1'b1))
                VALUE_o <= VALUE_o-1;
        else if ((A == 1'b0) && (A_i == 1'b0) && (B == 1'b0) && (B_i == 1'b1))
                        VALUE_o <= VALUE_o-1;
        else if ((A == 1'b1) && (A_i == 1'b0) && (B == 1'b0) && (B_i == 1'b0))
                                VALUE_o <= VALUE_o-1;
// after  
        else if (A == A_i ==B == B_i )
            VALUE_o <= VALUE_o-1;     
       end
      end
  end

  always@ (posedge CLK) // kasneje potrebo vezat za UP_DOWN_o
  begin      
       //steje dol
      if (VALUE_cmp > VALUE_o)
        UP_DOWN_o <= 0;

      //steje gor
      else if (VALUE_cmp < VALUE_o)
          UP_DOWN_o <= 1;        
  end        
endmodule

可以通过将 if-else 链替换为您建议的 case 来缩短它。这是密集的实现。同样在这类问题中,您可以使用查找表(LUT)。

  always@ (posedge CLK or posedge RESET)
  begin
    A <= A_i;
    B <= B_i;
    VALUE_cmp <= VALUE_o; 

    if (RESET || R_i)
    begin
      VALUE_o<= 8'b0;
      VALUE_cmp <=8'b0;  
    end

    else if (ENABLE_i)
    begin

//up or down
      if (UP_DOWN_i)
      begin 

        case({A,A_i,B,B_i})
            //up
            4'b0001, 4'b0111,
            4'b1110, 4'b1000,
            // change
            4'b0100, 4'b1101,
            4'b1011, 4'b0010:
                VALUE_o <= VALUE_o+1;
        endcase
        if (A == A_i ==B == B_i )
            VALUE_o <= VALUE_o+1; 
        end

      else
      begin

        case({A,A_i,B,B_i})
        //down 
        4'b0100, 4'b1101,
        4'b1011, 4'b0010,
        //change  
        4'b1110, 4'b0111,
        4'b0001, 4'b1000:
            VALUE_o <= VALUE_o-1;
        endcase
// after  
        else if (A == A_i ==B == B_i )
            VALUE_o <= VALUE_o-1;     
       end
      end
  end

以下是 LUT 实现的参考: https://www.csee.umbc.edu/~tinoosh/cmpe415/slides/Rom-LUT-verilog.pdf