1// 2// Copyright 2011 Ettus Research LLC 3// 4// This program is free software: you can redistribute it and/or modify 5// it under the terms of the GNU General Public License as published by 6// the Free Software Foundation, either version 3 of the License, or 7// (at your option) any later version. 8// 9// This program is distributed in the hope that it will be useful, 10// but WITHOUT ANY WARRANTY; without even the implied warranty of 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12// GNU General Public License for more details. 13// 14// You should have received a copy of the GNU General Public License 15// along with this program. If not, see <http://www.gnu.org/licenses/>. 16// 17 18 19// Wishbone module for spi communications with an SD Card 20// The programming interface is simple -- 21// Write the desired clock divider to address 1 (should be 1 or higher) 22// Status is in address 0. A 1 indicates the last transaction is done and it is safe to 23// send another 24// Writing a byte to address 2 sends that byte over SPI. When it is done, 25// status (addr 0) goes high again, and the received byte can be read from address 3. 26 27module sd_spi_wb 28 (input clk, 29 input rst, 30 31 // SD Card interface 32 output sd_clk, 33 output sd_csn, 34 output sd_mosi, 35 input sd_miso, 36 37 input wb_cyc_i, 38 input wb_stb_i, 39 input wb_we_i, 40 input [1:0] wb_adr_i, 41 input [7:0] wb_dat_i, 42 output reg [7:0] wb_dat_o, 43 output reg wb_ack_o); 44 45 localparam ADDR_STATUS = 0; 46 localparam ADDR_CLKDIV = 1; 47 localparam ADDR_WRITE = 2; 48 localparam ADDR_READ = 3; 49 50 wire [7:0] status, rcv_dat; 51 reg [7:0] clkdiv; 52 wire ready; 53 reg ack_d1; 54 55 reg cs_reg; 56 assign sd_csn = ~cs_reg; // FIXME 57 58 always @(posedge clk) 59 if(rst) ack_d1 <= 0; 60 else ack_d1 <= wb_ack_o; 61 62 always @(posedge clk) 63 if(rst) wb_ack_o <= 0; 64 else wb_ack_o <= wb_cyc_i & wb_stb_i & ~ack_d1; 65 66 always @(posedge clk) 67 case(wb_adr_i) 68 ADDR_STATUS : wb_dat_o <= {7'd0,ready}; 69 ADDR_CLKDIV : wb_dat_o <= clkdiv; 70 ADDR_READ : wb_dat_o <= rcv_dat; 71 default : wb_dat_o <= 0; 72 endcase // case(wb_adr_i) 73 74 always @(posedge clk) 75 if(rst) 76 begin 77 clkdiv <= 200; 78 cs_reg <= 0; 79 end 80 else if(wb_we_i & wb_stb_i & wb_cyc_i & wb_ack_o) 81 case(wb_adr_i) 82 ADDR_STATUS : cs_reg <= wb_dat_i; 83 ADDR_CLKDIV : clkdiv <= wb_dat_i; 84 endcase // case(wb_adr_i) 85 86 wire go = wb_we_i & wb_stb_i & wb_cyc_i & wb_ack_o & (wb_adr_i == ADDR_WRITE); 87 88 sd_spi sd_spi(.clk(clk),.rst(rst), 89 .sd_clk(sd_clk),.sd_mosi(sd_mosi),.sd_miso(sd_miso), 90 .clk_div(clkdiv),.send_dat(wb_dat_i),.rcv_dat(rcv_dat), 91 .go(go),.ready(ready) ); 92 93endmodule // sd_spi_wb 94