不能在Verilog中使用if语句的输入

时间:2013-06-03 03:31:00

标签: verilog

我正在尝试将整数值传递给模块,但IF语句不适用于该参数。它会引发以下错误。我是 Verilog 的新手,所以我不知道如何使这项工作。

Error (10200): Verilog HDL Conditional Statement error at clock_divider.v(17): 
cannot match operand(s) in the condition to the corresponding edges in the enclosing
event control of the always construct

clock_divider.v模块

module clock_divider (clockHandler, clk, rst_n, clk_o);

parameter DIV_CONST = 10000000 ;  // 1 second
parameter DIV_CONST_faster = 10000000 / 5;
input clockHandler;
input clk;
input rst_n;

output reg clk_o;

reg [31:0] div;
reg en;
integer div_helper = 0;

always @ (posedge clk or negedge rst_n)
begin
    if(clockHandler == 0)
    begin div_helper = DIV_CONST;
    end

    else
    begin div_helper = DIV_CONST_faster;
    end

    if (!rst_n)
    begin div <= 0;
          en <= 0;
    end

    else
    begin
        if (div == div_helper)
        begin div <= 0;
              en <= 1;
        end

        else
        begin div <= div + 1;
              en <= 0;
        end
    end
end

always @ (posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
    clk_o <= 1'b0;
end
else if (en)
    clk_o <= ~clk_o;
end

endmodule

main.v模块

reg clockHandler = 1;

// 7-seg display mux
always @ (*)
begin
    case (SW[2:0])
        3'b000: hexdata <= 16'h0188;
        3'b001: hexdata <= register_A ;
        3'b010: hexdata <= program_counter ;
        3'b011: hexdata <= instruction_register ;
        3'b100: hexdata <= memory_data_register_out ;
        3'b111: hexdata <= out;   
        default: hexdata <= 16'h0188;
    endcase

    if(SW[8] == 1)
    begin
      clockHandler = 1;
    end
    else
    begin
      clockHandler = 0;
    end
end

HexDigit d0(HEX0,hexdata[3:0]);
HexDigit d1(HEX1,hexdata[7:4]);
HexDigit d2(HEX2,hexdata[11:8]);
HexDigit d3(HEX3,hexdata[15:12]);


clock_divider clk1Hzfrom50MHz (
                clockHandler,
                CLOCK_50,
                KEY[3],
                clk_1Hz
                );

4 个答案:

答案 0 :(得分:4)

我的理解是,如果您使用异步重置,则verilog始终阻止的第一个语句必须是if(reset)项。

所以翻牌结构应该总是这样:

always @ (posedge clk or negedge rst_n) begin
   if(~rst_n) begin
       ...reset statements...
   end else begin
       ...all other statements...
   end
end

因此,对于您的情况,您应该在if(clockHandler==0)语句中移动else块,因为它与重置执行无关。更好的方法是将它移动到一个单独的组合总是阻塞,因为在一个总阻塞内混合阻塞和非阻塞语句通常不是一个好主意,除非你真的知道你在做什么。我认为你的情况很好。

答案 1 :(得分:0)

要添加到Tim的答案 - 原始代码(无论如何,第17行)都是有效的Verilog。

它的含义是“只要clk上升到rst_nclockHandler的下降沿,检查clockHandler并执行某些操作”(由方式,摆脱开始/结束;他们是冗余和冗长的)。当你想在真实硬件中实现它时,问题出现了,因此错误消息可能来自合成器,它需要的不仅仅是有效的Verilog。合成器怀疑它必须构建某种类型的同步元素,但是它不能(或者不会,精确地)处理在两者的边缘检查clk的情况。 / em> rst_n和{{1}}。遵循综合模板的规则,您将不会遇到此问题。

答案 2 :(得分:0)

这是编译错误还是合成错误?我使用相同的代码来查看它是否编译正常,我得到错误..此外,建议在同步块内使用“&lt; =”而不是“=”

答案 3 :(得分:0)

你使用相同的翻牌构造来做两件事。在代码中线性地导致状态的滑动。如果状态依赖于该时钟或重置,我总是将所有内容放在一个构造内,否则您需要额外的步骤来确保多个信号不会尝试改变您的状态。

当涉及翻牌结构时,你也不需要开头/结尾,Verilog知道如何为你处理。我相信Verilog虽然可以,但我通常不这样做。在块中使用单个语句时,也不必使用它。

所以你的第一个模块看起来像这样(如果我错过了一个块,请告诉我):

clock_divider.v模块(已编辑)

module clock_divider (clockHandler, clk, rst_n, clk_o);

parameter DIV_CONST = 10000000 ;  // 1 second
parameter DIV_CONST_faster = 10000000 / 5;
input clockHandler;
input clk;
input rst_n;

output reg clk_o;

reg [31:0] div;
reg en;
integer div_helper = 0;

always @ (posedge clk or negedge rst_n)
begin
    if(!rst_n)
    begin
        div <= 0;
        en <= 0;
        clk_o <= 1'b0;
    end
    else if(en)
    begin
        clk_o <= ~ clk_o;

        if(clockHandler == 0)
        begin 
            div_helper = DIV_CONST;
        end
        else
        begin 
            div_helper = DIV_CONST_faster;
        end
        else
        begin
            if (div == div_helper)
            begin 
                div <= 0;
                en <= 1;
            end
        end
        else
        begin 
            div <= div + 1;
            en <= 0;
        end
    end
end
end module

如果clk_o不打算同时处理那些其他操作,那么你可以用一般的'else'语句将其他所有内容分开。请确保将第二个构造嵌套为if语句以检查您的状态。

还记得像Tim提到的那样将@(posedge clk或negedge rst_n)添加到你的main.v模块中。