3

我有一个关于我正在研究的 AGC/SPI 控制器的奇怪行为的问题。它在 Verilog 中完成,针对 Xilinx Spartan 3e FPGA。控制器是一个依赖外部输入启动的 FSM。FSM 的状态存储在未显式初始化的state_reg中,因为我认为未初始化的寄存器默认为零。当我实现控制器时,FSM 不会运行。监控 SPI 总线我没有观察到任何活动。为了监控 FSM,我将state_reg路由到了一个输出总线,该总线连接到一个 LED 组。这就是行assign data_out = state_reg是在做。我发现,当我这样做时,FSM 的 AGC/SPI 控制器运行正常,正如在 SPI 总线上观察到的那样。似乎正在发生的事情是state_reg在初始化时处于未确定状态,因此 FSM 永远不会处于任何状态,因此它不会运行。但是通过将state_reg分配给一个输出,它初始化为00000000,正如我从一开始就期望它做的那样。所以我的问题是,未初始化的寄存器是否应该假定值为 0?通过将未初始化的寄存器分配给输出,这是否会迫使它像看起来那样假设为零?或者这里发生了什么我不明白的事情?下面是我的代码。我已经评论了将 *state_reg** 分配给输出线 [7:0] data_out的相关部分. 我知道这是一个很长的问题,但我真的很想了解我应该期待什么样的行为。谢谢。

  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
4

2 回答 2

10

我在 FPGA 的背景下回答(我对 Xilinx FPGA 最有经验);我不同意蒂姆的回答。

当 FPGA 被编程和初始化时,许多内部资源被初始化为一个已知状态。这包括所有触发器和块 ram。通过在整个设计中添加一揽子重置逻辑,如果您可以依靠内部元素初始化为已知状态,您可能会使其变得比需要的复杂得多。高扇出复位网络会使路由器的设计实施变得更加困难,并且将您的设计映射到切片也因您选择的复位而变得复杂 - 尤其是异步复位。

我的建议:

  • 为您的寄存器使用初始化值。仔细检查您正在使用的版本的赛灵思 XST 文档以了解支持的语法。与普遍认为的相反,初始化值在大多数情况下都会得到尊重。这样做的另一个好处是芯片的初始状态将与模拟的初始状态相匹配。
  • 仅重置必要的控制信号并单独保留数据路径寄存器,以实现更有效的映射(例如,流水线到移位寄存器)。
于 2012-04-06T16:35:38.140 回答
0

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

,他们假设 x。对于 Synthesis,您必须重置,因为它们可能持有任何值。我没有 FPGA 经验,但 Nathan Farrington 建议它们也被重置/初始化。

对于 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
于 2012-04-11T13:50:18.917 回答