Line 93... |
Line 93... |
`define MBOOT_READ 5'h06
|
`define MBOOT_READ 5'h06
|
`define MBOOT_WRITE 5'h0f
|
`define MBOOT_WRITE 5'h0f
|
`define MBOOT_DESYNC 5'h11
|
`define MBOOT_DESYNC 5'h11
|
module wbicapetwo(i_clk,
|
module wbicapetwo(i_clk,
|
i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
|
i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
|
o_wb_ack, o_wb_stall, o_wb_data);
|
o_wb_ack, o_wb_stall, o_wb_data, o_dbg);
|
input i_clk;
|
input i_clk;
|
// Wishbone inputs
|
// Wishbone inputs
|
input i_wb_cyc, i_wb_stb, i_wb_we;
|
input i_wb_cyc, i_wb_stb, i_wb_we;
|
input [4:0] i_wb_addr;
|
input [4:0] i_wb_addr;
|
input [31:0] i_wb_data;
|
input [31:0] i_wb_data;
|
// Wishbone outputs
|
// Wishbone outputs
|
output reg o_wb_ack, o_wb_stall;
|
output reg o_wb_ack, o_wb_stall;
|
output reg [31:0] o_wb_data;
|
output reg [31:0] o_wb_data;
|
|
// Debugging output
|
|
output wire [31:0] o_dbg;
|
// ICAPE2 interface signals
|
// ICAPE2 interface signals
|
// These are kept internal to this block ...
|
// These are kept internal to this block ...
|
|
|
reg wb_req, r_we;
|
reg wb_req, r_we;
|
reg [31:0] r_data;
|
reg [31:0] r_data;
|
reg [4:0] r_addr;
|
reg [4:0] r_addr;
|
|
|
reg slow_clk;
|
`ifdef DIVIDE_BY_FOUR
|
|
reg [1:0] slow_clk_counter;
|
|
reg clk_stb, clk_stall;
|
|
wire slow_clk;
|
|
always @(posedge i_clk)
|
|
begin
|
|
slow_clk <= slow_clk + 2'b01;
|
|
// We'll move on the positive edge of the clock, so therefore
|
|
// clk_stb must be true one clock before that, so we test for
|
|
// it one clock before that.
|
|
clk_stb <= (slow_clk_counter == 2'b10);
|
|
// CLK_STALL is set to true two clocks before any cycle that
|
|
// will, by necessity, stall.
|
|
clk_stall <= (slow_clk_counter != 2'b01);
|
|
end
|
|
|
|
assign slow_clk = slow_clk_counter[1];
|
|
`else
|
|
reg slow_clk, clk_stb, clk_stall;
|
|
always @(posedge i_clk)
|
|
begin
|
|
slow_clk <= (slow_clk + 1'b1);
|
|
// We'll move on the positive edge of the clock, so therefore
|
|
// clk_stb must be true one clock before that, so we test for
|
|
// it one clock before that.
|
|
clk_stb <= (slow_clk == 1'b1);
|
|
// CLK_STALL is set to true two clocks before any cycle that
|
|
// will, by necessity, stall.
|
|
clk_stall <= (slow_clk != 1'b0); //True all but one clock
|
|
end
|
|
`endif
|
|
|
reg [31:0] cfg_in;
|
reg [31:0] cfg_in;
|
reg cfg_cs_n, cfg_rdwrn;
|
reg cfg_cs_n, cfg_rdwrn;
|
wire [31:0] cfg_out;
|
wire [31:0] cfg_out;
|
reg [4:0] state;
|
reg [4:0] state;
|
initial state = `MBOOT_IDLE;
|
initial state = `MBOOT_IDLE;
|
initial cfg_cs_n = 1'b1;
|
initial cfg_cs_n = 1'b1;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
begin
|
begin
|
|
// In general, o_wb_ack is always zero. The exceptions to this
|
|
// will be handled individually below.
|
o_wb_ack <= 1'b0;
|
o_wb_ack <= 1'b0;
|
|
// We can simplify our logic a touch by always setting
|
|
// o_wb_data. It will only be examined if o_wb_ack
|
|
// is also true, so this is okay.
|
|
o_wb_data <= cfg_out;
|
|
|
// Turn any request "off", so that it will not be ack'd, if
|
// Turn any request "off", so that it will not be ack'd, if
|
// the wb_cyc line is ever lowered.
|
// the wb_cyc line is ever lowered.
|
wb_req <= wb_req & i_wb_cyc;
|
wb_req <= wb_req & i_wb_cyc;
|
slow_clk <= slow_clk ^ 1'b1;
|
o_wb_stall <= (state != `MBOOT_IDLE)||(clk_stall);
|
o_wb_stall <= (state != `MBOOT_IDLE)&&(slow_clk);
|
if (clk_stb)
|
if (~slow_clk)
|
|
begin
|
begin
|
state <= state + 5'h01;
|
state <= state + 5'h01;
|
case(state)
|
case(state)
|
`MBOOT_IDLE: begin
|
`MBOOT_IDLE: begin
|
cfg_cs_n <= 1'b1;
|
cfg_cs_n <= 1'b1;
|
Line 140... |
Line 179... |
o_wb_ack <= 1'b0;
|
o_wb_ack <= 1'b0;
|
|
|
r_addr <= i_wb_addr;
|
r_addr <= i_wb_addr;
|
r_data <= i_wb_data;
|
r_data <= i_wb_data;
|
r_we <= i_wb_we;
|
r_we <= i_wb_we;
|
if(i_wb_stb)
|
if(i_wb_stb) // &&(!o_wb_stall)
|
begin
|
begin
|
state <= `MBOOT_START;
|
state <= `MBOOT_START;
|
wb_req <= 1'b1;
|
wb_req <= 1'b1;
|
//
|
//
|
o_wb_ack <= 1'b0;
|
o_wb_ack <= 1'b0;
|
end end
|
end end
|
`MBOOT_START: cfg_in <= 32'hffffffff; // NOOP
|
`MBOOT_START: begin
|
|
cfg_in <= 32'hffffffff; // NOOP
|
|
cfg_cs_n <= 1'b1;
|
|
end
|
5'h02: begin
|
5'h02: begin
|
cfg_cs_n <= 1'b0; // Activate interface
|
cfg_cs_n <= 1'b0; // Activate interface
|
cfg_rdwrn <= 1'b0;
|
cfg_rdwrn <= 1'b0;
|
cfg_in <= 32'h20000000; // NOOP
|
cfg_in <= 32'h20000000; // NOOP
|
end
|
end
|
5'h03: cfg_in <= 32'haa995566; // Sync word
|
5'h03: begin
|
5'h04: cfg_in <= 32'h20000000; // NOOP
|
cfg_in <= 32'haa995566; // Sync word
|
|
cfg_cs_n <= 1'b0;
|
|
end
|
|
5'h04: begin
|
|
cfg_in <= 32'h20000000; // NOOP
|
|
cfg_cs_n <= 1'b0;
|
|
end
|
5'h05: begin
|
5'h05: begin
|
cfg_in <= 32'h20000000; // NOOP
|
cfg_in <= 32'h20000000; // NOOP
|
state <= (r_we) ? `MBOOT_WRITE : `MBOOT_READ;
|
state <= (r_we) ? `MBOOT_WRITE : `MBOOT_READ;
|
|
cfg_cs_n <= 1'b0;
|
|
end
|
|
`MBOOT_READ: begin
|
|
cfg_cs_n <= 1'b0;
|
|
cfg_in <= { 8'h28, 6'h0, r_addr, 13'h001 };
|
|
end
|
|
5'h07: begin
|
|
cfg_cs_n <= 1'b0;
|
|
cfg_in <= 32'h20000000; // NOOP
|
|
end
|
|
5'h08: begin
|
|
cfg_cs_n <= 1'b0;
|
|
cfg_in <= 32'h20000000; // NOOP
|
end
|
end
|
`MBOOT_READ: cfg_in <= { 8'h28, 6'h0, r_addr, 13'h001 };
|
|
5'h07: cfg_in <= 32'h20000000; // NOOP
|
|
5'h08: cfg_in <= 32'h20000000; // NOOP
|
|
5'h09: begin // Idle the interface before the read cycle
|
5'h09: begin // Idle the interface before the read cycle
|
cfg_cs_n <= 1'b1;
|
cfg_cs_n <= 1'b1;
|
cfg_rdwrn <= 1'b1;
|
cfg_rdwrn <= 1'b1;
|
cfg_in <= 32'h20000000; // NOOP
|
cfg_in <= 32'h20000000; // NOOP
|
end
|
end
|
5'h0a: begin // Re-activate the interface and wait 3 cycles
|
5'h0a: begin // Re-activate the interface and wait 3 cycles
|
cfg_cs_n <= 1'b0;
|
cfg_cs_n <= 1'b0;
|
cfg_rdwrn <= 1'b1;
|
cfg_rdwrn <= 1'b1;
|
cfg_in <= 32'h20000000; // NOOP
|
cfg_in <= 32'h20000000; // NOOP
|
end
|
end
|
5'h0b: // ... still waiting, cycle two
|
5'h0b: begin // ... still waiting, cycle two
|
cfg_in <= 32'h20000000; // NOOP
|
cfg_in <= 32'h20000000; // NOOP
|
5'h0c: // ... still waiting, cycle three
|
cfg_cs_n <= 1'b0;
|
|
end
|
|
5'h0c: begin // ... still waiting, cycle three
|
cfg_in <= 32'h20000000; // NOOP
|
cfg_in <= 32'h20000000; // NOOP
|
5'h0d: // ... still waiting, cycle four
|
cfg_cs_n <= 1'b0;
|
|
end
|
|
5'h0d: begin // ... still waiting, cycle four
|
cfg_in <= 32'h20000000; // NOOP
|
cfg_in <= 32'h20000000; // NOOP
|
|
cfg_cs_n <= 1'b0;
|
|
end
|
5'h0e: begin // and now our answer is there
|
5'h0e: begin // and now our answer is there
|
cfg_cs_n <= 1'b1;
|
cfg_cs_n <= 1'b1;
|
cfg_rdwrn <= 1'b1;
|
cfg_rdwrn <= 1'b1;
|
cfg_in <= 32'h20000000; // NOOP
|
cfg_in <= 32'h20000000; // NOOP
|
//
|
//
|
// Wishbone return
|
// Wishbone return
|
o_wb_ack <= wb_req;
|
o_wb_ack <= wb_req;
|
o_wb_data <= cfg_out;
|
// o_wb_data <= cfg_out; // Independent of state
|
wb_req <= 1'b0;
|
wb_req <= 1'b0;
|
//
|
//
|
state <= `MBOOT_DESYNC;
|
state <= `MBOOT_DESYNC;
|
end
|
end
|
`MBOOT_WRITE: // Issue a write command to the given address
|
`MBOOT_WRITE: begin
|
|
// Issue a write command to the given address
|
cfg_in <= { 8'h30, 6'h0, r_addr, 13'h001 };
|
cfg_in <= { 8'h30, 6'h0, r_addr, 13'h001 };
|
5'h10: cfg_in <= r_data; // Write the value
|
cfg_cs_n <= 1'b0;
|
|
end
|
|
5'h10: begin
|
|
cfg_in <= r_data; // Write the value
|
|
cfg_cs_n <= 1'b0;
|
|
end
|
`MBOOT_DESYNC: begin
|
`MBOOT_DESYNC: begin
|
cfg_cs_n <= 1'b0;
|
cfg_cs_n <= 1'b0;
|
cfg_rdwrn <= 1'b0;
|
cfg_rdwrn <= 1'b0;
|
cfg_in <= 32'h20000000; // 1st NOOP
|
cfg_in <= 32'h20000000; // 1st NOOP
|
end
|
end
|
5'h12: cfg_in <= 32'h20000000; // 2nd NOOP
|
5'h12: begin
|
5'h13: cfg_in <= 32'h30008001; // Write to CMD register
|
cfg_cs_n <= 1'b0;
|
5'h14: cfg_in <= 32'h0000000d; // DESYNC command
|
cfg_in <= 32'h20000000; // 2nd NOOP
|
5'h15: cfg_in <= 32'h20000000; // NOOP
|
end
|
5'h16: cfg_in <= 32'h20000000; // NOOP
|
5'h13: begin
|
|
cfg_cs_n <= 1'b0;
|
|
cfg_in <= 32'h30008001; // Write to CMD register
|
|
end
|
|
5'h14: begin
|
|
cfg_cs_n <= 1'b0;
|
|
cfg_in <= 32'h0000000d; // DESYNC command
|
|
end
|
|
5'h15: begin
|
|
cfg_cs_n <= 1'b0;
|
|
cfg_in <= 32'h20000000; // NOOP
|
|
end
|
|
5'h16: begin
|
|
cfg_cs_n <= 1'b0;
|
|
cfg_in <= 32'h20000000; // NOOP
|
|
end
|
5'h17: begin
|
5'h17: begin
|
// Acknowledge the bus transaction, it is now complete
|
// Acknowledge the bus transaction, it is now complete
|
o_wb_ack <= wb_req;
|
o_wb_ack <= wb_req;
|
wb_req <= 1'b0;
|
wb_req <= 1'b0;
|
//
|
//
|
Line 215... |
Line 300... |
cfg_in <= 32'hffffffff; // DUMMY
|
cfg_in <= 32'hffffffff; // DUMMY
|
//
|
//
|
state <= `MBOOT_IDLE;
|
state <= `MBOOT_IDLE;
|
end
|
end
|
default: begin
|
default: begin
|
o_wb_ack <= 1'b0;
|
wb_req <= 1'b0;
|
cfg_cs_n <= 1'b1;
|
cfg_cs_n <= 1'b1;
|
cfg_rdwrn <= 1'b0;
|
cfg_rdwrn <= 1'b0;
|
state <= `MBOOT_IDLE;
|
state <= `MBOOT_IDLE;
|
cfg_in <= 32'hffffffff; // DUMMY WORD
|
cfg_in <= 32'hffffffff; // DUMMY WORD
|
end
|
end
|
endcase
|
endcase
|
end else begin
|
|
o_wb_ack <= 1'b0;
|
|
end
|
end
|
end
|
end
|
|
|
genvar k;
|
genvar k;
|
//
|
//
|
Line 257... |
Line 340... |
end endgenerate
|
end endgenerate
|
|
|
ICAPE2 #(.ICAP_WIDTH("X32")) reconfig(.CLK(slow_clk),
|
ICAPE2 #(.ICAP_WIDTH("X32")) reconfig(.CLK(slow_clk),
|
.CSIB(cfg_cs_n), .RDWRB(cfg_rdwrn),
|
.CSIB(cfg_cs_n), .RDWRB(cfg_rdwrn),
|
.I(bit_swapped_cfg_in), .O(bit_swapped_cfg_out));
|
.I(bit_swapped_cfg_in), .O(bit_swapped_cfg_out));
|
|
|
|
assign o_dbg = {
|
|
`ifdef DIVIDE_BY_FOUR
|
|
slow_clk_counter, clk_stb, clk_stall,
|
|
`else
|
|
1'b0, slow_clk, clk_stb, clk_stall,
|
|
`endif
|
|
i_wb_stb, o_wb_ack, cfg_cs_n, cfg_rdwrn,
|
|
o_wb_stall, state, 2'h0,
|
|
cfg_in[7:0],
|
|
cfg_out[7:0] };
|
|
|
endmodule
|
endmodule
|
|
|
No newline at end of file
|
No newline at end of file
|