Verilog, FPGA, использование унифицированного регистра

У меня есть вопрос о том, что мне кажется странным в поведении контроллера AGC/SPI, над которым я работаю. Это сделано в Verilog для Xilinx Spartan 3e FPGA. Контроллер представляет собой FSM, который полагается на внешние входы для запуска. Состояние FSM хранится в state_reg, который явно не инициализируется, так как я думал, что неинициализированный регистр по умолчанию будет равен нулю. Когда я внедрил контроллер, FSM не запустился. Мониторинг шины SPI я не заметил никакой активности. Для мониторинга FSM я направил state_reg на выходную шину, которая шла к блоку светодиодов. Это то, что делает строка 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

person Frank Dejay    schedule 05.04.2012    source источник
comment
Для проектов FPGA всегда, всегда, всегда инициализируйте свои регистры.   -  person Nathan Farrington    schedule 06.04.2012
comment
Получаете ли вы такие же странные результаты при инициализации регистров? Мне все еще любопытно, что может быть причиной этого странного поведения - обычно, если вы не укажете, инструменты по умолчанию будут равны 0, я думаю.   -  person Josh    schedule 06.04.2012


Ответы (2)


Я отвечаю в контексте ПЛИС (у меня больше всего опыта работы с ПЛИС Xilinx); Я не согласен с ответом Тима.

Когда FPGA программируется и инициализируется, многие внутренние ресурсы инициализируются до известного состояния. Это включает в себя все шлепанцы и блокираторы. Добавляя общую логику сброса по всему проекту, вы можете сделать его значительно сложнее, чем нужно, если в противном случае вы могли бы рассчитывать на инициализацию внутренних элементов до известного состояния. Сети сброса с большим разветвлением могут значительно затруднить реализацию вашего проекта для маршрутизатора, а отображение вашего проекта на слайсы также усложняется вашим выбором сбросов, особенно асинхронных.

Мои предложения:

  • Используйте значения инициализации для ваших регистров. Дважды проверьте документацию Xilinx XST для версии, которую вы используете для поддерживаемого синтаксиса. Вопреки широко распространенному мнению, значения инициализации будут учитываться в большинстве случаев. Дополнительным преимуществом этого является то, что начальное состояние вашего чипа будет соответствовать начальному состоянию вашей симуляции.
  • Сбрасывайте только необходимые управляющие сигналы и оставьте регистры пути данных в покое, чтобы обеспечить более эффективное отображение (например, конвейер в сдвиговый регистр).
person Josh    schedule 06.04.2012
comment
Вы делаете хорошее замечание, я не осознавал, что значение по умолчанию широко поддерживается на FPGA. Я позволил своему опыту работы с ASIC затуманить мои суждения :) - person Tim; 06.04.2012
comment
Для справки, это также описано в официальном документе Xilinx: xilinx.com/support /documentation/white_papers/wp272.pdf - person sonicwave; 07.04.2012

Итак, мой вопрос: должен ли неинициализированный регистр принимать значение 0?

Нет, предполагается x. Для Синтеза вы должны сбросить, так как они могут содержать любое значение. У меня нет опыта работы с ПЛИС, но Натан Фаррингтон предполагает, что они также сбрасываются/инициализируются.

Для FPGA должно быть достаточно сделать следующее:

reg [4:0] state_reg = 'b0,

Для Synthesis я бы рекомендовал делать это внутри предложения сброса.

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