例如: IOs A和B是连接的,它们之间有10 to的io延迟。IOs以500 The (2ns周期)运行。
默认情况下,Verilog使用惯性延迟作为滤波器。因此,将互连线定义为wire #(10ns) io;将无法工作,因为它将过滤掉数据。
wire #(10ns) io;
assign io = io_a_en ? a_data_500MHz : 'z;
assign io = io_b_en ? b_data_500MHz : 'z;传输延迟是单向的。为IO上的每个方向创建一个将导致多个驱动程序和一个反馈循环。
always @(a) b_reg <= #(10ns) a;
always @(b) a_reg <= #(10ns) b;
assign a = b_reg; // feedback b_reg = b = a_reg = a ... and multi-driver
assign b = a_reg; // feedback a_reg = a = b_reg = b ... and multi-driver
assign a = io_a_en ? a_data_500MHz : 'z;
assign b = io_b_en ? b_data_500MHz : 'z;一个模式的双向传输延迟应该如何?
发布于 2017-12-14 19:06:00
双向传输延迟可以通过两个单向传输延迟的驱动强度来实现.该模型应将网络分配给较弱的驱动强度IO驱动程序。这将优先考虑真正的司机和防止司机冲突。
为了防止反馈循环,使用驱动器强度作为限定符来决定传输延迟应该分配源值还是高Z值。确定驱动器强度的一种简单方法是使用%v,请参阅IEEE Std 1800-2012§21.2.1.5强度格式
module bidi_delay #( parameter INERTIAL=0, TRANSPORT=10 ) (
inout a, b
);
reg a2b, b2a;
reg [23:0] a_strength, b_strength;
always @(a) begin
$sformat(a_strength, "%v", a);
a2b <= #(TRANSPORT) (a_strength[23:16] == "S") ? a : 1'bz;
end
always @(b) begin
$sformat(b_strength, "%v", b);
b2a <= #(TRANSPORT) (b_strength[23:16] == "S") ? b : 1'bz;
end
assign (weak0,weak1) #(INERTIAL) a = b2a;
assign (weak0,weak1) #(INERTIAL) b = a2b;
endmodule用Aldec Riviera、Icarus Verilog和GPL Cver在EDAplayground上进行测试
发布于 2022-02-04 14:28:02
我在文章https://www.fpgarelated.com/showthread/comp.arch.fpga/58894-1.php中研究了格雷格的解决方案和解决方案。这两种解决方案都有一个共同的缺点:没有考虑到io的优点。例如,Greg的解决方案将信号强度降低到弱,如果IO不是“强”或“供应”,那么上面的代码就无法工作。
因此,我试图写我自己的解决方案。
module via_d (inout l, r, input bit en);
timeunit 1ps;
timeprecision 100fs;
const bit[2:0] assoc_strn2int [bit[15:0]]='{ "Hi":0, "We":1, "Pu":2, "St":3, "Su":4};
real d_l2r_ps;
real d_r2l_ps;
bit l_internal_oe, r_internal_oe;
bit[23:0] r_desc, l_desc, r_desc_dly, l_desc_dly, r_desc_inside, l_desc_inside;
event l_stronger_drive_detected, r_stronger_drive_detected;
initial {r_desc_dly,l_desc_dly} = {2{"HiZ"}};
always @(r_desc_inside or l_desc_dly or r_stronger_drive_detected)
r_internal_oe <= oe_definition(l_desc_dly, r_desc, r_internal_oe);
always @(l_desc_inside or r_desc_dly or l_stronger_drive_detected)
l_internal_oe <= oe_definition(r_desc_dly, l_desc, l_internal_oe);
always @(l_desc_inside)
l_desc_dly <= #(d_l2r_ps) l_desc_inside;
always @(r_desc_inside)
r_desc_dly <= #(d_r2l_ps) r_desc_inside;
assign r_desc_inside = !r_internal_oe ? r_desc : "HiZ" ;
assign l_desc_inside = !l_internal_oe ? l_desc : "HiZ" ;
always @(r_desc_dly[23:8] or l_desc[23:8])
if((l_internal_oe == 1) & (r_desc_dly != l_desc))
-> l_stronger_drive_detected;
always @(l_desc_dly[23:8] or r_desc[23:8])
if((r_internal_oe == 1) & (l_desc_dly != r_desc))
-> r_stronger_drive_detected;
always_comb if(en) $sformat(l_desc, "%v", l);
always_comb if(en) $sformat(r_desc, "%v", r);
via_strn_driver driver_l (r_desc_dly, l_internal_oe & en , l);
via_strn_driver driver_r (l_desc_dly, r_internal_oe & en , r);
function automatic bit oe_definition (bit[23:0] inside_desc, outside_desc, bit old_oe);
oe_definition = inside_desc[23:8] == outside_desc[23:8] ? old_oe :
(assoc_strn2int[inside_desc[23:8]] > assoc_strn2int[outside_desc[23:8]]);
endfunction
endmodule
module via_strn_driver(input bit [23:0] descr, bit en, output o);
logic val ;
always_comb begin
case(descr[7:0])
"1": val = 1'b1;
"0": val = 1'b0;
"X": val = 1'bx;
"Z": val = 1'bz;
default: $error(" Descr value is uncompatible with logic type");
endcase
end
assign (supply1,supply0) o = en ? ( descr[23:8] == "Su" ? val : 'z) : 'z;
assign (strong1,strong0 )o = en ? ( descr[23:8] == "St" ? val : 'z) : 'z;
assign (pull1,pull0) o = en ? ( descr[23:8] == "Pu" ? val : 'z) : 'z;
assign (weak1,weak0) o = en ? ( descr[23:8] == "We" ? val : 'z) : 'z;
endmodulevia_d模块能够以其自身的强度传递信号。该解决方案在vcs (synopsys)工具上进行检查。我希望我的解决方案将对你的核查有用。
https://stackoverflow.com/questions/47820470
复制相似问题