Thoughts on this as a product now that SD card seems possible :
- I could put “sprites” like the bechamel logo and some numbers in some location in memory.
- I could be able to save screen shots on the SD card with a button combo.
- Could there be a kind of database, which would be like how rhino saves files of 3D models one is working on ?
- Am I making a mini computer (ALU, slow big memory, fast SRAM, user interface, screen output) ? What do I think about a scroll wheel and a mini screen then ?
- What could I do with a stack of images from the SD card ?
Just a reminder of what a fully fleshed out video system looks like with the Gameduino : https://excamera.com/files/gameduino/synth/doc/gen/poster.pdf
*********
Checking-in with my project goals for 2024.
- This year the goal was to have a finished open-source project that could be shared with people online or as a kit/product via prepared instruments.com. I would be able to show it to students as an example of a finished design/engineering project that I have completed. The idea would be to stabilize the design, to stop making endless boards, and begin exploring more verilog codes that run on it.
Currently, the Cyber Campus version of the board is basically complete enough to transition into just trying new code. There is just the SD card that remains before the object has a feel of being an independent finished object that isn’t dependent on any other products (like rpi) to function.
Perhaps a distinction between the product, art and workshop kit would be useful :
Kit : reprogrammable, built around the rpi, solderable by beginners, etc.
Product : HDMI IN (a compromise would be that chip that handles everything like the TFP401PZP) and HDMI OUT, plug and play with modern tech. Has a larger FPGA to be able to do more cool stuff.
Art : The Cyber Campus version has everything I need to have fun with new codes, especially ones that interact with time and sequence (like temporal compression?), like differences between images in time impacting the kinds of transformations instead of staying with just static filters.
*********
I need to make the SD card code more generalizable with a function that takes CMD IN.
Here is the command format :
For example CMD8, the first byte is 01001000 with : 0 (start bit) + 1 (tx bit) + 010000 (six bits of the CMD number 8 in binary). After this are 32 bits of arguments (such as address you want to select) the 6 bit CRC7 and then 1.
NOTE ** I may need to change the speed from 50KHz to 100KHz or 200KHz for things to work. I am unclear about when I need to send ticks but forum user writes this :
; There must be 8 clocks after
; * a command with no response
; * the response of a command with a response
; * the end of a read data block
; * the CRC status token on a write
Here is the sequence of commands I have so far :
//TICKS
parameter TICKS = 48'b11111111_11111111_11111111_11111111_11111111_11111111;
//CMD0 āGO_IDLE_STATEā
parameter CMD0 = 48'b01000000_00000000_00000000_00000000_00000000_10010101;
//CMD8 āSEND_IF_CONDā
parameter CMD8 = 48'b01001000_00000000_00000000_00000001_10101010_10000111;
//CMD55 āAPP_CMDā
parameter CMD55 = 48'b01110111_00000000_00000000_00000000_00000000_01100101;
//ACMD41 āSD_SEND_OP_CONDā
parameter ACMD41 = 48'b01101001_01000000_00010000_00000000_00000000_11001101;
//CMD2 āALL_SEND_CIDā
parameter CMD2 = 48'b01000010_00000000_00000000_00000000_00000000_01001101;
//CMD3 āSEND_RELATIVE_ADDRā
parameter CMD3 = 48'b01000011_00000000_00000000_00000000_00000000_00100001;
//CMD7 āSELECT/DESELECT_CARDā
parameter CMD7 = 48'b01000111_00000000_00000000_00000000_00000000_CRC+1; // need to generate my own CRC for this
//CMD17 āREAD_SINGLE_BLOCKā
parameter CMD17 = 48'b01010001_00000000_00000000_00000000_00000000_CRC+1;
NOTE ** There is a read multiple block command CMD18 READ_MULTIPLE_BLOCK that takes a 32 bit address and continuously transfers data blocks until interrupted by the STOP_TRANSMISSION command. By default sends 512 bytes followed by a CRC.
I am currently breaking up the code into cycles of 48 clock pulses to send and receive commands in sequence.
counter <= (counter==47) ? 0 : counter+1; // to count the steps in the sending of a single CMD
phase <= (counter==47) ? phase+1: phase; // to count how many CMDs we have sent
Each command is currently sent in order by checking the phase. For example :
if (phase == 8) begin
rec <= 1; // set CMD to output
CMD <= ACMD41[counter]; // iterate through the 48 bit command
end
Listening to input is tougher because of my poor understanding of inout, I am using inout to define the CMD pin. If we are receiving it is put in a high Z state.
assign CMD = rec ? CMD : 1'bz;
I am not sure if this will work :
if (phase == 9) begin
rec <= 0; // set CMD inout pin to high Z
data_in[counter] <= CMD; //store the data in data_in
end
Here I’m trying to check if a ready bit 31 is still unset :
if ((data_in & (1<<31))==0)
Here I’m trying to compose the CMD7 by concatenating the appropriate bytes.
//CMD7 āSELECT/DESELECT_CARDā
if (phase == 16) begin
rec <= 1;
RCA[15:0] = data_in[31:15]; // retrieve the RCA from the previous response
CMD7[47:0] = {8'b01000111,RCA[15:0],16'b0000000000000000,CRC+1}; // compose CMD7 from parts
CMD <= CMD7[counter]; // send the command
end
****
I’m on this site to calculate the CRC7 (https://www.ghsi.de/pages/subpages/Online%20CRC%20Calculation/)
- First I enter the CRC polynomial which for the SD card is x7 +x3 + 1
- Then I translate the 5 bytes I want to send into hex
- The 7 bit value generated at the end of the page is then added to the end of the message plus the end bit (1)
I need to figure out how to incorporate the CRC in verilog for certain commands however :
The above website automatically generates this verilog code that takes one bit at a time :
// ==========================================================================
// CRC Generation Unit - Linear Feedback Shift Register implementation
// (c) Kay Gorontzi, GHSi.de, distributed under the terms of LGPL
// ==========================================================================
module CRC_Unit(BITVAL, BITSTRB, CLEAR, CRC);
input BITVAL; // Next input bit
input BITSTRB; // Current bit valid (Clock)
input CLEAR; // Init CRC value
output [6:0] CRC; // Current output CRC value
reg [6:0] CRC; // We need output registers
wire inv;
assign inv = BITVAL ^ CRC[6]; // XOR required?
always @(posedge BITSTRB or posedge CLEAR) begin
if (CLEAR) begin
CRC = 0; // Init before calculation
end
else begin
CRC[6] = CRC[5];
CRC[5] = CRC[4];
CRC[4] = CRC[3];
CRC[3] = CRC[2] ^ inv;
CRC[2] = CRC[1];
CRC[1] = CRC[0];
CRC[0] = inv;
end
end
endmodule
I am not sure exactly how to feed this module one bit at a time. I also feel unsure about how to properly incorporate modules from different files.
****
Here is my test code (once the timescale is uncommented) that I’m hoping will not require CRC (I’ll just look on the oscilloscope to see what the RCA is and then use that). It is the simplest possible setup.
Possible things that need changing :
- I am not waiting to see if bit 31 is set after sending
ACMD41
, so I probably will need to add a delay here ? *EDIT* I am getting a busy bit 31 the first time I ask at the moment. - 8 clock ticks instead of 48 ? *EDIT* DONE
- No clock ticks after certain commands?
- The RCA (and CRC) if it is not 0001
- The block address (and CRC) if it is not 0
//-----------------------------------------------------------------
// - Attempt at SD 1 bit communication -
//CMD0 āGO_IDLE_STATEā
//CMD8 āSEND_IF_CONDā
//CMD55 āAPP_CMDā, ACMD41 āSD_SEND_OP_CONDā with argument 40100000 (HCS=1, voltage = 3.3).
//The R3 response has HCS and the supported voltages set. Repeat until bit 31 of the response is 1.
//CMD2 āALL_SEND_CIDā with argument 00000000. The R2 response has the CID. I ignore it.
//CMD3 āSEND_RELATIVE_ADDRā with argument 00000000. The R6 response contains the RCA and some status that I ignore.
//The card is now in the stand-by state. Reading a block is accomplished by
//CMD7 āSELECT/DESELECT_CARDā with argument bits 31-16 = the RCA you were given, 15-0 = 0. The R1b response I ignore.
//CMD17 āREAD_SINGLE_BLOCKā with argument = the block address.
//The R1 response I ignore, but there will also be the block data.
//Keep toggling the clock, and youāll eventually see a start bit followed by a block of data and a CRC.
//-----------------------------------------------------------------
`default_nettype none // disable implicit definitions by Verilog
//`timescale 1us/1ns
module top(
input wire clk100,
input wire reset,
//input reg DAT,
output reg SCK,
output reg CMD
);
//CMD0 āGO_IDLE_STATEā
parameter CMD0 = 48'b01000000_00000000_00000000_00000000_00000000_10010101;
//CMD8 āSEND_IF_CONDā
parameter CMD8 = 48'b01001000_00000000_00000000_00000001_10101010_10000111;
//CMD55 āAPP_CMDā
parameter CMD55 = 48'b01110111_00000000_00000000_00000000_00000000_01100101;
//ACMD41 āSD_SEND_OP_CONDā
parameter ACMD41 = 48'b01101001_01000000_00010000_00000000_00000000_11001101;
//CMD2 āALL_SEND_CIDā
parameter CMD2 = 48'b01000010_00000000_00000000_00000000_00000000_01001101;
//CMD3 āSEND_RELATIVE_ADDRā
parameter CMD3 = 48'b01000011_00000000_00000000_00000000_00000000_00100001;
//CMD7 āSELECT/DESELECT_CARDā
parameter CMD7 = 48'b01000111_00000000_00000001_00000000_00000000_11011101; // ASSUMING RCA IS 0001
//CMD17 āREAD_SINGLE_BLOCKā
parameter CMD17 = 48'b01010001_00000000_00000000_00000000_00000000_01010101; // ASSUMING ADDR ZERO EXISTS
//CMD18 āREAD_MULTIPLE_BLOCKā
parameter CMD18 = 48'b01010010_00000000_00000000_00000000_00000000_11100001; // ASSUMING ADDR ZERO EXISTS
//some counters
reg [9:0] counter=0;
reg [9:0] phase=0;
reg [7:0] q=0;
// divide 100MHz clock by 255 to equal 196.0784315 KHz which is in the 100KHz - 400KHz range
always @(posedge clk100) begin
q <= q+1;
if(q == 0) begin
SCK <= ~SCK;
end
end
//to count 48 SCK cycles and also how many which step of the communication sequence we're on
always @(posedge SCK) begin
//send 8 ticks
if (phase == 0) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send CMD0
if (phase == 1) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD0[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send 8 clock ticks while CMD high
if (phase == 2) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send CMD8
if (phase == 3) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD8[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//set CMD to input
if (phase == 4) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//NEED THIS ? send 8 clock ticks while CMD high
if (phase == 5) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send CMD55
if (phase == 6) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD55[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to response
if (phase == 7) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//NEED THIS ? send 8 clock ticks while CMD high
if (phase == 8) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send ACMD41
if (phase == 9) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= ACMD41[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to response and check bit 31 is 1
if (phase == 10) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send CMD2
if (phase == 11) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD2[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to 136 bit CID CMD from SD
if (phase == 12) begin
counter <= counter+1;
if (counter <= 135) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send CMD3
if (phase == 13) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD3[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
if (phase == 14) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//CMD7 āSELECT/DESELECT_CARDā
if (phase == 15) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD7[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to CMD from SD
if (phase == 16) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//CMD17 āREAD_SINGLE_BLOCKā with argument = the block address.
if (phase == 17) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD17[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
if (phase == 18) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
// Should start to see data coming in on the DAT pin !!
if (phase >= 19) begin
// DAT pin
end
end
endmodule
The sequence for ModelSim was :
- Open ModelSim, reselect the licence.dat file
- Open a “new project”
- Click Add Existing Files (pick only the test bench verilog file) and then Close
- Now Compilation > Compile All
- Now Simulation > Start Simulation
- In the console type <<view wave>>ā¦
- ā¦then <<add wave * >>ā¦ (note the space between wave and *)
- I right clicked on the SCK signal and selected Clock and then set the speed.
- ā¦and a time period for example : <<run 10000ms>>.
I should have been able to see that the bits were the wrong order and that the clock ticks were with CMD low instead of HIGH here !!
*****
So I have gotten as far as CMD0 -> CMD8 -> CMD55 -> ACM41
At this point the SD card returns a busy bit 31, and when I ask again and again it eventually tries to talk while I am controlling the CMD pin and communications break down. Reading the documentation it looks like I can just keep pulsing the clock between 100-400KHz and delaying before checking the busy bit again (so getting rid of the 5x checks I do back to back and adding a seriously long delay could be the answer). This is the next step !
Here is the code so far :
//-----------------------------------------------------------------
// - Attempt at SD 1 bit communication -
//CMD0 āGO_IDLE_STATEā
//CMD8 āSEND_IF_CONDā
//CMD55 āAPP_CMDā, ACMD41 āSD_SEND_OP_CONDā with argument 40100000 (HCS=1, voltage = 3.3).
//The R3 response has HCS and the supported voltages set. Repeat until bit 31 of the response is 1.
//CMD2 āALL_SEND_CIDā with argument 00000000. The R2 response has the CID. I ignore it.
//CMD3 āSEND_RELATIVE_ADDRā with argument 00000000. The R6 response contains the RCA and some status that I ignore.
//The card is now in the stand-by state. Reading a block is accomplished by
//CMD7 āSELECT/DESELECT_CARDā with argument bits 31-16 = the RCA you were given, 15-0 = 0. The R1b response I ignore.
//CMD17 āREAD_SINGLE_BLOCKā with argument = the block address.
//The R1 response I ignore, but there will also be the block data.
//Keep toggling the clock, and youāll eventually see a start bit followed by a block of data and a CRC.
//-----------------------------------------------------------------
`default_nettype none // disable implicit definitions by Verilog
//`timescale 1us/1ns
module top(
input wire clk100,
input wire reset,
//input reg DAT,
output reg SCK,
output reg CMD
);
//CMD0 āGO_IDLE_STATEā
parameter CMD0 = 48'b01000000_00000000_00000000_00000000_00000000_10010101;
//CMD8 āSEND_IF_CONDā
parameter CMD8 = 48'b01001000_00000000_00000000_00000001_10101010_10000111;
//CMD55 āAPP_CMDā
parameter CMD55 = 48'b01110111_00000000_00000000_00000000_00000000_01100101;
//ACMD41 āSD_SEND_OP_CONDā
parameter ACMD41 = 48'b01101001_01000000_00010000_00000000_00000000_11001101;
//CMD2 āALL_SEND_CIDā
parameter CMD2 = 48'b01000010_00000000_00000000_00000000_00000000_01001101;
//CMD3 āSEND_RELATIVE_ADDRā
parameter CMD3 = 48'b01000011_00000000_00000000_00000000_00000000_00100001;
//CMD7 āSELECT/DESELECT_CARDā
parameter CMD7 = 48'b01000111_00000000_00000001_00000000_00000000_11011101; // ASSUMING RCA IS 0001
//CMD17 āREAD_SINGLE_BLOCKā
parameter CMD17 = 48'b01010001_00000000_00000000_00000000_00000000_01010101; // ASSUMING ADDR ZERO EXISTS
//CMD18 āREAD_MULTIPLE_BLOCKā
parameter CMD18 = 48'b01010010_00000000_00000000_00000000_00000000_11100001; // ASSUMING ADDR ZERO EXISTS
//some counters
reg [9:0] counter=0;
reg [9:0] phase=0;
reg [7:0] q=0;
// divide 100MHz clock by 255 to equal 196.0784315 KHz which is in the 100KHz - 400KHz range
always @(posedge clk100) begin
q <= q+1;
if(q == 0) begin
SCK <= ~SCK;
end
end
//to count 48 SCK cycles and also how many which step of the communication sequence we're on
always @(posedge SCK) begin
//send 8 ticks
if (phase == 0) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send CMD0
if (phase == 1) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD0[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send 8 clock ticks while CMD high
if (phase == 2) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send CMD8
if (phase == 3) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD8[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//set CMD to input
if (phase == 4) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//NEED THIS ? send 8 clock ticks while CMD high
if (phase == 5) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send CMD55
if (phase == 6) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD55[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to response
if (phase == 7) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//NEED THIS ? send 8 clock ticks while CMD high
if (phase == 8) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send ACMD41
if (phase == 9) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= ACMD41[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to response and check bit 31 is 1
if (phase == 10) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
// START OF SEND CMD55 + ACMD41 again (X2)
//START OF CONTINUOUS CLOCK BEFORE POLLING AGAIN
//END OF CONTINUOUS CLOCK BEFORE POLLING AGAIN
//
//NEED THIS ? send 8 clock ticks while CMD high
if (phase == 11) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send CMD55
if (phase == 12) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD55[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to response
if (phase == 13) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//NEED THIS ? send 8 clock ticks while CMD high
if (phase == 14) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send ACMD41
if (phase == 15) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= ACMD41[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to response and check bit 31 is 1
if (phase == 16) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
// END OF SEND CMD55 + ACMD41 again (x2)
// START OF SEND CMD55 + ACMD41 again (x3)
//NEED THIS ? send 8 clock ticks while CMD high
if (phase == 17) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send CMD55
if (phase == 18) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD55[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to response
if (phase == 19) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//NEED THIS ? send 8 clock ticks while CMD high
if (phase == 20) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send ACMD41
if (phase == 21) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= ACMD41[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to response and check bit 31 is 1
if (phase == 22) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
// END OF SEND CMD55 + ACMD41 again (x3)
// START OF SEND CMD55 + ACMD41 again (x4)
//NEED THIS ? send 8 clock ticks while CMD high
if (phase == 23) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send CMD55
if (phase == 24) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD55[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to response
if (phase == 25) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//NEED THIS ? send 8 clock ticks while CMD high
if (phase == 26) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send ACMD41
if (phase == 27) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= ACMD41[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to response and check bit 31 is 1
if (phase == 28) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
// END OF SEND CMD55 + ACMD41 again (x4)
// START OF SEND CMD55 + ACMD41 again (x5)
//NEED THIS ? send 8 clock ticks while CMD high
if (phase == 29) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send CMD55
if (phase == 30) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD55[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to response
if (phase == 31) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//NEED THIS ? send 8 clock ticks while CMD high
if (phase == 32) begin
counter <= counter+1;
if (counter <= 7) begin
CMD <= 1'b1;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send ACMD41
if (phase == 33) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= ACMD41[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to response and check bit 31 is 1
if (phase == 34) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
// END OF SEND CMD55 + ACMD41 again (x5)
//ADD TICKS HERE ??????????
//send CMD2
if (phase == 35) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD2[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to 136 bit CID CMD from SD
if (phase == 36) begin
counter <= counter+1;
if (counter <= 135) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//send CMD3
if (phase == 37) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD3[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
if (phase == 38) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//CMD7 āSELECT/DESELECT_CARDā
if (phase == 39) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD7[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
//listen to CMD from SD
if (phase == 40) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
//CMD17 āREAD_SINGLE_BLOCKā with argument = the block address.
if (phase == 41) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= CMD17[47-counter];
end
else begin
counter<=0;
phase<=phase+1;
end
end
if (phase == 42) begin
counter <= counter+1;
if (counter <= 47) begin
CMD <= 1'bz;
end
else begin
counter<=0;
phase<=phase+1;
end
end
// Should start to see data coming in on the DAT pin !!
if (phase >= 43) begin
// DAT pin
end
end
endmodule
Here is what it looks like on the scope with just one exchange :
…and a series of back and forth commands :
….
To go further I would need to switch the logic analyzer.