/* spi peripheral when fire = 0b1, a command starts. command = spi_cmd_data(17..16) command 0b01 : 2 byte (16 bit) mode : high byte -> low byte order command 0b00 : 1 byte (8 bit) mode data input = spi_cmd_data(15..0) data output = data_out command 0b10 : set spped data input = spi_cmd_data(0) 0b0: low spped (clock speed / 256) 0b1: high speed (clk speed / 2) command 0b11 : set cs data input = spi_cmd_data(0) 0b0: set cs as 0 0b1: set cs as 1 when a command has completed, comp en signal becomes high for one clock cycle. usage in Cherry C do { spi_cmd_data = xxx; } while (~comp); yyy = data_out; note that comp is enable signal (comp en) */ process spi(clkin uint#1 clk, rstin uint#1 rst, in uint#18 spi_cmd_data, in uint#1 fire, out uint#16 data_out, out uint#1 en comp, out uint#1 latch sd_cs, out uint#1 latch sd_di, out uint#1 latch sd_clk, in uint#1 sd_do ) { uint#12 i = 0b000000000000; // 17 + 7bit uint#8 input = 0; uint#16 winput = 0; uint#1 speed = 0; uint#8 output = 0; uint#1 cs = 0, ck = 0, di = 0, doo = 0; uint#1 word = 0, high = 0; cs = 1; sd_cs = cs; SD_SPI_WAIT: { uint#1 f1 = fire; ck = 0; di = 0; sd_clk = ck; sd_di = di; data_out = winput; if (f1) { uint#18 scd = spi_cmd_data; uint#2 cmd = scd#(17..16); if (cmd==0b00) { word = 0; i = 0; output = scd#(7..0); winput = 0; goto SD_SPI_DO; } else if (cmd==0b01) { word = 1; high = 0; i = 0; output = scd#(7..0); winput = 0; goto SD_SPI_DO; } else if (cmd==0b10) goto SD_SPI_SET_SPEED; else goto SD_SPI_SET_CS; } else goto SD_SPI_WAIT; } SD_SPI_SET_SPEED: { uint#18 scd = spi_cmd_data; speed = scd#(0); comp = 1; goto SD_SPI_WAIT; } SD_SPI_SET_CS: { uint#18 scd = spi_cmd_data; cs = scd#(0); sd_cs = cs; comp = 1; goto SD_SPI_WAIT; } SD_SPI_DO: { uint#18 scd = spi_cmd_data; uint#1 sddo = sd_do; uint#5 step = i#(11..7); uint#7 fine = i#(6..0); if ((step != 0) & (~step#(0)) & (speed | (fine==0b1111111))) { doo = sddo; input = input#(6..0)@doo; } if (~step#(4) & ~step#(0) & (speed | (fine == 0b1111111))) { di = output#(7); sd_di = di; output = output#(6..0)@0b0; } if (speed | (fine == 0b1111111)) { if (step == 17) ck = 0; else if (step#(0)) ck = 1; else ck = 0; sd_clk = ck; } if (speed) i += 0b10000000; // 16 MHz else i += 0b00000001; // 125 KHz if (step == 17) { if (word == 0b1) { if (high == 0) { i = 0; winput = input; output = scd#(15..8); high = 1; goto SD_SPI_DO; } else { winput = input@winput#(7..0); comp = 1; goto SD_SPI_WAIT; } } else { winput = input; comp = 1; goto SD_SPI_WAIT; } } else goto SD_SPI_DO; } }