如何在Verilog中设置延迟? [英] How to program a delay in Verilog?

查看:1494
本文介绍了如何在Verilog中设置延迟?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用led显示器显示莫尔斯电码.我需要半秒的光脉冲来表示一个点,而需要1.5秒的光脉冲来表示一个破折号.

I'm trying to make a morse code display using an led. I need a half second pulse of the light to represent a dot and a 1.5 second pulse to represent a dash.

我真的被困在这里.我在FPGA上使用内部50MHz时钟进行了计数.我必须制造的机器将输入3位数字并将其转换为摩斯字母,A-H,A为000,B为001,依此类推.我只需要弄清楚如何告诉FPGA将LED保持指定的时间,然后关闭大约一秒钟(这就是点脉冲和破折号脉冲之间的延迟).

I'm really stuck here. I have made a counter using an internal 50MHz clock on my FPGA. The machine I have to make will take as input a 3 bit number and translate that to a morse letter, A-H with A being 000, B being 001 and so on. I just need to figure out how to tell the FPGA to keep the led on for the specified time and then turn off for about a second (that would be the delay between a dot pulse and a dash pulse).

任何提示将不胜感激. 而且,它必须是可综合的.

Any tips would be greatly appreciated. Also, it has to be synthesizable.

这是我的代码.它还没有运行.它不断给我的错误消息是:

Here is my code. It's not functioning yet. The error message it keeps giving me is:

错误(10028):无法解析网络"c3 [0]"的多个常量驱动程序 在part4.v(149)

Error (10028): Can't resolve multiple constant drivers for net "c3[0]" at 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 

推荐答案

我一直在阅读您的代码,并且有很多问题:

I have been reading your code and there are many issues:

  1. 代码未格式化.

  1. The code is not formatted.

您未提供测试平台.你写了吗?

You did not provide a test-bench. Did you write one?

无法解析网络的多个常量驱动程序" 在堆栈交换中搜索错误消息.已经问了很多遍了.

"Can't resolve multiple constant drivers for net" Search on stack exchange for the error message. It has been asked many times.

始终使用@(*)而不是例如总是@(STATE),您会丢失诸如i, halfsecflag, ending之类的信号.但是请参见第6点:您希望在计时部分中使用STATE.

Use always @(*) not e.g. always @(STATE) you are missing signals like i, halfsecflag, ending. But see point 6: You want the STATE in a clocked section.

在始终使用@(posege CLK)的情况下,必须使用非阻塞分配:<=.

Where you use always @(posedge CLK) you must use non-blocking assignments: <=.

在许多使用always @(posedge CLK)的地方要使用always @(*)(例如,在其中设置lengthcode的地方)相反,在要使用posedge CLK的地方要使用您的国家.

There are many places where you use always @(posedge CLK) where you want to use always @(*) (e.g. where you set length and code) Opposite you want to use a posedge CLK where you work with your STATE.

仅使用一个时钟和一个时钟.请勿使用CLK CLOCK_50.使用其中之一.

Use one clock and one clock only. Do not use CLK and CLOCK_50. Use either one or the other.

照顾您的向量大小.此8'd25000000是错误的,因为您不能在8位中容纳25000000.

Take care of your vector sizes. This 8'd25000000 is wrong as you can no fit 25000000 in 8 bits.

您使用的halfsecflag非常好!我见过很多次人们认为他们可以使用always @(halfsecflag)这是灾难的秘诀!

Your usage of halfsecflag is excellent! I have see many times where people think they can use always @(halfsecflag) which is a recipe for disaster!

在下面,您会找到一小段我重新编写的代码.

Below you find a small piece of your code which I have re-written.

  • 所有分配都是非阻塞的<=

halfsecflag对于仅每半秒操作一次代码至关重要,因此我将其单独放在顶部的单独的if中.我会在整个代码中使用它.

halfsecflag is essential to operate the code only every half a second, so I put that by itself in a separate if at the top. I would use that throughout the code.

所有寄存器都重置,COUNT2dashflag.

All register are reset, both COUNT2 and dashflag.

dashflag设置为1,但从未设置回0.我已修复该问题.

dashflag was set to 1 but never set back to 0. I fixed that.

我指定了向量大小.它使代码不起毛的证明".

I specified the vector sizes. It makes the code "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 

以相同的方式开始修复其余代码.编写测试平台,在出现问题的波形显示器上进行仿真和跟踪.

Start fixing the rest of your code the same way. Write a test-bench, simulate and trace on a waveform display where things go wrong.

这篇关于如何在Verilog中设置延迟?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆