module wb_buf(
  wb_clk_i,
  wb_rst_i,

  wbs_adr_i,
  wbs_cyc_i,
  wbs_stb_i,
  wbs_we_i,
  wbs_dat_i,
  wbs_dat_o,
  wbs_ack_o,
  wbs_sel_i,

  wbm_cyc_o,
  wbm_stb_o,
  wbm_we_o,
  wbm_dat_o,
  wbm_dat_i,
  wbm_adr_o,
  wbm_ack_i,
  wbm_sel_o
);

input wb_clk_i, wb_rst_i, wbs_cyc_i, wbs_stb_i, wbs_we_i, wbm_ack_i;
output [31:0] wbs_dat_o, wbm_dat_o, wbm_adr_o;
input [31:0] wbs_dat_i, wbm_dat_i, wbs_adr_i;
output wbs_ack_o, wbm_cyc_o, wbm_stb_o, wbm_we_o;
output [3:0] wbm_sel_o;
input [3:0] wbs_sel_i;

reg ack, we, cyc;
reg [31:0] idat, odat, adr;
reg [3:0] sel;
assign wbs_ack_o = ack;
assign wbs_dat_o = idat;
assign wbm_dat_o = odat;
assign wbm_cyc_o = cyc;
assign wbm_stb_o = cyc;
assign wbm_adr_o = adr;
assign wbm_sel_o = sel;
assign wbm_we_o = we;
always @(posedge wb_clk_i or posedge wb_rst_i) begin
  if (wb_rst_i) begin
    sel <= 4'd0;
    ack <= 1'b0;
    we <= 1'b0;
    cyc <= 1'b0;
    idat <= 32'd0;
    odat <= 32'd0;
    adr <= 32'd0;
  end else begin
    ack <= 1'b0;
    if (wbs_cyc_i && wbs_stb_i && !cyc && !ack) begin
      adr <= wbs_adr_i;
      odat <= wbs_dat_i;
      we <= wbs_we_i;
      cyc <= 1'b1;
      sel <= wbs_sel_i;
    end
    if (cyc && wbm_ack_i) begin
      cyc <= 1'b0;
      ack <= 1'b1;
      idat <= wbm_dat_i;
    end
  end
end

endmodule


module wb_readbuf(
  wb_clk_i,
  wb_rst_i,

  wbs_cyc_i,
  wbs_stb_i,
  wbs_we_i,
  wbs_dat_i,
  wbs_dat_o,
  wbs_ack_o,

  wbm_cyc_o,
  wbm_stb_o,
  wbm_we_o,
  wbm_dat_o,
  wbm_dat_i,
  wbm_ack_i
);

input wb_clk_i, wb_rst_i, wbs_cyc_i, wbs_stb_i, wbs_we_i, wbm_ack_i;
output [31:0] wbs_dat_o, wbm_dat_o;
input [31:0] wbs_dat_i, wbm_dat_i;
output wbs_ack_o, wbm_cyc_o, wbm_stb_o, wbm_we_o;

reg ack /* synthesis syn_maxfan=1 */;
reg [31:0] dat;
assign wbm_cyc_o = wbs_cyc_i && !ack;
assign wbm_stb_o = wbs_stb_i && !ack;
assign wbm_we_o = wbs_we_i;
assign wbm_dat_o = wbs_dat_i;
assign wbs_ack_o = wbs_we_i ? wbm_ack_i : ack;
assign wbs_dat_o = dat;
always @(posedge wb_clk_i or posedge wb_rst_i) begin
  if (wb_rst_i) begin
    ack <= 1'b0;
    dat <= 32'd0;
  end else begin
    ack <= 1'b0;
    if (wbm_cyc_o && wbm_stb_o && wbm_ack_i && !wbm_we_o) begin
      dat <= wbm_dat_i;
      ack <= 1'b1;
    end
  end
end

endmodule
