📄 pci_delayed_sync.v
字号:
) ;
// wire for clearing completion side request flag - whenever completion or retry expired are signalled
wire comp_req_pending_clear = comp_req_pending && ( comp_in || retry_expired_in) ;
// wire for enabling request flip - flop - it is enabled when completion is not active and done is not active
wire comp_req_pending_ena = ~comp_comp_pending && ~comp_done_reg_main && ~comp_rty_exp_reg ;
// completion side request flip flop - gets a value from intermediate stage sync flip flop
always@(posedge comp_clk_in or posedge reset_in)
begin
if ( reset_in )
comp_req_pending <= #`FF_DELAY 1'b0 ;
else
if ( comp_req_pending_clear )
comp_req_pending <= #`FF_DELAY 1'b0 ;
else
if ( comp_req_pending_ena )
comp_req_pending <= #`FF_DELAY sync_comp_req_pending ;
end
// completion side request output assignment - when request ff is set and completion ff is not set
assign comp_req_pending_out = comp_req_pending ;
// requesting side request pending output
assign req_req_pending_out = req_req_pending ;
/*=================================================================================================================================
Passing of completions between clock domains:
completion originates on completing side. It's then synchronized with two flip-flops to cross to requesting clock domain
=================================================================================================================================*/
// main completion Flip - Flop - triggered by completing side's clock
// completion side completion pending flag is cleared when done flag propagates through clock domains
wire comp_comp_clear = comp_done_reg_main && ~comp_done_reg_clr ;
always@(posedge comp_clk_in or posedge reset_in)
begin
if ( reset_in )
comp_comp_pending <= #`FF_DELAY 1'b0 ;
else
if ( comp_comp_clear )
comp_comp_pending <= #`FF_DELAY 1'b0 ;
else
if ( comp_in && comp_req_pending )
comp_comp_pending <= #`FF_DELAY 1'b1 ;
end
assign comp_comp_pending_out = comp_comp_pending ;
// interemediate stage completion synchronization flip - flop - this one is prone to metastability
pci_synchronizer_flop #(1, 0) comp_sync
(
.data_in (comp_comp_pending),
.clk_out (req_clk_in),
.sync_data_out (sync_req_comp_pending),
.async_reset (reset_in)
) ;
// request side completion pending flip flop is cleared whenever done is signalled or completion counter expires - 2^^16 clock cycles
wire req_comp_pending_clear = done_in || comp_cycle_count[16];
// request side completion pending flip flop is disabled while done flag is set
wire req_comp_pending_ena = ~req_done_reg ;
// request side completion flip flop - gets a value from intermediate stage sync flip flop
always@(posedge req_clk_in or posedge reset_in)
begin
if ( reset_in )
req_comp_pending <= #`FF_DELAY 1'b0 ;
else
if ( req_comp_pending_clear )
req_comp_pending <= #`FF_DELAY 1'b0 ;
else
if ( req_comp_pending_ena )
req_comp_pending <= #`FF_DELAY sync_req_comp_pending ;
end
// sampling FF - used for sampling incoming completion flag from completing side
always@(posedge req_clk_in or posedge reset_in)
begin
if ( reset_in )
req_comp_pending_sample <= #`FF_DELAY 1'b0 ;
else
req_comp_pending_sample <= #`FF_DELAY sync_req_comp_pending ;
end
// requesting side completion pending output assignment
assign req_comp_pending_out = req_comp_pending && ~req_req_pending ;
/*==================================================================================================================================
Passing of delayed transaction done signal between clock domains.
Done is signalled by requesting side of the bridge and is passed to completing side of the bridge
==================================================================================================================================*/
// main done flip-flop triggered on requesting side's clock
// when completing side removes completion flag, done flag is also removed, so requests can proceede
wire req_done_clear = ~req_comp_pending_sample ;
always@(posedge req_clk_in or posedge reset_in)
begin
if ( reset_in )
req_done_reg <= #`FF_DELAY 1'b0 ;
else
if ( req_done_clear )
req_done_reg <= #`FF_DELAY 1'b0 ;
else
if ( done_in || comp_cycle_count[16] )
req_done_reg <= #`FF_DELAY 1'b1 ;
end
pci_synchronizer_flop #(1, 0) done_sync
(
.data_in (req_done_reg),
.clk_out (comp_clk_in),
.sync_data_out (sync_comp_done),
.async_reset (reset_in)
) ;
always@(posedge comp_clk_in or posedge reset_in)
begin
if ( reset_in )
comp_done_reg_main <= #`FF_DELAY 1'b0 ;
else
comp_done_reg_main <= #`FF_DELAY sync_comp_done ;
end
always@(posedge comp_clk_in or posedge reset_in)
begin
if ( reset_in )
comp_done_reg_clr <= #`FF_DELAY 1'b0 ;
else
comp_done_reg_clr <= #`FF_DELAY comp_done_reg_main ;
end
/*=================================================================================================================================
Passing of retry expired signal between clock domains
Retry expiration originates on completing side. It's then synchronized with two flip-flops to cross to requesting clock domain
=================================================================================================================================*/
// main retry expired Flip - Flop - triggered by completing side's clock
wire comp_rty_exp_clear = comp_rty_exp_clr && comp_rty_exp_reg ;
// retry expired is a special case of transaction removal - retry expired propagates from completing
// clock domain to requesting clock domain to remove all pending requests and than propagates back
// to completing side to qualify valid new requests
always@(posedge comp_clk_in or posedge reset_in)
begin
if ( reset_in )
comp_rty_exp_reg <= #`FF_DELAY 1'b0 ;
else
if ( comp_rty_exp_clear )
comp_rty_exp_reg <= #`FF_DELAY 1'b0 ;
else
if ( retry_expired_in && comp_req_pending)
comp_rty_exp_reg <= #`FF_DELAY 1'b1 ;
end
// interemediate stage retry expired synchronization flip - flop - this one is prone to metastability
pci_synchronizer_flop #(1, 0) rty_exp_sync
(
.data_in (comp_rty_exp_reg),
.clk_out (req_clk_in),
.sync_data_out (sync_req_rty_exp),
.async_reset (reset_in)
) ;
// request retry expired flip flop - gets a value from intermediate stage sync flip flop
always@(posedge req_clk_in or posedge reset_in)
begin
if ( reset_in )
req_rty_exp_reg <= #`FF_DELAY 1'b0 ;
else
req_rty_exp_reg <= #`FF_DELAY sync_req_rty_exp ;
end
always@(posedge req_clk_in or posedge reset_in)
begin
if ( reset_in )
req_rty_exp_clr <= #`FF_DELAY 1'b0 ;
else
req_rty_exp_clr <= #`FF_DELAY req_rty_exp_reg ;
end
pci_synchronizer_flop #(1, 0) rty_exp_back_prop_sync
(
.data_in (req_rty_exp_reg && req_rty_exp_clr),
.clk_out (comp_clk_in),
.sync_data_out (sync_comp_rty_exp_clr),
.async_reset (reset_in)
) ;
always@(posedge comp_clk_in or posedge reset_in)
begin
if ( reset_in )
comp_rty_exp_clr <= #`FF_DELAY 1'b0 ;
else
comp_rty_exp_clr <= #`FF_DELAY sync_comp_rty_exp_clr ;
end
// completion status flip flop - if 0 when completion is signalled it's finished OK otherwise it means error
reg status_out ;
always@(posedge comp_clk_in or posedge reset_in)
begin
if (reset_in)
status_out <= #`FF_DELAY 1'b0 ;
else
if (comp_in && comp_req_pending)
status_out <= #`FF_DELAY status_in ;
end
// clocks counter - it counts how many clock cycles completion is present without beeing repeated
// if it counts to 2^^16 cycles the completion must be ditched
// wire for clearing this counter
wire clear_count = in_progress_in || ~req_comp_pending_out || comp_cycle_count[16] ;
always@(posedge req_clk_in or posedge reset_in)
begin
if (reset_in)
comp_cycle_count <= #`FF_DELAY 17'h0_0000 ;
else
if (clear_count)
comp_cycle_count <= #`FF_DELAY 17'h0_0000 ;
else
comp_cycle_count <= #`FF_DELAY comp_cycle_count + 1'b1 ;
end
// completion flush output - used for flushing fifos when counter expires
// if counter doesn't expire, fifo flush is up to WISHBONE slave or PCI target state machines
reg comp_flush_out ;
always@(posedge req_clk_in or posedge reset_in)
begin
if (reset_in)
comp_flush_out <= #`FF_DELAY 1'b0 ;
else
comp_flush_out <= #`FF_DELAY comp_cycle_count[16] ;
end
endmodule //delayed_sync
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -