«ОШИБКА: несколько драйверов на net» при установке регистра как для положительного, так и для отрицательного фронта - PullRequest
0 голосов
/ 12 июля 2020

Я следил за учебником по мастеру SPI в Verilog. Я отлаживаю это около трех часов и не могу заставить его работать.

Мне удалось разбить проблему на минимальную репрезентативную проблему. Вот спецификации:

У нас есть два состояния, IDLE и COUNTING. Затем на положительном фронте clock мы проверяем:

  • Если состояние IDLE, то регистр counter устанавливается в 0. Если в этом состоянии dataReady вывод высокий, то state устанавливается на COUNTING, а counter устанавливается на все единицы.

  • Если состояние COUNTING, состояние остается COUNTING, пока counter не равно нулю. В противном случае состояние возвращается в IDLE.

Затем мы рассчитываем по отрицательному фронту:

  • По отрицательному фронту clock, если state равно COUNTING, затем уменьшаем counter.

Вот код, который я придумал, чтобы соответствовать этой спецификации:

// look in pins.pcf for all the pin names on the TinyFPGA BX board
module top (
    input CLK,    // 16MHz clock
    input PIN_14,
    output LED,   // User/boot LED next to power LED
    output USBPU  // USB pull-up resistor
);
    // drive USB pull-up resistor to '0' to disable USB
    assign USBPU = 0;

    reg [23:0] clockDivider;
    wire clock;

    always @(posedge CLK)
        clockDivider <= clockDivider + 1;

    assign clock = clockDivider[23];

    wire dataReady;
    assign dataReady = PIN_14;


    parameter IDLE = 0, COUNTING = 1;
    reg state = IDLE;

    reg [3:0] counter;

    always @(posedge clock) begin
        case (state)
            IDLE: begin
                if (dataReady)
                    state <= COUNTING;
            end
            COUNTING: begin
                if (counter == 0)
                    state <= IDLE;
            end
        endcase
    end

    always @(negedge clock) begin
        if (state == COUNTING)
            counter <= counter - 1;
    end

    always @(state) begin
        case (state)
            IDLE:
                counter <= 0;
            COUNTING:
                counter <= counter;
        endcase
    end

    assign LED = counter != 0;
endmodule

Таким образом, мы получаем ошибка:

ERROR: multiple drivers on net 'LED' (LED_SB_DFFNE_Q.Q and LED_SB_DFFNE_Q_1.Q)

Почему? На светодиодном индикаторе буквально одна инструкция присваивания.

1 Ответ

2 голосов
/ 13 июля 2020

Во-первых, в таком случае было бы непросто придумать синтезируемую модель. Но вам не нужны никакие negedge logi c для реализации вашей модели. Также вы сделали несколько ошибок и нарушили многие общепринятые практики.

Теперь о некоторых проблемах в вашем коде.

  1. Используя неблокирующее назначение в строке часов, вы создали условие гонки в симуляция, которая, вероятно, приведет к неверным результатам симуляции:
always @(posedge CLK)
        clockDivider <= clockDivider + 1; // <<< this is a red flag!
assign clock = clockDivider[23];
...
always @(posedge clk)
вы неправильно использовали nbas в своем всегда блоке
always(@state)
... counter <= conunter-1; // <<< this is a red flag again!
ваш конечный автомат не сброшен. Такие утверждения, как reg state = IDLE;, будут работать только в симуляции и в некоторых fpgas. Это вообще не синтезируется. Я предлагаю вам не использовать его, а вместо этого подать сигнал сброса.

Сказав это, я не знаю какой-либо методологии, которая использовала бы положительные и отрицательные фронты в таком случае. Так что не стоит. Вся ваша реализация может быть выполнена под постановкой, примерно так. Однако

always @(posedge clock) begin
   if (reset) begin  // i suggest that you use reset in some form.
      state <= IDLE;
      counter <= 0;
   end
   else begin
        case (state)
            IDLE: begin
                if (dataReady) begin
                    state <= COUNTING;
                    counter <= counter - 1; 
                end
            end
            COUNTING: begin
                if (counter == 0) 
                    state <= IDLE;
                else 
                    counter <= counter - 1;
            end

        endcase
    end
end

Надеюсь, я сделал все правильно, не тестировал.

Теперь вам вообще не нужны два других блока always.

...