mirror of
https://github.com/corundum/corundum.git
synced 2025-01-16 08:12:53 +08:00
Refactor pointer handling in FIFOs
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
parent
9cb38fa2a0
commit
2be72bb758
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014-2021 Alex Forencich
|
||||
Copyright (c) 2014-2023 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -162,10 +162,9 @@ localparam USER_OFFSET = DEST_OFFSET + (DEST_ENABLE ? DEST_WIDTH : 0);
|
||||
localparam WIDTH = USER_OFFSET + (USER_ENABLE ? USER_WIDTH : 0);
|
||||
|
||||
reg [ADDR_WIDTH:0] wr_ptr_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_cur_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_commit_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_sync_gray_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_cur_gray_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_sync_commit_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
@ -177,6 +176,8 @@ reg [ADDR_WIDTH:0] wr_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
(* SHREG_EXTRACT = "NO" *)
|
||||
reg [ADDR_WIDTH:0] wr_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
(* SHREG_EXTRACT = "NO" *)
|
||||
reg [ADDR_WIDTH:0] wr_ptr_commit_sync_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
(* SHREG_EXTRACT = "NO" *)
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync1_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
(* SHREG_EXTRACT = "NO" *)
|
||||
reg [ADDR_WIDTH:0] rd_ptr_gray_sync2_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
@ -218,11 +219,10 @@ reg [RAM_PIPELINE+1-1:0] m_axis_tvalid_pipe_reg = 0;
|
||||
// full when first TWO MSBs do NOT match, but rest matches
|
||||
// (gray code equivalent of first MSB different but rest same)
|
||||
wire full = wr_ptr_gray_reg == (rd_ptr_gray_sync2_reg ^ {2'b11, {ADDR_WIDTH-1{1'b0}}});
|
||||
wire full_cur = wr_ptr_cur_gray_reg == (rd_ptr_gray_sync2_reg ^ {2'b11, {ADDR_WIDTH-1{1'b0}}});
|
||||
// empty when pointers match exactly
|
||||
wire empty = rd_ptr_gray_reg == (FRAME_FIFO ? wr_ptr_gray_sync1_reg : wr_ptr_gray_sync2_reg);
|
||||
wire empty = FRAME_FIFO ? (rd_ptr_reg == wr_ptr_commit_sync_reg) : (rd_ptr_gray_reg == wr_ptr_gray_sync2_reg);
|
||||
// overflow within packet
|
||||
wire full_wr = wr_ptr_reg == (wr_ptr_cur_reg ^ {1'b1, {ADDR_WIDTH{1'b0}}});
|
||||
wire full_wr = wr_ptr_reg == (wr_ptr_commit_reg ^ {1'b1, {ADDR_WIDTH{1'b0}}});
|
||||
|
||||
// control signals
|
||||
reg write;
|
||||
@ -254,7 +254,7 @@ reg good_frame_sync2_reg = 1'b0;
|
||||
reg good_frame_sync3_reg = 1'b0;
|
||||
reg good_frame_sync4_reg = 1'b0;
|
||||
|
||||
assign s_axis_tready = (FRAME_FIFO ? (!full_cur || (full_wr && DROP_OVERSIZE_FRAME) || DROP_WHEN_FULL) : !full) && !s_rst_sync3_reg;
|
||||
assign s_axis_tready = (FRAME_FIFO ? (!full || (full_wr && DROP_OVERSIZE_FRAME) || DROP_WHEN_FULL) : !full) && !s_rst_sync3_reg;
|
||||
|
||||
wire [WIDTH-1:0] s_axis;
|
||||
|
||||
@ -326,7 +326,7 @@ always @(posedge s_clk) begin
|
||||
if (wr_ptr_update_reg == wr_ptr_update_ack_sync2_reg) begin
|
||||
// no sync in progress; sync update
|
||||
wr_ptr_update_valid_reg <= 1'b0;
|
||||
wr_ptr_sync_gray_reg <= wr_ptr_gray_reg;
|
||||
wr_ptr_sync_commit_reg <= wr_ptr_commit_reg;
|
||||
wr_ptr_update_reg <= !wr_ptr_update_ack_sync2_reg;
|
||||
end
|
||||
end
|
||||
@ -362,44 +362,46 @@ always @(posedge s_clk) begin
|
||||
// update pointers
|
||||
wr_ptr_temp = wr_ptr_reg + 1;
|
||||
wr_ptr_reg <= wr_ptr_temp;
|
||||
wr_ptr_commit_reg <= wr_ptr_temp;
|
||||
wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1);
|
||||
end
|
||||
end else if ((full_cur && DROP_WHEN_FULL) || (full_wr && DROP_OVERSIZE_FRAME) || drop_frame_reg) begin
|
||||
end else if ((full && DROP_WHEN_FULL) || (full_wr && DROP_OVERSIZE_FRAME) || drop_frame_reg) begin
|
||||
// full, packet overflow, or currently dropping frame
|
||||
// drop frame
|
||||
drop_frame_reg <= 1'b1;
|
||||
if (s_axis_tlast) begin
|
||||
// end of frame, reset write pointer
|
||||
wr_ptr_temp = wr_ptr_reg;
|
||||
wr_ptr_cur_reg <= wr_ptr_temp;
|
||||
wr_ptr_cur_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1);
|
||||
wr_ptr_temp = wr_ptr_commit_reg;
|
||||
wr_ptr_reg <= wr_ptr_temp;
|
||||
wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1);
|
||||
drop_frame_reg <= 1'b0;
|
||||
overflow_reg <= 1'b1;
|
||||
end
|
||||
end else begin
|
||||
mem[wr_ptr_cur_reg[ADDR_WIDTH-1:0]] <= s_axis;
|
||||
wr_ptr_temp = wr_ptr_cur_reg + 1;
|
||||
wr_ptr_cur_reg <= wr_ptr_temp;
|
||||
wr_ptr_cur_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1);
|
||||
mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis;
|
||||
wr_ptr_temp = wr_ptr_reg + 1;
|
||||
wr_ptr_reg <= wr_ptr_temp;
|
||||
wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1);
|
||||
if (s_axis_tlast || (!DROP_OVERSIZE_FRAME && (full_wr || send_frame_reg))) begin
|
||||
// end of frame or send frame
|
||||
send_frame_reg <= !s_axis_tlast;
|
||||
if (s_axis_tlast && DROP_BAD_FRAME && USER_BAD_FRAME_MASK & ~(s_axis_tuser ^ USER_BAD_FRAME_VALUE)) begin
|
||||
// bad packet, reset write pointer
|
||||
wr_ptr_temp = wr_ptr_reg;
|
||||
wr_ptr_cur_reg <= wr_ptr_temp;
|
||||
wr_ptr_cur_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1);
|
||||
wr_ptr_temp = wr_ptr_commit_reg;
|
||||
wr_ptr_reg <= wr_ptr_temp;
|
||||
wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1);
|
||||
bad_frame_reg <= 1'b1;
|
||||
end else begin
|
||||
// good packet or packet overflow, update write pointer
|
||||
wr_ptr_temp = wr_ptr_cur_reg + 1;
|
||||
wr_ptr_temp = wr_ptr_reg + 1;
|
||||
wr_ptr_reg <= wr_ptr_temp;
|
||||
wr_ptr_commit_reg <= wr_ptr_temp;
|
||||
wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1);
|
||||
|
||||
if (wr_ptr_update_reg == wr_ptr_update_ack_sync2_reg) begin
|
||||
// no sync in progress; sync update
|
||||
wr_ptr_update_valid_reg <= 1'b0;
|
||||
wr_ptr_sync_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1);
|
||||
wr_ptr_sync_commit_reg <= wr_ptr_temp;
|
||||
wr_ptr_update_reg <= !wr_ptr_update_ack_sync2_reg;
|
||||
end else begin
|
||||
// sync in progress; flag it for later
|
||||
@ -414,14 +416,15 @@ always @(posedge s_clk) begin
|
||||
// data valid with packet overflow
|
||||
// update write pointer
|
||||
send_frame_reg <= 1'b1;
|
||||
wr_ptr_temp = wr_ptr_cur_reg;
|
||||
wr_ptr_temp = wr_ptr_reg;
|
||||
wr_ptr_reg <= wr_ptr_temp;
|
||||
wr_ptr_commit_reg <= wr_ptr_temp;
|
||||
wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1);
|
||||
|
||||
if (wr_ptr_update_reg == wr_ptr_update_ack_sync2_reg) begin
|
||||
// no sync in progress; sync update
|
||||
wr_ptr_update_valid_reg <= 1'b0;
|
||||
wr_ptr_sync_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1);
|
||||
wr_ptr_sync_commit_reg <= wr_ptr_temp;
|
||||
wr_ptr_update_reg <= !wr_ptr_update_ack_sync2_reg;
|
||||
end else begin
|
||||
// sync in progress; flag it for later
|
||||
@ -431,10 +434,9 @@ always @(posedge s_clk) begin
|
||||
|
||||
if (s_rst_sync3_reg) begin
|
||||
wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_cur_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_commit_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_sync_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_cur_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_sync_commit_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
wr_ptr_update_valid_reg <= 1'b0;
|
||||
wr_ptr_update_reg <= 1'b0;
|
||||
@ -442,10 +444,9 @@ always @(posedge s_clk) begin
|
||||
|
||||
if (s_rst) begin
|
||||
wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_cur_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_commit_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_sync_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_cur_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_sync_commit_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
wr_ptr_update_valid_reg <= 1'b0;
|
||||
wr_ptr_update_reg <= 1'b0;
|
||||
@ -476,12 +477,11 @@ always @(posedge s_clk) begin
|
||||
end
|
||||
|
||||
always @(posedge m_clk) begin
|
||||
if (!FRAME_FIFO) begin
|
||||
wr_ptr_gray_sync1_reg <= wr_ptr_gray_reg;
|
||||
end else if (wr_ptr_update_sync2_reg ^ wr_ptr_update_sync3_reg) begin
|
||||
wr_ptr_gray_sync1_reg <= wr_ptr_sync_gray_reg;
|
||||
end
|
||||
wr_ptr_gray_sync1_reg <= wr_ptr_gray_reg;
|
||||
wr_ptr_gray_sync2_reg <= wr_ptr_gray_sync1_reg;
|
||||
if (FRAME_FIFO && wr_ptr_update_sync2_reg ^ wr_ptr_update_sync3_reg) begin
|
||||
wr_ptr_commit_sync_reg <= wr_ptr_sync_commit_reg;
|
||||
end
|
||||
wr_ptr_update_sync1_reg <= wr_ptr_update_reg;
|
||||
wr_ptr_update_sync2_reg <= wr_ptr_update_sync1_reg;
|
||||
wr_ptr_update_sync3_reg <= wr_ptr_update_sync2_reg;
|
||||
@ -493,6 +493,7 @@ always @(posedge m_clk) begin
|
||||
if (m_rst) begin
|
||||
wr_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_commit_sync_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_update_sync1_reg <= 1'b0;
|
||||
wr_ptr_update_sync2_reg <= 1'b0;
|
||||
wr_ptr_update_sync3_reg <= 1'b0;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013-2021 Alex Forencich
|
||||
Copyright (c) 2013-2023 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -158,7 +158,7 @@ localparam USER_OFFSET = DEST_OFFSET + (DEST_ENABLE ? DEST_WIDTH : 0);
|
||||
localparam WIDTH = USER_OFFSET + (USER_ENABLE ? USER_WIDTH : 0);
|
||||
|
||||
reg [ADDR_WIDTH:0] wr_ptr_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_cur_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] wr_ptr_commit_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
(* ramstyle = "no_rw_check" *)
|
||||
@ -171,11 +171,10 @@ reg [RAM_PIPELINE+1-1:0] m_axis_tvalid_pipe_reg = 0;
|
||||
|
||||
// full when first MSB different but rest same
|
||||
wire full = wr_ptr_reg == (rd_ptr_reg ^ {1'b1, {ADDR_WIDTH{1'b0}}});
|
||||
wire full_cur = wr_ptr_cur_reg == (rd_ptr_reg ^ {1'b1, {ADDR_WIDTH{1'b0}}});
|
||||
// empty when pointers match exactly
|
||||
wire empty = wr_ptr_reg == rd_ptr_reg;
|
||||
wire empty = wr_ptr_commit_reg == rd_ptr_reg;
|
||||
// overflow within packet
|
||||
wire full_wr = wr_ptr_reg == (wr_ptr_cur_reg ^ {1'b1, {ADDR_WIDTH{1'b0}}});
|
||||
wire full_wr = wr_ptr_reg == (wr_ptr_commit_reg ^ {1'b1, {ADDR_WIDTH{1'b0}}});
|
||||
|
||||
reg drop_frame_reg = 1'b0;
|
||||
reg send_frame_reg = 1'b0;
|
||||
@ -183,7 +182,7 @@ reg overflow_reg = 1'b0;
|
||||
reg bad_frame_reg = 1'b0;
|
||||
reg good_frame_reg = 1'b0;
|
||||
|
||||
assign s_axis_tready = FRAME_FIFO ? (!full_cur || (full_wr && DROP_OVERSIZE_FRAME) || DROP_WHEN_FULL) : !full;
|
||||
assign s_axis_tready = FRAME_FIFO ? (!full || (full_wr && DROP_OVERSIZE_FRAME) || DROP_WHEN_FULL) : !full;
|
||||
|
||||
wire [WIDTH-1:0] s_axis;
|
||||
|
||||
@ -225,30 +224,31 @@ always @(posedge clk) begin
|
||||
// normal FIFO mode
|
||||
mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis;
|
||||
wr_ptr_reg <= wr_ptr_reg + 1;
|
||||
end else if ((full_cur && DROP_WHEN_FULL) || (full_wr && DROP_OVERSIZE_FRAME) || drop_frame_reg) begin
|
||||
wr_ptr_commit_reg <= wr_ptr_reg + 1;
|
||||
end else if ((full && DROP_WHEN_FULL) || (full_wr && DROP_OVERSIZE_FRAME) || drop_frame_reg) begin
|
||||
// full, packet overflow, or currently dropping frame
|
||||
// drop frame
|
||||
drop_frame_reg <= 1'b1;
|
||||
if (s_axis_tlast) begin
|
||||
// end of frame, reset write pointer
|
||||
wr_ptr_cur_reg <= wr_ptr_reg;
|
||||
wr_ptr_reg <= wr_ptr_commit_reg;
|
||||
drop_frame_reg <= 1'b0;
|
||||
overflow_reg <= 1'b1;
|
||||
end
|
||||
end else begin
|
||||
// store it
|
||||
mem[wr_ptr_cur_reg[ADDR_WIDTH-1:0]] <= s_axis;
|
||||
wr_ptr_cur_reg <= wr_ptr_cur_reg + 1;
|
||||
mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis;
|
||||
wr_ptr_reg <= wr_ptr_reg + 1;
|
||||
if (s_axis_tlast || (!DROP_OVERSIZE_FRAME && (full_wr || send_frame_reg))) begin
|
||||
// end of frame or send frame
|
||||
send_frame_reg <= !s_axis_tlast;
|
||||
if (s_axis_tlast && DROP_BAD_FRAME && USER_BAD_FRAME_MASK & ~(s_axis_tuser ^ USER_BAD_FRAME_VALUE)) begin
|
||||
// bad packet, reset write pointer
|
||||
wr_ptr_cur_reg <= wr_ptr_reg;
|
||||
wr_ptr_reg <= wr_ptr_commit_reg;
|
||||
bad_frame_reg <= 1'b1;
|
||||
end else begin
|
||||
// good packet or packet overflow, update write pointer
|
||||
wr_ptr_reg <= wr_ptr_cur_reg + 1;
|
||||
wr_ptr_commit_reg <= wr_ptr_reg + 1;
|
||||
good_frame_reg <= s_axis_tlast;
|
||||
end
|
||||
end
|
||||
@ -257,12 +257,12 @@ always @(posedge clk) begin
|
||||
// data valid with packet overflow
|
||||
// update write pointer
|
||||
send_frame_reg <= 1'b1;
|
||||
wr_ptr_reg <= wr_ptr_cur_reg;
|
||||
wr_ptr_commit_reg <= wr_ptr_reg;
|
||||
end
|
||||
|
||||
if (rst) begin
|
||||
wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_cur_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
wr_ptr_commit_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
drop_frame_reg <= 1'b0;
|
||||
send_frame_reg <= 1'b0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2020 Alex Forencich
|
||||
# Copyright (c) 2020-2023 Alex Forencich
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
@ -36,7 +36,8 @@ proc constrain_axis_async_fifo_inst { inst } {
|
||||
|
||||
# pointer synchronization
|
||||
set_max_delay -from [get_registers "$inst|rd_ptr_reg[*] $inst|rd_ptr_gray_reg[*]"] -to [get_registers "$inst|rd_ptr_gray_sync1_reg[*]"] 8.000
|
||||
set_max_delay -from [get_registers "$inst|wr_ptr_reg[*] $inst|wr_ptr_gray_reg[*] $inst|wr_ptr_sync_gray_reg[*]"] -to [get_registers "$inst|wr_ptr_gray_sync1_reg[*]"] 8.000
|
||||
set_max_delay -from [get_registers "$inst|wr_ptr_reg[*] $inst|wr_ptr_gray_reg[*]"] -to [get_registers "$inst|wr_ptr_gray_sync1_reg[*]"] 8.000
|
||||
set_max_delay -from [get_registers "$inst|wr_ptr_sync_commit_reg[*]"] -to [get_registers "$inst|wr_ptr_commit_sync_reg[*]"] 8.000
|
||||
|
||||
# frame FIFO pointer update synchronization
|
||||
set_max_delay -from [get_registers "$inst|wr_ptr_update_reg"] -to [get_registers "$inst|wr_ptr_update_sync1_reg"] 8.000
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2021 Alex Forencich
|
||||
# Copyright (c) 2021-2023 Alex Forencich
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
@ -37,8 +37,10 @@ proc constrain_axis_async_fifo_inst { inst } {
|
||||
# pointer synchronization
|
||||
set_data_delay -from [get_registers "$inst|rd_ptr_reg[*] $inst|rd_ptr_gray_reg[*]"] -to [get_registers "$inst|rd_ptr_gray_sync1_reg[*]"] -override -get_value_from_clock_period dst_clock_period -value_multiplier 0.8
|
||||
set_max_skew -from [get_keepers "$inst|rd_ptr_reg[*] $inst|rd_ptr_gray_reg[*]"] -to [get_keepers "$inst|rd_ptr_gray_sync1_reg[*]"] -get_skew_value_from_clock_period min_clock_period -skew_value_multiplier 0.8
|
||||
set_data_delay -from [get_registers "$inst|wr_ptr_reg[*] $inst|wr_ptr_gray_reg[*] $inst|wr_ptr_sync_gray_reg[*]"] -to [get_registers "$inst|wr_ptr_gray_sync1_reg[*]"] -override -get_value_from_clock_period dst_clock_period -value_multiplier 0.8
|
||||
set_max_skew -from [get_keepers "$inst|wr_ptr_reg[*] $inst|wr_ptr_gray_reg[*] $inst|wr_ptr_sync_gray_reg[*]"] -to [get_keepers "$inst|wr_ptr_gray_sync1_reg[*]"] -get_skew_value_from_clock_period min_clock_period -skew_value_multiplier 0.8
|
||||
set_data_delay -from [get_registers "$inst|wr_ptr_reg[*] $inst|wr_ptr_gray_reg[*]"] -to [get_registers "$inst|wr_ptr_gray_sync1_reg[*]"] -override -get_value_from_clock_period dst_clock_period -value_multiplier 0.8
|
||||
set_max_skew -from [get_keepers "$inst|wr_ptr_reg[*] $inst|wr_ptr_gray_reg[*]"] -to [get_keepers "$inst|wr_ptr_gray_sync1_reg[*]"] -get_skew_value_from_clock_period min_clock_period -skew_value_multiplier 0.8
|
||||
set_data_delay -from [get_registers "$inst|wr_ptr_sync_commit_reg[*]"] -to [get_registers "$inst|wr_ptr_commit_sync_reg[*]"] -override -get_value_from_clock_period dst_clock_period -value_multiplier 0.8
|
||||
set_max_skew -from [get_keepers "$inst|wr_ptr_sync_commit_reg[*]"] -to [get_keepers "$inst|wr_ptr_commit_sync_reg[*]"] -get_skew_value_from_clock_period min_clock_period -skew_value_multiplier 0.8
|
||||
|
||||
# frame FIFO pointer update synchronization
|
||||
set_data_delay -from [get_registers "$inst|wr_ptr_update_reg"] -to [get_registers "$inst|wr_ptr_update_sync1_reg"] -override -get_value_from_clock_period dst_clock_period -value_multiplier 0.8
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2019 Alex Forencich
|
||||
# Copyright (c) 2019-2023 Alex Forencich
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
@ -78,8 +78,17 @@ foreach fifo_inst [get_cells -hier -filter {(ORIG_REF_NAME == axis_async_fifo ||
|
||||
if {[llength $sync_ffs]} {
|
||||
set_property ASYNC_REG TRUE $sync_ffs
|
||||
|
||||
set_max_delay -from [get_cells -quiet "$fifo_inst/wr_ptr_reg_reg[*] $fifo_inst/wr_ptr_gray_reg_reg[*] $fifo_inst/wr_ptr_sync_gray_reg_reg[*]"] -to [get_cells "$fifo_inst/wr_ptr_gray_sync1_reg_reg[*]"] -datapath_only $write_clk_period
|
||||
set_bus_skew -from [get_cells -quiet "$fifo_inst/wr_ptr_reg_reg[*] $fifo_inst/wr_ptr_gray_reg_reg[*] $fifo_inst/wr_ptr_sync_gray_reg_reg[*]"] -to [get_cells "$fifo_inst/wr_ptr_gray_sync1_reg_reg[*]"] $read_clk_period
|
||||
set_max_delay -from [get_cells -quiet "$fifo_inst/wr_ptr_reg_reg[*] $fifo_inst/wr_ptr_gray_reg_reg[*]"] -to [get_cells "$fifo_inst/wr_ptr_gray_sync1_reg_reg[*]"] -datapath_only $write_clk_period
|
||||
set_bus_skew -from [get_cells -quiet "$fifo_inst/wr_ptr_reg_reg[*] $fifo_inst/wr_ptr_gray_reg_reg[*]"] -to [get_cells "$fifo_inst/wr_ptr_gray_sync1_reg_reg[*]"] $read_clk_period
|
||||
}
|
||||
|
||||
set sync_ffs [get_cells -quiet -hier -regexp ".*/wr_ptr_commit_sync_reg_reg\\\[\\d+\\\]" -filter "PARENT == $fifo_inst"]
|
||||
|
||||
if {[llength $sync_ffs]} {
|
||||
set_property ASYNC_REG TRUE $sync_ffs
|
||||
|
||||
set_max_delay -from [get_cells -quiet "$fifo_inst/wr_ptr_sync_commit_reg_reg[*]"] -to [get_cells "$fifo_inst/wr_ptr_commit_sync_reg_reg[*]"] -datapath_only $write_clk_period
|
||||
set_bus_skew -from [get_cells -quiet "$fifo_inst/wr_ptr_sync_commit_reg_reg[*]"] -to [get_cells "$fifo_inst/wr_ptr_commit_sync_reg_reg[*]"] $read_clk_period
|
||||
}
|
||||
|
||||
# output register (needed for distributed RAM sync write/async read)
|
||||
|
Loading…
x
Reference in New Issue
Block a user