2017-02-27 119 views
0

我必须设计一个使用FPGA和Verilog的红外发射器。verilog红外输出

其中一个条件是每10Hz发送一个数据包,我有一个计数器在主时钟(100MHz)的10Hz处创建一个辅助时钟。 该数据包包含开始间隙选择间隙右侧间隙左侧间隙前向间隙后向间隙。我有一个FSM在10Hz辅助时钟的正向边缘进行这种转换。 数据包中的每个块都有其大小,Gap只是将它们分开的空白空间。方向块选择时尺寸较大,否则较小。 在接收器的脉冲频率为36kHz的条件下,我有另一个计数器,它将主时钟减少到36kHz,我用这个计数器为Start,Select等产生脉冲大小,并在计数器递增时使输出为1到那个大小(对于开始的情况,请选择..)和0为间隙状态。

但是,当我通过智能手机摄像头查看LED时,显示它始终处于正常状态,这是我期望看到的,因为它应该每秒发送数据包10次。

问题是,汽车根本不动,我的问题是这是做事情的正确逻辑还是我错过了什么? 感谢

请求代码:

为36kHz脉冲

[email protected](posedge CLK) begin 
    if(RESET) begin 
     Counter <= 0; 
     SEC_CLK <= 0; 
    end 
    else if(Counter == 2778) begin 
     Counter <= 0; 
     SEC_CLK <= 1'b1; 
    end 
    else begin 
     Counter <= Counter + 1; 
     SEC_CLK <= 1'b0; 
    end 
end 

的10Hz的计数器,计数器,不知道是好是减少36kHz或使用主时钟,但它是一个不错的轮数,所以我使用的主时钟

[email protected](posedge CLK) begin 
    if(sec_counter == 100000) begin 
     sec_counter <= 0; 
     send <= 1; 
    end 
    else begin 
     sec_counter <= sec_counter +1; 
     send <= 0; 
    end 
end` 

的FSM逻辑:

[email protected](Curr_State) begin 
      case(Curr_State) 
       1'd0: begin //START 
        Next_State <= 1'd1; 
        Previous_State <= Next_State; 
        max_count <= StartBurstSize; 
        flag <= 0; 
       end 
       1'd1: begin //GAP 
        if(Previous_State <= 1'd7) 
         Next_State<=1'd0; 
        else 
         Next_State <= Previous_State +1; 
        max_count <= GapSize; 
        flag <= 1; 
             IR_LED = 1'b1; 

        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
       end 
       1'd2: begin //SELECT 
        Next_State <= 1'd1; 
        Previous_State <= Curr_State; 
        max_count <= CarSelectBurstSize; 
        IR_LED = 1'b0; 
        flag <= 0; 
        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
       end 
       1'd3: begin //RIGHT 
        if(BTNR) 
         max_count <= AsserBurstSize; 
        else 
         max_count <= DeAssertBurstSize; 
        Next_State <= 1'd1; 
        Previous_State <= Curr_State; 
        flag <= 0; 
        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
         IR_LED = 1'b1; 
       end 
       1'd4: begin //LEFT 
        if(BTNL) 
         max_count <= AsserBurstSize; 
        else 
         max_count <= DeAssertBurstSize; 
        Next_State <= 1'd1; 
        Previous_State <= Curr_State; 
        flag <= 0; 
        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
         IR_LED = 1'b1; 
       end 
       1'd5: begin //FORWARD 
        if(BTNU) 
         max_count <= AsserBurstSize; 
        else 
         max_count <= DeAssertBurstSize; 
        Next_State <= 1'd1; 
        Previous_State <= Curr_State; 
        flag <= 0; 
        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
         IR_LED = 1'b1; 
       end 
       1'd6: begin //Backwards 
        if(BTND) 
         max_count <= AsserBurstSize; 
        else 
         max_count <= DeAssertBurstSize; 
        Next_State <= 1'd1; 
        Previous_State <= Curr_State; 
        flag <= 0; 
        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
         IR_LED = 1'b1; 
       end 

      endcase 
end 

发送到红外脉冲LED

[email protected](posedge SEC_CLK) begin 
    if(send) begin 
     if(Pcounter == max_count) begin //COUNTING BLOCK SIZE 
      Pcounter <= 0; 
      IR_LED=1'b0; 
     end 
     else begin 
      if(flag) 
       IR_LED=1'b0; //GAP 
      else 
       IR_LED=1'b1; 
      Pcounter <= Pcounter+1; 
     end 
    end 
end 
+1

很难说没有看到您的代码。请在问题中包含您的代码。输出波形(如ISim)的屏幕截图也非常有用。 – duskwuff

回答

0

上有sec_counter没有复位,这样的行为可能是不可预测的(除非你指定一个初始值,当你宣布REG)。由于您没有包含代码的声明部分,因此很难说清楚。

你的状态机设计有点不寻常,我认为你没有得到你期望的行为。通常状态机以两种方式编码。一种方法将next_state计算放入一个组合块中,其中包含所有状态机输入和块的灵敏度列表中的当前状态。代码的第二同步总是块(即灵敏度列表posedge clk)将next_state分配给状态机时钟的posedge处的current_state。第二种方法对状态机和输出都使用一个同步始终块。在这种情况下,没有next_state变量,只需将新值直接赋值给状态变量,确保为每个分支或if语句赋值状态值。第二个版本可以运行得更快,因为所有的输出都是注册的,第一个版本使用较少的逻辑,我个人觉得它更容易解码。既然你的设计非常慢,我建议使用第一个版本。

由于没有使用时钟,您的状态机实际上并不保持状态 - 所以它实际上不是状态机。尝试从你的时钟信号运行它。另外,请确保正确处理时钟域交叉以避免亚稳态问题。

0

我不知道,如果你还在乎这个问题,但在你的case语句您有类似

1'd2: begin //SELECT 

甚至

Previous_State <= 1'd7 

不过,顶了表示小数数字宽度为1位,所以它不可能与0或1不同,最高有效位只会被丢弃。

你试过模拟这个吗?