如何在Verilog中的延迟编程?

问题描述 投票:-1回答:2

我试图让使用LED的莫尔斯电码显示。我需要光线的一半第二脉冲来表示的点和1.5秒的脉冲来表示破折号。

我真的被困在这里。我已经用我的FPGA内部50MHz的时钟计数器。机器我必须做出将作为输入的3位数字,并把这一到莫尔斯字母,A-H,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 
verilog fpga morse-code
2个回答
3
投票

我一直在读你的代码,有很多问题:

  1. 该代码未格式化。
  2. 您没有提供一个测试台。你写一个?
  3. “无法解析净多不断驱动程序”搜索上的错误信息堆栈交换。它已被问了很多次。
  4. 总是使用@(*)未如总是@(州)你缺少像i, halfsecflag, ending信号。但是,见第6点:你想在一个时钟部分的状态。
  5. 当你总是使用@(posedge时钟),则必须使用非阻塞赋值:<=
  6. 在有些情况下,你使用always @(posedge CLK)很多地方要使用always @(*)(例如,您可以设置lengthcode)对面,你想用,你与你的工作状态一个posedge CLK
  7. 使用一个时钟,只有一个时钟。不要使用CLK和CLOCK_50。使用一个或另一个。
  8. 把你的矢量大小的照顾。这8'd25000000是错误的,你可以不适合25000000 8位。

halfsecflag的使用是极好的!我看到很多次,人们认为他们可以使用always @(halfsecflag)这是一个后患无穷!

下面你可以看到一小块代码的我已经重新编写。

  • 所有的作业都无阻塞<=
  • halfsecflag是操作码仅每隔半秒钟必不可少的,所以我把它通过将自身在一个单独的if顶部。我会用在整个代码。
  • 所有寄存器被重置,既COUNT2dashflag
  • dashflag设置为1,但从来没有回到0我固定的。
  • 我指定的向量大小。这使得代码“林特证明”。

就这个:

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
投票

通常你会建立有限状态机来产生输出。该机器将具有某些阶段,像读取输入,将其映射到莫尔斯电码元的序列,移出元件,以输出缓冲器中,等待条件来移动到下一个元素莫尔斯。你会需要一些定时器会产生一个莫尔斯时间单位间隔,并根据FSM阶段,你会等待一,三和七时间单位。密克罗尼西亚联邦将在待机台旋转,它并不“神奇”睡在一些FPGA产生的延迟,有没有这样的事情。

© www.soinside.com 2019 - 2024. All rights reserved.