blob: c1929d4501376b5b3d00f15dbc481211d10c5098 [file] [log] [blame]
/****************************************************************************
* wb_clockdomain_bridge.v
*
*
****************************************************************************/
`include "wishbone_macros.svh"
/**
* Module: wb_clockdomain_bridge
*
* TODO: Add module documentation
*/
module wb_clockdomain_bridge #(
parameter ADR_WIDTH = 32,
parameter DAT_WIDTH = 32
) (
input reset,
input i_clock,
`WB_TARGET_PORT(i_, ADR_WIDTH, DAT_WIDTH),
input t_clock,
`WB_INITIATOR_PORT(t_, ADR_WIDTH, DAT_WIDTH)
);
// request path
// response path
reg[DAT_WIDTH-1:0] dat_r0, dat_r1, dat_r2;
reg[DAT_WIDTH-1:0] dat_w0, dat_w1, dat_w2;
reg[ADR_WIDTH-1:0] adr0, adr1, adr2;
reg we0, we1, we2;
reg[DAT_WIDTH/8-1:0] sel0, sel1, sel2;
reg req0, req1, req2;
wire req_i;
wire ack_i;
reg ack0, ack1, ack2;
// reg ack_ack0, ack_ack1, ack_ack2;
reg[1:0] i_state;
reg[1:0] t_state;
// Initiator-clocked block
// - Handles last two stages of dat_r
`ifdef FW_RESET_ASYNC
always @(posedge i_clock or posedge reset) begin
`else
always @(posedge i_clock) begin
`endif
if (reset) begin
dat_r0 <= {32{1'b0}};
dat_r1 <= {32{1'b0}};
adr2 <= {ADR_WIDTH{1'b0}};
dat_w2 <= {DAT_WIDTH{1'b0}};
sel0 <= {DAT_WIDTH/8{1'b0}};
we0 <= 1'b0;
ack2 <= 1'b0;
ack1 <= 1'b0;
req0 <= 1'b0;
i_state <= 2'b0;
end else begin
dat_r0 <= dat_r1;
dat_r1 <= dat_r2;
adr2 <= i_adr;
dat_w2 <= i_dat_w;
sel0 <= i_sel;
we0 <= i_we;
ack2 <= ack1;
ack1 <= ack0;
req0 <= req_i;
case (i_state)
0: begin // Waiting for a i->t request
if (i_cyc && i_stb) begin
i_state <= 1;
end
end
1: begin // Waiting for an acknowledge
if (ack2) begin
i_state <= 2;
end
end
2: begin
// Wait for the ack to be dropped before
// accepting another request
if (!ack2) begin
i_state <= 0;
end
end
default: i_state <= 0;
endcase
end
end
assign req_i = ((i_state == 0 && i_cyc && i_stb) | i_state == 1);
assign i_ack = (i_state == 1 && ack2);
assign i_dat_r = dat_r0;
// Target-clocked block
// - Handles last two stages of adr, dat_w
// - Handles first stage of dat_r
`ifdef FW_RESET_ASYNC
always @(posedge t_clock or posedge reset) begin
`else
always @(posedge t_clock) begin
`endif
if (reset) begin
dat_w0 <= {32{1'b0}};
dat_w1 <= {32{1'b0}};
dat_r2 <= {32{1'b0}};
adr0 <= {32{1'b0}};
adr1 <= {32{1'b0}};
ack0 <= 1'b0;
sel2 <= {DAT_WIDTH/8{1'b0}};
sel1 <= {DAT_WIDTH/8{1'b0}};
we2 <= 1'b0;
we1 <= 1'b0;
req2 <= 1'b0;
req1 <= 1'b0;
t_state <= 2'b00;
end else begin
dat_w0 <= dat_w1;
dat_w1 <= dat_w2;
dat_r2 <= t_dat_r;
adr0 <= adr1;
adr1 <= adr2;
sel2 <= sel1;
sel1 <= sel0;
we2 <= we1;
we1 <= we0;
req2 <= req1;
req1 <= req0;
ack0 <= ack_i;
case (t_state)
0: begin // Waiting for a request
if (req2) begin
t_state <= 1;
end
end
1: begin // Waiting for an acknowledge
if (t_ack) begin
t_state <= 2;
end
end
2: begin
// Ensure that req is dropped before proceeding
if (!req2) begin
t_state <= 0;
end
end
default: t_state <= 0;
endcase
end
end
assign ack_i = ((t_ack && t_state == 1) || t_state == 2);
assign t_adr = adr2;
assign t_dat_w = dat_w2;
assign t_cyc = (req2 && (t_state == 0 || t_state == 1));
assign t_stb = (req2 && (t_state == 0 || t_state == 1));
assign t_sel = sel2;
assign t_we = we2;
endmodule