module altera_fpgaloader(
  wb_clk_i,
  wb_we_i,
  wb_adr_i,
  wb_dat_i,
  wb_dat_o,
  wb_cyc_i,
  wb_stb_i,
  wb_ack_o,

  data0_o,
  dclk_o,
  config_o,
  conf_done_i
);

input wb_clk_i;
input wb_we_i;
input wb_cyc_i;
input wb_stb_i;
input wb_adr_i;
input conf_done_i;
input [7:0] wb_dat_i;

output [7:0] wb_dat_o;
output reg data0_o;
output dclk_o;
output reg config_o;
output wb_ack_o;

wire data0_stb = wb_cyc_i && wb_stb_i && wb_adr_i == 1'b0 && wb_we_i;
wire ser_busy, datashifter_busy, ser_o;
/* Altera serial configuration stream is sent LSB first */
wire [7:0] wb_dat_i_bitreversed = {wb_dat_i[0], wb_dat_i[1], wb_dat_i[2], 
  wb_dat_i[3], wb_dat_i[4], wb_dat_i[5], wb_dat_i[6], wb_dat_i[7]};
ssp datashifter(
  .clk_i(wb_clk_i),
  .ser_clken_i(ser_busy),
  .parallel_clken_i(data0_stb),
  .direction_i(1'b1),
  .parallel_busy_o(datashifter_busy),
  .ser_busy_o(ser_busy),
  .ser_o(ser_o),
  .parallel_i(wb_dat_i_bitreversed),
  .quadbit_i(1'b0),
  .reset_i(1'b0)
);

assign wb_dat_o = { 5'bxxxxx, conf_done_i, config_o, datashifter_busy };
assign wb_ack_o = wb_stb_i && wb_cyc_i;
assign dclk_o = wb_clk_i || !ser_busy;

always @(posedge wb_clk_i) begin
  if (wb_cyc_i && wb_stb_i && wb_we_i && wb_adr_i) begin
    config_o <= wb_dat_i[1];
  end
end

always @(negedge wb_clk_i) begin
  data0_o <= ser_o;
end

endmodule
