I2S Transmitter Verilog实现无法正常工作

时间:2016-11-22 05:09:53

标签: verilog

我正在尝试在verilog中实现I2S Transmitter。其数据表位于:https://www.sparkfun.com/datasheets/BreakoutBoards/I2SBUS.pdf

我编写了代码,但是当我测试时,我的SD线延迟了1个时钟周期。 有人可以查看我的实施吗?

module Transmiter(
    input signed [23:0] DLeft, input signed [23:0] DRight, input WS, input CLK,
    output reg SD
    );

  wire PL;
  reg Q1,Q2;
  reg [23:0] shift_reg;
  reg [23:0] Tdata;


   assign PL = Q1^Q2;



   always @(posedge CLK)
    begin
       Q1 <= WS;
       Q2 <= Q1;
    end


    always @( Q1)  begin
       if (Q1)  
         begin
         Tdata <= DRight;
         end
       else
          begin
          Tdata  <= DLeft;
          end
    end



   always @(negedge CLK)
       begin   

           if(PL)
           begin
              shift_reg <= Tdata;
           end
           else begin

           SD <= shift_reg[23];
           shift_reg <= {shift_reg[22:0],1'b0};
           end
       end


endmodule

编辑:这是波形image

的图像

TEST BENCH CODE:

module Transmitter_tb(

    );


    reg CLK, WS;
    reg [23:0] dataL;
    reg [23:0] dataR;

    wire SDout;



    Transmiter UT(dataL, dataR, WS, CLK, SDout);

    initial begin 
    dataL = 24'hF0F0FF; #2;
    dataR = 24'h0000F0; #2;

    end



    always begin
     CLK=0; #20;
     CLK=1; #20;
    end;

        always begin
     WS=0; #1000;
     WS=1; #1000;
    end;





endmodule

2 个答案:

答案 0 :(得分:1)

您的negedge块包含if-else结构,并且只能在单个时钟边沿计算一个或另一个。因此SDPL为高时不会改变价值。

此外,您在代码中使用了非阻止分配(<=)。这大致意味着在始终阻止结束之前不会评估变化。因此,即使在SD <= shift_reg[23]之后shift_reg <= Tdata,它也不会在shift_reg[23]中使用新值,而是使用之前的值。如果您希望在SD更改时立即更改shift_reg[23],则需要以组合方式执行此操作。

这应该有效:

always @(negedge CLK)
   begin   

       if(PL)
       begin
          shift_reg <= Tdata;
       end
       else
          shift_reg <= {shift_reg[22:0],1'b0};
   end
   assign SD = shift_reg[23];

工作示例:https://www.edaplayground.com/x/4bPv

另一方面,我仍然不相信DRightDLeft实际上是常数,我可以看到它们在你的结核病中,但数据没有意义因为你的I2S是不变的。您当前的构造可能会生成一个锁存器(而不是MUX),我们通常不希望那些在我们的设计中。

答案 1 :(得分:0)

您应该清除阻塞与非阻止语句的使用:

始终在时钟语句中使用非阻塞分配,意思是“&lt; =”。

始终在组合(非时钟)语句中使用阻塞分配,即“=”。

这是一项行业范围的建议,而不是个人意见。您可以在许多地方找到此建议,例如:

http://web.mit.edu/6.111/www/f2007/handouts/L06.pdf

敏感性列表不完整(由@Hida指出)也可能导致问题。

尝试纠正这两件事,看看它是否按预期开始工作。

另请注意,您正在使用Q1(以及其他信号)来生成PL信号。如果WS输入与本地时钟不同步(我认为不是),则在开始使用输出之前需要再放一次(即两个串联),以避免亚稳态问题。但是你不会在RTL模拟中看到这一点。