的Verilog,FPGA,使用未初始化寄存器的(Verilog, FPGA, use of an

2019-06-25 07:47发布

我有一个关于什么在我看来,一个AGC / SPI控制器我工作的古怪行为问题。 它用Verilog完成,瞄准一个赛灵思Spartan 3E FPGA。 该控制器是依赖于外部输入来启动FSM。 FSM的状态被存储在state_reg未明确初始化,因为我想到了一个未初始化的寄存器将默认为零。 当我实现了控制器的FSM将无法运行。 监控SPI总线我观察没有活动。 为了监控FSM我击溃了state_reg到去一个LED银行的输出总线。 这是该行指定什么DATA_OUT = state_reg在做什么。 我发现,虽然,当我做了SPI总线上所观察到的这个有限状态机的AGC / SPI控制器正确地操作。 看来,正在发生的事情是,state_reg是处于不确定的状态,当它初始化,因此,该FSM从来没有在任何状态下,因此不会运行。 但是,到输出分配state_reg它初始化为00000000如我所料它从一开始就做。 所以我的问题是,是否应该承担的0值未初始化寄存器? 通过分配未初始化寄存器的输出,这是否迫使它假定为零,因为它似乎? 抑或是别的事情就在这里,我不明白? 下面是我的代码。 我已经发表了评论,其中* state_reg **被分配给输出线相关部分[7:0] DATA_OUT。 我知道这是一个长期的问题,但我的“M真的想了解我应该期待什么样的行为。谢谢。

  module agc_control
        (
            input wire [7:0] agc_data,
            input wire clk,
            input wire agc_start,
            input wire AMP_DO,
            output reg MOSI,
            output reg SCK,
            output reg CS_AMP,
            output wire inhibit_ADC,
            output wire [7:0] data_out  
         );

        //signals
        reg [4:0] state_reg,
        reg [2:

0] ampclkreg;
    reg ampclk;
    reg [7:0] agc_data_reg;
    reg agc_running;
    reg [7:0] data_out_reg;
    wire agc_done;




    //ampclk generation
    always @(posedge clk)
        begin
            ampclkreg = ampclkreg + 1;
            if (ampclkreg == 3)
                begin
                    ampclkreg = 0;
                    ampclk = ~ampclk;
                end
        end

    always @(posedge clk)
        begin
            if(agc_start == 1)
                begin
                    agc_running = 1'b1;
                    agc_data_reg = agc_data;
                end
            if(agc_done == 1)
                begin
                    agc_running = 1'b0;
                end
        end



    //FSM
    always @(posedge ampclk)
        begin
            if (agc_running == 0)
                begin
                    SCK = 0;
                    state_reg = 0;
                    CS_AMP = 1;
                end
            if (agc_running == 1)
                begin
                    case (state_reg)
                        0:  begin
                                CS_AMP = 1;
                                SCK = 0;
                                state_reg = 1;
                            end
                        1:  begin
                                CS_AMP = 0;
                                MOSI = agc_data_reg[7];
                                state_reg = 2;
                            end
                        2:  begin
                                SCK = 1;
                                state_reg = 3;
                            end
                        3:  begin
                                SCK = 0;
                                MOSI = agc_data_reg[6];
                                state_reg = 4;
                            end
                        4:  begin
                                SCK = 1;
                                state_reg = 5;
                            end
                        5:  begin
                                SCK = 0;
                                MOSI = agc_data_reg[5];
                                state_reg = 6;
                            end
                        6:  begin
                                SCK = 1;
                                state_reg = 7;
                            end
                        7:  begin
                                SCK = 0;
                                MOSI    = agc_data_reg[4];
                                state_reg = 8;
                            end
                        8:  begin
                                SCK = 1;
                                state_reg = 9;
                            end
                        9:  begin
                                SCK = 0;
                                MOSI = agc_data_reg[3];
                                state_reg = 10;
                            end
                        10:begin
                                SCK = 1;
                                state_reg = 11;
                            end
                        11:begin
                                SCK = 0;
                                MOSI = agc_data_reg[2];
                                state_reg = 12;
                            end
                        12:begin
                                SCK = 1;
                                state_reg = 13;
                            end
                        13:begin
                                SCK = 0;
                                MOSI = agc_data_reg[1];
                                state_reg = 14;
                            end
                        14:begin
                                SCK = 1;
                                state_reg = 15;
                            end
                        15:begin
                                SCK = 0;
                                MOSI = agc_data_reg[0];
                                state_reg = 16;
                            end
                        16:begin
                                SCK = 1;
                                state_reg = 17;
                            end
                        17:begin
                                CS_AMP = 1;
                                state_reg = 18;
                            end
                        18:begin
                                SCK = 0;
                                state_reg = 19;
                            end
                        19:begin
                                state_reg = 19;
                            end
                    default: state_reg = 19;
                endcase
            end
        end

    //retrieve previous vlaues
    always @(posedge clk)
    begin
        case(state_reg)
            2: begin
                    if (ampclkreg == 2)             
                        data_out_reg[7] = AMP_DO;
                end
            4: begin
                    if (ampclkreg == 2)
                        data_out_reg[6] = AMP_DO;
                end
            6: begin 
                    if (ampclkreg == 2)
                        data_out_reg[5] = AMP_DO;
                end
            8:  begin
                    if (ampclkreg == 2)
                        data_out_reg[4] = AMP_DO;
                end
            10:begin
                    if (ampclkreg == 2)
                        data_out_reg[3] = AMP_DO;
                end
            12:begin
                    if (ampclkreg == 2)
                        data_out_reg[2] = AMP_DO;
                end
            14:begin
                    if (ampclkreg == 2)
                        data_out_reg[1] = AMP_DO;
                end
            16:begin
                    if (ampclkreg == 2)
                        data_out_reg[0] = AMP_DO;
                end

        endcase
    end


    //output wire [7:0] data_out--to top module to drive 7 LEDs and display state_reg
    assign data_out =  state_reg;

    assign agc_done = (state_reg == 19);
    assign inhibit_ADC = (agc_running == 1);


    endmodule

Answer 1:

我的回答是在FPGA中的情况下(我与赛灵思FPGA最有经验); 我不同意Tim的答案。

当FPGA进行编程和初始化, 许多内部资源被初始化为一个已知的状态。 这包括所有触发器和块RAM。 通过在整个设计中加入毯复位逻辑,你可以让它显著复杂得多,它需要的,如果你能以其他方式初始化到已知状态,内部元件数。 高扇出复位网可以实现您的设计更加困难的路由器,并映射设计成片也由您选择重置的复杂 - 特别是异步的。

我的建议:

  • 使用初始值的寄存器。 仔细检查赛灵思XST文档,您正在使用支持的语法的版本。 相反,广泛持有的信念,初始化值会在大多数情况下兑现。 这样做的附带好处是,你的芯片的初始状态将匹配你的模拟的初始状态。
  • 仅重置必要的控制信号和单独离开你的数据通路的寄存器来允许更有效的映射(例如,一个管道到移位寄存器)。


Answer 2:

所以我的问题是,是否应该承担的0值未初始化寄存器?

,他们假设X。 对于合成必须重置,因为他们可能持有的任何值。 我没有FPGA经验,但内森富华表明它们也将复位/初始化。

对于FPGA执行以下操作应该是足够了:

reg [4:0] state_reg = 'b0,

对于合成我建议这样做复位子句中。

always @(posedge clk or negedge reset) begin
  if (!reset) begin
    state_reg <= 'b0 ;
  end
  else begin
    ..
  end
end


文章来源: Verilog, FPGA, use of an unitialized register