From 05d77f772317de5d925301aa11bb9a880656dd05 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 15 Apr 2010 11:24:24 -0700 Subject: moved usrp1 and usrp2 fpga dirs into fpga subdirectory --- fpga/usrp2/control_lib/ram_loader.v | 225 ++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 fpga/usrp2/control_lib/ram_loader.v (limited to 'fpga/usrp2/control_lib/ram_loader.v') diff --git a/fpga/usrp2/control_lib/ram_loader.v b/fpga/usrp2/control_lib/ram_loader.v new file mode 100644 index 000000000..cb67de739 --- /dev/null +++ b/fpga/usrp2/control_lib/ram_loader.v @@ -0,0 +1,225 @@ + +// Adapted from VHDL code in spi_boot by Arnim Legauer +// Added a full wishbone master interface (32-bit) + +module ram_loader #(parameter AWIDTH=16, RAM_SIZE=16384) + (input clk_i, input rst_i, + // CPLD Interface + input cfg_clk_i, input cfg_data_i, + output start_o, output mode_o, output done_o, + input detached_i, + // Wishbone interface + output wire [31:0] wb_dat_o, + output reg [AWIDTH-1:0] wb_adr_o, + output wb_stb_o, + output wb_cyc_o, + output reg [3:0] wb_sel_o, + output reg wb_we_o, + input wb_ack_i, + output ram_loader_done_o); + + // FSM to control start signal, clocked on main clock + localparam FSM1_WAIT_DETACH = 2'b00; + localparam FSM1_CHECK_NO_DONE = 2'b01; + localparam FSM1_WAIT_DONE = 2'b10; + + reg [1:0] start_fsm_q, start_fsm_s; + reg start_q, enable_q, start_s, enable_s; + reg done_q, done_s; + + always @(posedge clk_i or posedge rst_i) + if(rst_i) + begin + start_fsm_q <= FSM1_WAIT_DETACH; + start_q <= 1'b0; + enable_q <= 1'b0; + end + else + begin + start_fsm_q <= start_fsm_s; + enable_q <= enable_s; + start_q <= start_s; + end // else: !if(rst_i) + + always @* + case(start_fsm_q) + FSM1_WAIT_DETACH: + if(detached_i == 1'b1) + begin + start_fsm_s <= FSM1_CHECK_NO_DONE; + enable_s <= 1'b1; + start_s <= 1'b1; + end + else + begin + start_fsm_s <= FSM1_WAIT_DETACH; + enable_s <= enable_q; + start_s <= start_q; + end // else: !if(detached_i == 1'b1) + FSM1_CHECK_NO_DONE: + if(~done_q) + begin + start_fsm_s <= FSM1_WAIT_DONE; + enable_s <= enable_q; + start_s <= start_q; + end + else + begin + start_fsm_s <= FSM1_CHECK_NO_DONE; + enable_s <= enable_q; + start_s <= start_q; + end // else: !if(~done_q) + FSM1_WAIT_DONE: + if(done_q) + begin + start_fsm_s <= FSM1_WAIT_DETACH; + enable_s <= 1'b0; + start_s <= 1'b0; + end + else + begin + start_fsm_s <= FSM1_WAIT_DONE; + enable_s <= enable_q; + start_s <= start_q; + end // else: !if(done_q) + default: + begin + start_fsm_s <= FSM1_WAIT_DETACH; + enable_s <= enable_q; + start_s <= start_q; + end // else: !if(done_q) + endcase // case(start_fsm_q) + + // FSM running on data clock + + localparam FSM2_IDLE = 3'b000; + localparam FSM2_WE_ON = 3'b001; + localparam FSM2_WE_OFF = 3'b010; + localparam FSM2_INC_ADDR1 = 3'b011; + localparam FSM2_INC_ADDR2 = 3'b100; + localparam FSM2_FINISHED = 3'b101; + + reg [AWIDTH-1:0] addr_q; + reg [7:0] shift_dat_q, ser_dat_q; + reg [2:0] bit_q, fsm_q, fsm_s; + reg bit_ovfl_q, ram_we_s, ram_we_q, mode_q, mode_s, inc_addr_s; + + always @(posedge cfg_clk_i or posedge rst_i) + if(rst_i) + begin + addr_q <= 0; + shift_dat_q <= 8'd0; + ser_dat_q <= 8'd0; + bit_q <= 3'd0; + bit_ovfl_q <= 1'b0; + fsm_q <= FSM2_IDLE; + ram_we_q <= 1'b0; + done_q <= 1'b0; + mode_q <= 1'b0; + end + else + begin + if(inc_addr_s) + addr_q <= addr_q + 1; + if(enable_q) + begin + bit_q <= bit_q + 1; + bit_ovfl_q <= (bit_q == 3'd7); + shift_dat_q[0] <= cfg_data_i; + shift_dat_q[7:1] <= shift_dat_q[6:0]; + end + if(bit_ovfl_q) + ser_dat_q <= shift_dat_q; + + fsm_q <= fsm_s; + + ram_we_q <= ram_we_s; + + if(done_s) + done_q <= 1'b1; + mode_q <= mode_s; + end // else: !if(rst_i) + + always @* + begin + inc_addr_s <= 1'b0; + ram_we_s <= 1'b0; + done_s <= 1'b0; + fsm_s <= FSM2_IDLE; + mode_s <= 1'b0; + + case(fsm_q) + FSM2_IDLE : + if(start_q) + if(bit_ovfl_q) + fsm_s <= FSM2_WE_ON; + FSM2_WE_ON: + begin + ram_we_s <= 1'b1; + fsm_s <= FSM2_WE_OFF; + end + FSM2_WE_OFF: + begin + ram_we_s <= 1'b1; + fsm_s <= FSM2_INC_ADDR1; + end + FSM2_INC_ADDR1: + fsm_s <= FSM2_INC_ADDR2; + FSM2_INC_ADDR2: + if(addr_q == (RAM_SIZE-1)) + //if(&addr_q) + begin + fsm_s <= FSM2_FINISHED; + done_s <= 1'b1; + mode_s <= 1'b1; + end + else + begin + inc_addr_s <= 1'b1; + fsm_s <= FSM2_IDLE; + end // else: !if(&addr_q) + FSM2_FINISHED: + begin + fsm_s <= FSM2_FINISHED; + mode_s <= 1'b1; + end + endcase // case(fsm_q) + end // always @ * + + assign start_o = start_q; + assign mode_o = mode_q; + assign done_o = start_q ? done_q : 1'b1; + wire [AWIDTH-1:0] ram_addr = addr_q; + wire [7:0] ram_data = ser_dat_q; + assign ram_loader_done_o = (fsm_q == FSM2_FINISHED); + + // wishbone master, only writes + reg [7:0] dat_holder; + assign wb_dat_o = {4{dat_holder}}; + assign wb_stb_o = wb_we_o; + assign wb_cyc_o = wb_we_o; + + always @(posedge clk_i or posedge rst_i) + if(rst_i) + begin + dat_holder <= 8'd0; + wb_adr_o <= 0; + wb_sel_o <= 4'b0000; + wb_we_o <= 1'b0; + end + else if(ram_we_q) + begin + dat_holder <= ram_data; + wb_adr_o <= ram_addr; + wb_we_o <= 1'b1; + case(ram_addr[1:0]) // Big Endian + 2'b00 : wb_sel_o <= 4'b1000; + 2'b01 : wb_sel_o <= 4'b0100; + 2'b10 : wb_sel_o <= 4'b0010; + 2'b11 : wb_sel_o <= 4'b0001; + endcase // case(ram_addr[1:0]) + end // if (ram_we_q) + else if(wb_ack_i) + wb_we_o <= 1'b0; + +endmodule // ram_loader -- cgit v1.2.3