微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 延时上的问题

延时上的问题

时间:10-02 整理:3721RD 点击:

请高手指教一下啊,这个程序是从外界输入4个数,然后并行输出,怎样写才能达到同步输出呢?
我这样写的话最后一个数总是落后一个周期才输出结果。





module SP ( clk, rst_n, idin,
    dout_0, dout_1, dout_2, dout_3
     );
input clk, rst_n;
input [7:0] idin;
output [7:0] dout_0, dout_1, dout_2, dout_3;
wire sp_done;
reg [1:0] cnt;            
reg [7:0] dout_buf_0, dout_buf_1, dout_buf_2, dout_buf_3;  
reg [7:0] dout_0, dout_1, dout_2, dout_3;
assign sp_done = (cnt == 'b11) ? 1 : 0;
  
always @ (posedge clk or negedge rst_n)
if (!rst_n )
  cnt <= 'b0_0000;
else
  cnt <= cnt + 'b1;
  

always @ (sp_done)
  begin
   dout_0 = dout_buf_0;
   dout_1 = dout_buf_1;
   dout_2 = dout_buf_2;
   dout_3 = dout_buf_3;
end

always @ (posedge clk or negedge rst_n)
if (!rst_n)
  begin
   dout_buf_0 <= 'b0;
   dout_buf_1 <= 'b0;
   dout_buf_2 <= 'b0;
   dout_buf_3 <= 'b0;
  end
else
  case (cnt)
   'b00: dout_buf_0 = idin;
   'b01: dout_buf_1 = idin;
   'b10: dout_buf_2 = idin;
   'b11: dout_buf_3 = idin;
  endcase
endmodule

sp_done是个什么样的信号?

4组数据载入完成信号

你可以试试让sp_done 晚一个时钟周期 在把数据放到dout上,这样是可以的,我试了一下 数据正确显示。
但是这样不知道符不符合你设计的预期。
估计是不能在同一个沿让数据既输出又赋值,要延后一个时钟周期才可以正确的赋值的。

可不可以这样
assign a = (cnt == 'b10) ? 1 : 0;
always @ (posedge clk)
   if (a)
      sp_done = 1;
  else
     sp_done = 0;

还是不行的。我的方法是使计数器多记一个时钟周期,再把存好的数值输出出去。

楼上的你看看这样改可以么? 计数满四个的时候标志位a立刻置位, 同时第四组数据载入且sp_done = 1, 发出数据输出信号。
能给些更好的建议么?

assign a = (cnt == 'b11) ? 1 : 0;        
always @ (posedge clk or negedge rst_n)
        if (!rst_n )
                cnt <= 'b0_0000;
        else
                cnt <= cnt + 'b1;
               
always @ (posedge clk or negedge rst_n)
        if (!rst_n)
                sp_done = 0;
        else if (a)
                sp_done = 1;
        else
                sp_done = 0;
always @ (sp_done)
        if (sp_done)
                begin
                        dout_0 = dout_buf_0;
                        dout_1 = dout_buf_1;
                        dout_2 = dout_buf_2;
                        dout_3 = dout_buf_3;
                end

补个图


always @ (posedge clk or negedge rst_n)
        if (!rst_n)
                sp_done = 0;
        else if (a)
                sp_done = 1;
        else
                sp_done = 0;
这种语句有问题吧,容易出现竞争冒险!

module SP ( clk, rst_n, idin,
    dout0, dout1, dout2, dout3
     );
input clk, rst_n;
input [7:0] idin;
output [7:0] dout0, dout1, dout2, dout3;
wire sp_done;
reg [1:0] cnt_n;
wire[1:0] cnt;
            
reg [7:0] dout_buf0, dout_buf1, dout_buf2, dout_buf3;  
reg [7:0] dout0, dout1, dout2, dout3;
assign sp_done = (cnt_n == 'b11) ? 1 : 0;
always @ (posedge clk or negedge rst_n)
if (!rst_n )
  cnt_n <= #1 2'b00;
else
  cnt_n <= #1 cnt;
  
assign cnt = (cnt_n == 2'b11)?2'b00:cnt_n +1;
always @ (posedge clk or negedge rst_n)
  begin
   if(!rst_n)
   begin
   dout0 <= #1 0;
   dout1 <= #1 0;
   dout2 <= #1 0;
   dout3 <= #1 0;  
   end
   else if(sp_done)
   begin   
   dout0 <= #1 dout_buf0;
   dout1 <= #1 dout_buf1;
   dout2 <= #1 dout_buf2;
   dout3 <= #1 dout_buf3;
   end
   else
   begin
   dout0 <= #1 dout0;
   dout1 <= #1 dout1;
   dout2 <= #1 dout2;
   dout3 <= #1 dout3;
   end
end
always@(*)
  case (cnt_n)
   2'b00: dout_buf0 =  idin;
   2'b01: dout_buf1 =  idin;
   2'b10: dout_buf2 =  idin;
   2'b11: dout_buf3 =  idin;
  endcase

endmodule



上面是小弟改写的代码,但是问题也存在, 在代码中dout_buf0等应该只改变一次才是我的意愿,但是它改变了两次,这样中间的寄存器的值被改变了,造成结果不对,原因是什么呢?按照最后一个always模块他的中间寄存器的值不应该改变的啊? 求解释?(中间的寄存器的值不应该改变的啊 如图 dout_buf0 它从10 变成了11),原因?

时序逻辑赋值要用<=,
同一个always块里的赋值要用同一种赋值方式,要么都是=,要么都是<=

这不是出现锁相环了吗?



    qidaizhong...

下面这一段改改看看:
always@(*)
   case (cnt_n)
    2'b00: dout_buf0 =  idin;
    2'b01: dout_buf1 =  idin;
    2'b10: dout_buf2 =  idin;
    2'b11: dout_buf3 =  idin;
   endcase
改成:
always@(*)
   case (cnt_n)
    2'b00: begin
         dout_buf0 =  idin;
         dout_buf1 = dout_1;
         dout_buf2 = dout_2;
         dout_buf3 = dout_3;
    end
    2'b01: begin
         dout_buf0 = dout_0;
         dout_buf1 = idin;
         dout_buf2 = dout_2;
         dout_buf3 = dout_3;
    end
    2'b10: begin
         dout_buf0 = dout_0;
         dout_buf1 = dout_1;
         dout_buf2 = idin;
         dout_buf3 = dout_3;
    end
    2'b11: begin
         dout_buf0 = dout_0;
         dout_buf1 = dout_1;
         dout_buf2 = dout_2;
         dout_buf3 = idin;
    end
   endcase

you can check the changes for each input and use sp-done as output enable

assign sp_done = (cnt == 'b11) ? 1 : 0;
改成 assign sp_done = (cnt == 2'b00) ? 1 : 0;



    试试拿掉dout_buf_3,在第四个上升沿到的时候直接把in赋予dout_3。

用dout_0~3充当2级缓冲,等sp_done到来时立刻输出。这样就不阻止数据的输入了。



    同意,dout0,1,2都比din晚至少一拍,这样就可以用DFF存着,
  但是dout3要跟din同步,所以din不能再经过DFF给dout3了

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top