检查变量是否是枚举集合的一部分的最佳方法是?

时间:2015-05-26 21:17:21

标签: system-verilog

我目前正在尝试移植一些Specman代码,该代码根据变量是否是枚举的一部分来执行某些操作。在Specman中,代码看起来像这样:

define COMP_STATES do_add, do_sub;
define WAIT_STATES wait_X, wait_Y;
defube RUN_STATES  run_X, run_Y;

type my_states : [
    do_add = 3'b000;
    do_sub = 3'b001;
    wait_X = 3'b010;
    wait_Y = 3'b011;
    run_X  = 3'b100;
    run_Y  = 3'b101;
] (bits:3);

然后再说:

if(state in [COMP_STATES, RUN_STATES]){
    /* DO STUFF */
} else if(state in [WAIT_STATES]){
    /* DO STUFF */
}

我现在想在SystemVerilog中做到这一点但是遇到了一些障碍。我目前最好的方法是使用数组:

my_state which_state[$] = {`COMP_STATES, `RUN_STATES};
int indexes[$]  = which_state.get_index( index ) where ( index == state );
int num_indexes = indexes.size(); //If state doesn't exist in my_state then the returned array of indexes will be empty.
if(num_indexes > 0) begin /* DO STUFF */ end

但必须有一种更优雅和简洁的方式?我想到了find_first_index,但是如果找不到匹配项,我就无法找到它会返回的内容。

1 个答案:

答案 0 :(得分:1)

有几种方法可以做到这一点。如果您可以依赖编码,那么您可以使用通配符定义集合并使用通配符相等运算符或内部运算符

let COMP_STATES = 3'b00?; // or parameter COMP_STATES = 3'b00?;
let RUN_STATES = 3'b01?; // or parameter RUN_STATES = 3'b01?;
let WAIT_STATES = 3'b10?; // or parameter WAIT_STATES = 3'b10?;

if (my_states inside {COMP_STATES,RUN_STATES})
   ...
else if (my_state ==? WAIT_STATES)
   ...

或者你可以创建一个表达式

module top;
   enum bit [2:0] {
           do_add = 3'b000,
           do_sub = 3'b001,
           wait_X = 3'b010,
           wait_Y = 3'b011,
           run_X  = 3'b100,
           run_Y  = 3'b101
          } my_states;
   let COMP_STATES = my_states inside {do_add, do_sub};
   let WAIT_STATES = my_states inside {wait_X, wait_Y};
   let RUN_STATES =  my_states inside {run_X, run_Y};

   initial repeat(20) begin
      std::randomize(my_states);
      $write (my_states.name());
      case(1)
    COMP_STATES, RUN_STATES:
      $display("=comp,run");
    WAIT_STATES:
      $display("-wait");
      endcase
   end
endmodule

最后,如果您是从头开始,我建议您查看标记的联盟及其相应的模式匹配条件语句