2 // Adapted from VHDL code in spi_boot by Arnim Legauer
3 // Added a full wishbone master interface (32-bit)
5 module ram_loader #(parameter AWIDTH=16, RAM_SIZE=16384)
6 (input clk_i, input rst_i,
8 input cfg_clk_i, input cfg_data_i,
9 output start_o, output mode_o, output done_o,
12 output wire [31:0] wb_dat_o,
13 output reg [AWIDTH-1:0] wb_adr_o,
16 output reg [3:0] wb_sel_o,
19 output ram_loader_done_o);
21 // FSM to control start signal, clocked on main clock
22 localparam FSM1_WAIT_DETACH = 2'b00;
23 localparam FSM1_CHECK_NO_DONE = 2'b01;
24 localparam FSM1_WAIT_DONE = 2'b10;
26 reg [1:0] start_fsm_q, start_fsm_s;
27 reg start_q, enable_q, start_s, enable_s;
30 always @(posedge clk_i or posedge rst_i)
33 start_fsm_q <= FSM1_WAIT_DETACH;
39 start_fsm_q <= start_fsm_s;
42 end // else: !if(rst_i)
47 if(detached_i == 1'b1)
49 start_fsm_s <= FSM1_CHECK_NO_DONE;
55 start_fsm_s <= FSM1_WAIT_DETACH;
58 end // else: !if(detached_i == 1'b1)
62 start_fsm_s <= FSM1_WAIT_DONE;
68 start_fsm_s <= FSM1_CHECK_NO_DONE;
71 end // else: !if(~done_q)
75 start_fsm_s <= FSM1_WAIT_DETACH;
81 start_fsm_s <= FSM1_WAIT_DONE;
84 end // else: !if(done_q)
87 start_fsm_s <= FSM1_WAIT_DETACH;
90 end // else: !if(done_q)
91 endcase // case(start_fsm_q)
93 // FSM running on data clock
95 localparam FSM2_IDLE = 3'b000;
96 localparam FSM2_WE_ON = 3'b001;
97 localparam FSM2_WE_OFF = 3'b010;
98 localparam FSM2_INC_ADDR1 = 3'b011;
99 localparam FSM2_INC_ADDR2 = 3'b100;
100 localparam FSM2_FINISHED = 3'b101;
102 reg [AWIDTH-1:0] addr_q;
103 reg [7:0] shift_dat_q, ser_dat_q;
104 reg [2:0] bit_q, fsm_q, fsm_s;
105 reg bit_ovfl_q, ram_we_s, ram_we_q, mode_q, mode_s, inc_addr_s;
107 always @(posedge cfg_clk_i or posedge rst_i)
123 addr_q <= addr_q + 1;
127 bit_ovfl_q <= (bit_q == 3'd7);
128 shift_dat_q[0] <= cfg_data_i;
129 shift_dat_q[7:1] <= shift_dat_q[6:0];
132 ser_dat_q <= shift_dat_q;
136 ram_we_q <= ram_we_s;
141 end // else: !if(rst_i)
159 fsm_s <= FSM2_WE_OFF;
164 fsm_s <= FSM2_INC_ADDR1;
167 fsm_s <= FSM2_INC_ADDR2;
169 if(addr_q == (RAM_SIZE-1))
172 fsm_s <= FSM2_FINISHED;
180 end // else: !if(&addr_q)
183 fsm_s <= FSM2_FINISHED;
186 endcase // case(fsm_q)
189 assign start_o = start_q;
190 assign mode_o = mode_q;
191 assign done_o = start_q ? done_q : 1'b1;
192 wire [AWIDTH-1:0] ram_addr = addr_q;
193 wire [7:0] ram_data = ser_dat_q;
194 assign ram_loader_done_o = (fsm_q == FSM2_FINISHED);
196 // wishbone master, only writes
197 reg [7:0] dat_holder;
198 assign wb_dat_o = {4{dat_holder}};
199 assign wb_stb_o = wb_we_o;
200 assign wb_cyc_o = wb_we_o;
202 always @(posedge clk_i or posedge rst_i)
212 dat_holder <= ram_data;
213 wb_adr_o <= ram_addr;
215 case(ram_addr[1:0]) // Big Endian
216 2'b00 : wb_sel_o <= 4'b1000;
217 2'b01 : wb_sel_o <= 4'b0100;
218 2'b10 : wb_sel_o <= 4'b0010;
219 2'b11 : wb_sel_o <= 4'b0001;
220 endcase // case(ram_addr[1:0])
225 endmodule // ram_loader