Как запрограммировать задержку в Verilog? - PullRequest
0 голосов
/ 02 февраля 2019

Я пытаюсь сделать отображение кода Морзе с помощью светодиода.Мне нужен полсекундный импульс света для представления точки и 1,5 секундный импульс для представления тире.

Я действительно застрял здесь.Я сделал счетчик, используя внутренние часы 50 МГц на моей FPGA.Машина, которую я должен сделать, примет в качестве входных данных 3-битное число и переведет его в азбуку Морзе, AH с A 000, B с 001 и так далее.Мне просто нужно выяснить, как сказать FPGA, чтобы светодиод оставался включенным в течение указанного времени, а затем выключался примерно на секунду (это было бы задержкой между точечным импульсом и штриховым импульсом).

Любые советы будут с благодарностью.Кроме того, он должен быть синтезируемым.

Вот мой код.Это еще не работает.Я получаю сообщение об ошибке:

Ошибка (10028): не удается разрешить несколько постоянных драйверов для сети "c3 [0]" в part4.v (149)

module part4 (SELECT, CLK, CLOCK_50, RESET, led);
input [2:0]SELECT;
input RESET, CLK, CLOCK_50;
output reg led=0;
reg [26:0] COUNT=0; //register that keeps track of count
reg [1:0] COUNT2=0; //keeps track of half seconds
reg halfsecflag=0;  //goes high every time half second passes
reg dashflag=0;     //goes high every time 1 and half second passes
reg [3:0] code;     //1 is dot and 0 is dash. There are 4 total
reg [1:0] c3;       //keeps track of the index we are on in the code.
reg [3:0] STATE;    //register to keep track of states in the state machine
reg done=0;         //a flag that goes up when one morse pulse is done.
reg ending=0;       //another flag that goes up when a whole morse letter has flashed
reg [1:0] length;   //This is the length of the morse letter. It varies from 1 to 4
wire i;             // if i is 1, then the state machine goes to "dot". if 0 "dash"

assign i = code[c3];

parameter START= 4'b000, DOT= 4'b001, DASH= 4'b010, DELAY= 4'b011, IDLE= 
4'b100;

parameter A= 3'b000, B=3'b001, C=3'b010, D=3'b011, E=3'b100, F=3'b101, 
G=3'b110, H=3'b111;


always @(posedge CLOCK_50 or posedge RESET) //making counter
begin
    if (RESET == 1)
        COUNT <= 0;
    else if (COUNT==8'd25000000)
    begin
        COUNT <= 0;
        halfsecflag <= 1;
    end
    else
    begin
        COUNT <= COUNT+1;
        halfsecflag <=0;
    end
end

always @(posedge CLOCK_50 or posedge RESET)
begin
    if (RESET == 1)
        COUNT2 <= 0;
    else if ((COUNT2==2)&&(halfsecflag==1))
    begin
        COUNT2 = 0;
        dashflag=1;
    end
    else if (halfsecflag==1)
        COUNT2= COUNT2+1;
end



always @(RESET) //asynchronous reset
begin
    STATE=IDLE;
end


always@(STATE) //State machine
begin
    done=0;
    case(STATE)

        START: begin
            led = 1;
            if (i) STATE = DOT;
            else STATE = DASH;
        end

        DOT: begin
            if (halfsecflag && ~ending) STATE = DELAY;
            else if (ending) STATE= IDLE;
            else STATE=DOT;
        end

        DASH: begin
            if ((dashflag)&& (~ending))
                STATE = DELAY;
            else if (ending)
                STATE = IDLE;
            else STATE = DASH;
        end

        DELAY: begin
            led = 0;
            if ((halfsecflag)&&(ending))
                STATE=IDLE;
            else if ((halfsecflag)&&(~ending))
            begin
                done=1;
                STATE=START;
            end
            else STATE = DELAY;
        end

        IDLE: begin
            c3=0;
            if (CLK) STATE=START;
            else STATE=IDLE;
        end

        default: STATE = IDLE;

    endcase
end


always @(posedge CLK)
begin
    case (SELECT)
        A: length=2'b01;
        B: length=2'b11;
        C: length=2'b11;
        D: length=2'b10;
        E: length=2'b00;
        F: length=2'b11;
        G: length=2'b10;
        H: length=2'b11;
        default: length=2'bxx;
    endcase
end

always @(posedge CLK)
begin
    case (SELECT)
        A: code= 4'b0001;
        B: code= 4'b1110;
        C: code= 4'b1010;
        D: code= 4'b0110;
        E: code= 4'b0001;
        F: code= 4'b1011;
        G: code= 4'b0100;
        H: code= 4'b1111;
        default: code=4'bxxxx;
    endcase
end

always @(posedge CLK)
begin 
    if (c3==length) 
    begin
        c3<=0; ending=1;
    end
    else if (done)
        c3<= c3+1;
    end 
endmodule 

Ответы [ 2 ]

0 голосов
/ 03 февраля 2019

Я читал ваш код, и есть много проблем:

  1. Код не отформатирован.

  2. Вы не предоставилииспытательный стенд.Вы написали один?

  3. «Не удается разрешить несколько постоянных драйверов для сети» Поиск в стеке обмена для сообщения об ошибке.Об этом спрашивали много раз.

  4. Используйте всегда @ (*), а не всегда @ (СОСТОЯНИЕ), вы пропускаете сигналы типа i, halfsecflag, ending.Но смотри пункт 6: вы хотите СОСТОЯНИЕ в закрытом разделе.

  5. Если вы используете всегда @ (posedge CLK), вы должны использовать неблокирующие назначения: <=.

  6. Есть много мест, гдевы используете always @(posedge CLK) там, где хотите использовать always @(*) (например, там, где вы установили length и code). Напротив, вы хотите использовать posedge CLK там, где вы работаете с вашим STATE.

  7. Используйте только одни часы и одни часы.Не используйте CLK и CLOCK_50.Используйте один или другой.

  8. Позаботьтесь о своих векторных размерах.Это 8'd25000000 неверно, так как вы не можете уместить 25000000 в 8 битах.

Использование halfsecflag отлично!Я много раз видел, как люди думают, что могут использовать always @(halfsecflag), что является рецептом катастрофы!

Ниже вы найдете небольшой фрагмент вашего кода, который я переписал.

  • Все назначения не блокируют <=

  • halfsecflag необходимо для работы с кодом только каждые полсекунды, поэтому я поместил его отдельно в if вверху.Я бы использовал это по всему коду.

  • Все регистры сброшены, и COUNT2 и dashflag.

  • dashflag былоустановить на 1, но никогда не устанавливать обратно на 0. Я это исправил.

  • Я указал размеры вектора.Это делает код "Lint proof".

Вот оно:

always @(posedge CLOCK_50 or posedge RESET)
begin
   if (RESET == 1'b1)
   begin 
      COUNT2 <= 2'd00;
      dashflag <= 1'b0;
   end // reset
   else if (halfsecflag) // or  if (halfsecflag==1'b1)
   begin     
      if (COUNT2==2'd2))
      begin
         COUNT2 <= 2'd0;
         dashflag <=1'b1;
      end
      else
      begin
         COUNT2 <= COUNT2+2'd1;
         dashflag <=1'b0;
      end
   end // clocked 
end // always 

Начните исправлять оставшуюся часть кода таким же образом.Напишите тестовый стенд, смоделируйте и проследите на дисплее сигнала, где что-то идет не так.

0 голосов
/ 02 февраля 2019

Обычно вы должны создать конечный автомат для получения результата.У этой машины будет несколько этапов, таких как чтение ввода, сопоставление его с последовательностью элемента кода Морзе, смещение элементов в выходной буфер, ожидание перехода условий к следующему элементу Морзе.Вам понадобится некоторый таймер, который будет генерировать интервалы времени по одному Морзе, и в зависимости от этапа FSM вы будете ждать одну, три или семь единиц времени.FSM будет вращаться на этапе ожидания, он не «волшебным образом» спит с некоторой задержкой, производимой fpga, таких вещей нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...