Verilog 从模块参数选择posedge/negedge灵敏度的最短版本?

Verilog 从模块参数选择posedge/negedge灵敏度的最短版本?,verilog,Verilog,我想建立一个Verilog模块,这样用户就可以通过模块参数选择一些输入时钟信号的灵敏度。作为一个例子,我编写了以下计数器,它可以在参数clockEdge选择的posedge或negedge上进行计数 module Counter (clk, reset, value); parameter clockEdge = 1; // react to rising edge by default input clk; input reset; output reg [7:0] value; gene

我想建立一个Verilog模块,这样用户就可以通过模块参数选择一些输入时钟信号的灵敏度。作为一个例子,我编写了以下计数器,它可以在参数
clockEdge
选择的posedge或negedge上进行计数

module Counter (clk, reset, value);
parameter clockEdge = 1; // react to rising edge by default

input clk;
input reset;
output reg [7:0] value;

generate
    if(clockEdge == 1) begin
        always @(posedge clk or posedge reset) begin
            if (reset) begin
                value <= 0;
            end else begin
                value <= value + 1;
            end
        end
    end else begin
        always @(negedge clk or posedge reset) begin
            if (reset) begin
                value <= 0;
            end else begin
                value <= value + 1;
            end
        end
    end
endgenerate

endmodule
模块计数器(时钟、复位、值);
参数clockEdge=1;//默认情况下对上升沿作出反应
输入时钟;
输入复位;
输出reg[7:0]值;
生成
如果(时钟边缘==1)开始
始终@(posedge clk或posedge重置)开始
如果(重置)开始

value实现clk的posedge或NEGDEDGE之后的自定义时钟reg可能是一种方法。这似乎在我的机器上运行良好:)

reg myclk;
始终@(clk)开始
如果(时钟)开始
myclk=时钟边缘?1 : 0; #1 myclk=0;
结束,否则开始
myclk=时钟边缘?0 : 1; #1 myclk=0;
结束
结束
始终@(posedge myclk或posedge重置)开始
如果(重置)

cnt最简单的方法是使用exor门反转时钟。然后在“始终”部分中使用该时钟:

wire user_clock;
assign user_clock = clk ^ falling_edge;

always @(posedge user_clock) // or posedge/negedge reset/_n etc.
   test_signal <= ~ test_signal;
有线用户时钟;
分配用户时钟=时钟下降沿;
始终@(posedge用户时钟)//或posedge/NEGFEDGE重置/\n等。

test_signal我认为这个小例子中的cut-n-paste是可以的,尽管verilog有一些工具使它更容易处理更复杂的情况,即函数和宏。你也可以使用它们,即

 function newValue(input reset, input reg[7:0] oldValue);
    if (reset) begin
       newValue = 0;
    end else begin
       newValue = value + 1;
    end
 endfunction

 generate
    if(clockEdge == 1) begin
       always @(posedge clk or posedge reset) begin
          value <= newValue(reset, value);
       end
    end else begin
       always @(negedge clk or posedge reset) begin
          value <= newValue(reset, value);
       end
    end
 endgenerate
功能新值(输入复位,输入reg[7:0]旧值);
如果(重置)开始
newValue=0;
结束,否则开始
newValue=value+1;
结束
端功能
生成
如果(时钟边缘==1)开始
始终@(posedge clk或posedge重置)开始

值正如我的问题所说,时钟选择由模块参数控制。所以我要求一个解决方案,它在编译时控制这种行为,而不是作为电路的一部分。因此,一个额外的门是不可接受的,尽管它可能会被合成优化掉。你所要做的就是把
下降沿
作为一个参数。大门将被优化掉。如果在设计中使用posedge和NEGDEDGE,您永远不知道是否添加了门延迟。e、 g.您的库可能只有posedge FFs,在这种情况下,您将在时钟线或正负时钟树中使用反相器。在所有情况下,合成工具都会意识到这一点,并调整您的计时。如果你的设计不能复制一个反相器的时钟偏差,你就有一个大问题。你的答案意味着使用门控时钟。这意味着额外的传播延迟被添加到时钟路径,这在时序方面是有问题的。
 function newValue(input reset, input reg[7:0] oldValue);
    if (reset) begin
       newValue = 0;
    end else begin
       newValue = value + 1;
    end
 endfunction

 generate
    if(clockEdge == 1) begin
       always @(posedge clk or posedge reset) begin
          value <= newValue(reset, value);
       end
    end else begin
       always @(negedge clk or posedge reset) begin
          value <= newValue(reset, value);
       end
    end
 endgenerate
`define NEW_VALUE(clk_edge) \
   always @(clk_edge clk or posedge reset) begin\
      if (reset) begin\
         value <= 0;\
      end else begin\
          value <= value + 1;\
       end\
   end

     generate
        if(clockEdge == 1) begin
           `NEW_VALUE(posedge)
        end else begin
           `NEW_VALUE(negedge)
        end
     endgenerate