延时上的问题
请高手指教一下啊,这个程序是从外界输入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了
