cvw/testbench/sdc/sdModel.sv
2024-08-21 10:51:24 -07:00

1117 lines
31 KiB
Systemverilog

//`include "timescale.v"
//`timescale 1ps / 1ps
`include "sd_defines.h"
`define tTLH 10 //Clock rise time
`define tHL 10 //Clock fall time
`define tISU 6 //Input setup time
`define tIH 0 //Input hold time
`define tODL 14 //Output delay
`define DLY_TO_OUTP 47 //47
`define BLOCKSIZE 512
`define MEMSIZE 24643590 // 2mb block
`define BLOCK_BUFFER_SIZE 1
`define TIME_BUSY 512
`define PRG 7
`define RCV 6
`define DATAS 5
`define TRAN 4
module sdModel
(
input sdClk,
inout tri1 cmd,
inout tri1 [3:0] dat
);
//parameter SD_FILE = "ramdisk2.hex";
reg oeCmd;
reg oeDat;
reg cmdOut;
reg [3:0] datOut;
reg [10:0] transf_cnt;
reg [10:0] BLOCK_WIDTH;
reg [5:0] lastCMD;
reg cardIdentificationState;
reg CardTransferActive;
reg [2:0] BusWidth;
assign cmd = oeCmd ? cmdOut : 1'bz;
assign dat = oeDat ? datOut : 4'bz;
reg InbuffStatus;
reg [32:0] ByteAddr;
reg [7:0] Inbuff [0:511];
reg [7:0] FLASHmem [logic[32:0]];
reg [7:0] wide_data [0:63];
reg [46:0] inCmd;
reg [5:0] cmdRead;
reg [7:0] cmdWrite;
reg crcIn;
reg crcEn;
reg crcRst;
reg [31:0] CardStatus;
reg [15:0] RCA;
reg [31:0] OCR;
reg [120:0] CID;
reg [120:0] CSD;
reg Busy; //0 when busy
wire [6:0] crcOut;
reg [4:0] crc_c;
reg [3:0] CurrentState;
reg [3:0] DataCurrentState;
`define RCASTART 16'h2000
`define OCRSTART 32'h40ff8000 // SDHC
`define STATUSSTART 32'h0
`define CIDSTART 128'hffffffddddddddaaaaaaaa99999999 //Just some random data not really useful anyway
`define CSDSTART 128'hadaeeeddddddddaaaaaaaa12345678
`define outDelay 4
reg [2:0] outDelayCnt;
reg [9:0] flash_write_cnt;
reg [8:0] flash_blockwrite_cnt;
parameter SIZE = 10;
parameter CONTENT_SIZE = 40;
parameter
IDLE = 10'b0000_0000_01,
READ_CMD = 10'b0000_0000_10,
ANALYZE_CMD = 10'b0000_0001_00,
SEND_CMD = 10'b0000_0010_00;
reg [SIZE-1:0] state;
reg [SIZE-1:0] next_state;
parameter
DATA_IDLE =10'b0000_0000_01,
READ_WAITS =10'b0000_0000_10,
READ_DATA =10'b0000_0001_00,
WRITE_FLASH =10'b0000_0010_00,
WRITE_DATA =10'b0000_0100_00;
parameter okcrctoken = 4'b0101;
parameter invalidcrctoken = 4'b1111;
reg [SIZE-1:0] dataState;
reg [SIZE-1:0] next_datastate;
reg ValidCmd;
reg inValidCmd;
reg [7:0] response_S;
reg [135:0] response_CMD;
integer responseType;
reg [9:0] block_cnt;
reg wptr;
reg crc_ok;
reg [3:0] last_din;
reg crcDat_rst;
reg mult_read;
reg mult_write;
reg crcDat_en;
reg [3:0] crcDat_in;
wire [15:0] crcDat_out [3:0];
integer sdModel_file_desc;
genvar i;
for(i=0; i<4; i=i+1) begin:CRC_16_gen
sd_crc_16 CRC_16_i (crcDat_in[i],crcDat_en, sdClk, crcDat_rst, crcDat_out[i]);
end
sd_crc_7 crc_7
(
crcIn,
crcEn,
sdClk,
crcRst,
crcOut
);
reg stop;
reg appendCrc;
reg [31:0] startUppCnt;
reg q_start_bit;
//Card initialization DAT contents
//initial $readmemh(SD_FILE, FLASHmem);
initial begin
wide_data[0] <= 'h00;
wide_data[1] <= 'hc8;
wide_data[2] <= 'h80;
wide_data[3] <= 'h01;
wide_data[4] <= 'h80;
wide_data[5] <= 'h01;
wide_data[6] <= 'h80;
wide_data[7] <= 'h01;
wide_data[8] <= 'h80;
wide_data[9] <= 'h01;
wide_data[10] <= 'hc0;
wide_data[11] <= 'h01;
wide_data[12] <= 'h80;
wide_data[13] <= 'h03;
wide_data[14] <= 'h00;
wide_data[15] <= 'h00;
wide_data[16] <= 'h01;
wide_data[17] <= 00;
wide_data[18] <= 00;
wide_data[19] <= 00;
wide_data[20] <= 00;
wide_data[21] <= 00;
wide_data[22] <= 00;
wide_data[23] <= 00;
wide_data[24] <= 00;
wide_data[25] <= 00;
wide_data[26] <= 00;
wide_data[27] <= 00;
wide_data[28] <= 00;
wide_data[29] <= 00;
wide_data[30] <= 00;
wide_data[31] <= 00;
wide_data[32] <= 00;
wide_data[33] <= 00;
wide_data[34] <= 00;
wide_data[35] <= 00;
wide_data[36] <= 00;
wide_data[37] <= 00;
wide_data[38] <= 00;
wide_data[39] <= 00;
wide_data[40] <= 00;
wide_data[41] <= 00;
wide_data[42] <= 00;
wide_data[43] <= 00;
wide_data[44] <= 00;
wide_data[45] <= 00;
wide_data[46] <= 00;
wide_data[47] <= 00;
wide_data[48] <= 00;
wide_data[49] <= 00;
wide_data[50] <= 00;
wide_data[51] <= 00;
wide_data[52] <= 00;
wide_data[53] <= 00;
wide_data[54] <= 00;
wide_data[55] <= 00;
wide_data[56] <= 00;
wide_data[57] <= 00;
wide_data[58] <= 00;
wide_data[59] <= 00;
wide_data[60] <= 00;
wide_data[61] <= 00;
wide_data[62] <= 00;
wide_data[63] <= 00;
/* -----\/----- EXCLUDED -----\/-----
wide_data[0] <= 00;
wide_data[1] <= 20;
wide_data[2] <= 80;
wide_data[3] <= 01;
wide_data[4] <= 80;
wide_data[5] <= 01;
wide_data[6] <= 80;
wide_data[7] <= 01;
wide_data[8] <= 80;
wide_data[9] <= 01;
wide_data[10] <= 80;
wide_data[11] <= 01;
wide_data[12] <= 80;
wide_data[13] <= 03;
wide_data[14] <= 00;
wide_data[15] <= 00;
wide_data[16] <= 01;
wide_data[17] <= 00;
wide_data[18] <= 00;
wide_data[19] <= 00;
wide_data[20] <= 00;
wide_data[21] <= 00;
wide_data[22] <= 00;
wide_data[23] <= 00;
wide_data[24] <= 00;
wide_data[25] <= 00;
wide_data[26] <= 00;
wide_data[27] <= 00;
wide_data[28] <= 00;
wide_data[29] <= 00;
wide_data[30] <= 00;
wide_data[31] <= 00;
wide_data[32] <= 00;
wide_data[33] <= 00;
wide_data[34] <= 00;
wide_data[35] <= 00;
wide_data[36] <= 00;
wide_data[37] <= 00;
wide_data[38] <= 00;
wide_data[39] <= 00;
wide_data[40] <= 00;
wide_data[41] <= 00;
wide_data[42] <= 00;
wide_data[43] <= 00;
wide_data[44] <= 00;
wide_data[45] <= 00;
wide_data[46] <= 00;
wide_data[47] <= 00;
wide_data[48] <= 00;
wide_data[49] <= 00;
wide_data[50] <= 00;
wide_data[51] <= 00;
wide_data[52] <= 00;
wide_data[53] <= 00;
wide_data[54] <= 00;
wide_data[55] <= 00;
wide_data[56] <= 00;
wide_data[57] <= 00;
wide_data[58] <= 00;
wide_data[59] <= 00;
wide_data[60] <= 00;
wide_data[61] <= 00;
wide_data[62] <= 00;
wide_data[63] <= 00;
-----/\----- EXCLUDED -----/\----- */
end
integer k;
reg qCmd;
reg [2:0] crcCnt;
reg add_wrong_cmd_crc;
reg add_wrong_cmd_indx;
reg add_wrong_data_crc;
initial begin
add_wrong_data_crc<=0;
add_wrong_cmd_indx<=0;
add_wrong_cmd_crc<=0;
stop<=1;
cardIdentificationState<=1;
state<=IDLE;
dataState<=DATA_IDLE;
Busy<=0;
oeCmd<=0;
crcCnt<=0;
CardTransferActive<=0;
qCmd<=1;
oeDat<=0;
cmdOut<=0;
cmdWrite<=0;
InbuffStatus<=0;
datOut<=0;
inCmd<=0;
BusWidth<=1;
responseType=0;
mult_read=0;
mult_write=0;
crcIn<=0;
response_S<=0;
crcEn<=0;
crcRst<=0;
cmdRead<=0;
ValidCmd<=0;
inValidCmd=0;
appendCrc<=0;
RCA<= `RCASTART;
OCR<= `OCRSTART;
CardStatus <= `STATUSSTART;
CID<=`CIDSTART;
CSD<=`CSDSTART;
response_CMD<=0;
outDelayCnt<=0;
crcDat_rst<=1;
crcDat_en<=0;
crcDat_in<=0;
transf_cnt<=0;
ByteAddr<=0;
block_cnt <=0;
wptr<=0;
transf_cnt<=0;
crcDat_rst<=1;
crcDat_en<=0;
crcDat_in<=0;
flash_write_cnt<=0;
startUppCnt<=0;
flash_blockwrite_cnt<=0;
end
//CARD logic
always @ (state or cmd or cmdRead or ValidCmd or inValidCmd or cmdWrite or outDelayCnt)
begin : FSM_COMBO
next_state = 0;
case(state)
IDLE: begin
if (!cmd)
next_state = READ_CMD;
else
next_state = IDLE;
end
READ_CMD: begin
if (cmdRead>= 47)
next_state = ANALYZE_CMD;
else
next_state = READ_CMD;
end
ANALYZE_CMD: begin
if ((ValidCmd ) & (outDelayCnt >= `outDelay )) // outDelayCnt >= 4 (NCR)
next_state = SEND_CMD;
else if (inValidCmd)
next_state = IDLE;
else
next_state = ANALYZE_CMD;
end
SEND_CMD: begin
if (cmdWrite>= response_S)
next_state = IDLE;
else
next_state = SEND_CMD;
end
endcase
end
always @ (dataState or CardStatus or crc_c or flash_write_cnt or dat[0] )
begin : FSM_COMBODAT
next_datastate = 0;
case(dataState)
DATA_IDLE: begin
if ((CardStatus[12:9]==`RCV) | (mult_write == 1'b1) )
next_datastate = READ_WAITS;
else if ((CardStatus[12:9]==`DATAS )| (mult_read == 1'b1) )
next_datastate = WRITE_DATA;
else
next_datastate = DATA_IDLE;
end
READ_WAITS: begin
if ( dat[0] == 1'b0 )
next_datastate = READ_DATA;
else
next_datastate = READ_WAITS;
end
READ_DATA : begin
if (crc_c==0 )
next_datastate = WRITE_FLASH;
else begin
if (stop == 1'b0)
next_datastate = READ_DATA;
else
next_datastate = DATA_IDLE;
end
end
WRITE_FLASH : begin
if (flash_write_cnt>265 )
next_datastate = DATA_IDLE;
else
next_datastate = WRITE_FLASH;
end
WRITE_DATA : begin
if (transf_cnt >= BLOCK_WIDTH) // transf_cnt >= 1044
next_datastate= DATA_IDLE;
else
begin
if (stop == 1'b0)
next_datastate=WRITE_DATA;
else
next_datastate = DATA_IDLE;
end
end
endcase
end
always @ (posedge sdClk )
begin
q_start_bit <= dat[0];
end
always @ (posedge sdClk )
begin : FSM_SEQ
state <= next_state;
end
always @ (posedge sdClk )
begin : FSM_SEQDAT
dataState <= next_datastate;
end
always @ (posedge sdClk) begin
if (CardTransferActive) begin
if (InbuffStatus==0) //empty
CardStatus[8]<=1;
else
CardStatus[8]<=0;
end
else
CardStatus[8]<=1;
startUppCnt<=startUppCnt+1;
OCR[31]<=Busy; // THERE IS NO TILDA "OCR[31]<=~BUSY", BUSY is OCR[31]
if (startUppCnt == `TIME_BUSY) // startUppCnt == 63 (counts until ACMD41 valid)
Busy <=1;
end // always @ (posedge sdClk)
always @ (posedge sdClk) begin
qCmd<=cmd;
end
//read data and cmd on rising edge
always @ (posedge sdClk) begin
case(state)
IDLE: begin
mult_write <= 0;
mult_read <=0;
crcIn<=0;
crcEn<=0;
crcRst<=1;
oeCmd<=0;
stop<=0;
cmdRead<=0;
appendCrc<=0;
ValidCmd<=0;
inValidCmd=0;
cmdWrite<=0;
crcCnt<=0;
response_CMD<=0;
response_S<=0;
outDelayCnt<=0;
responseType=0;
end // case: IDLE
READ_CMD: begin //read cmd
crcEn<=1;
crcRst<=0;
crcIn <= #`tIH qCmd; // tIH 0
inCmd[47-cmdRead] <= #`tIH qCmd; // tIH 0
cmdRead <= cmdRead+1;
if (cmdRead >= 40)
crcEn<=0;
if (cmdRead == 46) begin
oeCmd<=1;
cmdOut<=1;
end
end // case: READ_CMD
ANALYZE_CMD: begin//check for valid cmd
//Wrong CRC go idle
if (inCmd[46] == 0) //start
inValidCmd=1;
else if (inCmd[7:1] != crcOut) begin
inValidCmd=1;
$fdisplay(sdModel_file_desc, "**sd_Model Command Packet - CRC Error") ;
$display(sdModel_file_desc, "**sd_Model Command Packet - CRC Error") ;
end
else if (inCmd[0] != 1) begin//stop
inValidCmd=1;
$fdisplay(sdModel_file_desc, "**sd_Model Command Packet - No Stop Bit Error") ;
$display(sdModel_file_desc, "**sd_Model Command Packet - No Stop Bit Error") ;
end
else begin
if(outDelayCnt ==0 )
CardStatus[3]<=0; // AKE_SEQ_ERROR = no error in sequence of authentication process, until I say otherwise
case(inCmd[45:40])
0 : response_S <= 0; // GO_IDLE_STATE
2 : response_S <= 136; //ALL_SEND_CARD_ID (CID)
3 : response_S <= 48; //SEND_RELATIVE_CARD_ADDRESS (RCA)
7 : response_S <= 48; // SELECT_CARD
8 : response_S <= 48; // SEND_INTERFACE_CONDITION (IC)
9 : response_S <= 136; // SEND_CARD_SPECIFIC_DATA (CSD)
14 : response_S <= 0; // reserved (why is this even here?)
16 : response_S <= 48; // SET_BLOCK_LENGTH (Does nothing for SDHC/SDXC)
17 : response_S <= 48; // READ_SINGLE_BLOCK of data from card
18 : response_S <= 48; // READ_MULTIPLE_BLOCKS of data from card
24 : response_S <= 48; // WRITE_BLOCK of data to card
25 : response_S <= 48; // WRITE_MULTIPLE_BLOCKS of data to card
33 : response_S <= 48; // ERASE_WR_BLK_END
55 : response_S <= 48; // APP_CMD
41 : response_S <= 48; // CMD41 - SD_SEND_OCR
endcase // case (inCmd[45:40])
case(inCmd[45:40])
0 : begin // GO_IDLE_STATE
response_CMD <= 0;
cardIdentificationState<=1;
ResetCard;
end
2 : begin //ALL_SEND_CARD_ID (CID)
if (lastCMD != 41 & outDelayCnt==0) begin
$fdisplay(sdModel_file_desc, "**Error in sequence, ACMD 41 should precede 2 in Start-up state") ;
//$display(sdModel_file_desc, "**Error in sequence, ACMD 41 should precede 2 in Start-up state") ;
CardStatus[3]<=1; // AKE_SEQ_ERROR = ERROR in sequence of authentication process
end
response_CMD[127:8] <= CID;
appendCrc<=0;
CardStatus[12:9] <=2;
end
3 : begin //SEND_RELATIVE_CARD_ADDRESS (RCA)
if (lastCMD != 2 & outDelayCnt==0 ) begin
$fdisplay(sdModel_file_desc, "**Error in sequence, CMD 2 should precede 3 in Start-up state") ;
//$display(sdModel_file_desc, "**Error in sequence, CMD 2 should precede 3 in Start-up state") ;
CardStatus[3]<=1; // AKE_SEQ_ERROR = ERROR in sequence of authentication process
end
response_CMD[127:112] <= RCA[15:0] ;
response_CMD[111:96] <= CardStatus[15:0] ;
appendCrc<=1;
CardStatus[12:9] <=3;
cardIdentificationState<=0;
end
6 : begin
if (lastCMD == 55 & outDelayCnt==0) begin //ACMD6 - SET_BUS_WIDTH
if (inCmd[9:8] == 2'b10) begin
BusWidth <=4;
$display(sdModel_file_desc, "**BUS WIDTH 4 ") ;
end
else
BusWidth <=1;
response_S<=48;
response_CMD[127:96] <= CardStatus;
end
else if (outDelayCnt==0) begin //CMD6 - SWITCH_CARD_FUNCTION (Clock speed)
if (CardStatus[12:9] == `TRAN) begin //If card is in transfer state
CardStatus[12:9] <=`DATAS;//Put card in data state
response_CMD[127:96] <= CardStatus ;
response_S<=48;
BLOCK_WIDTH <= 11'd148;
$fdisplay(sdModel_file_desc, "**Error Invalid CMD, %h",inCmd[45:40]);
$display(sdModel_file_desc, "**Error Invalid CMD, %h",inCmd[45:40]);
end
else begin
response_S <= 0;
response_CMD[127:96] <= 0;
$fdisplay(sdModel_file_desc, "**Error Invalid CMD, %h, card not in transfer state",inCmd[45:40]);
$display(sdModel_file_desc, "**Error Invalid CMD, %h, card not in transfer state",inCmd[45:40]);
end // else: !if(CardStatus[12:9] == `TRAN)
end // if (outDelayCnt==0)
end // case: 6
7: begin // SELECT_CARD
if (outDelayCnt==0) begin
if (inCmd[39:24]== RCA[15:0]) begin
CardTransferActive <= 1;
response_CMD[127:96] <= CardStatus ;
CardStatus[12:9] <=`TRAN;
end
else begin
CardTransferActive <= 0;
response_CMD[127:96] <= CardStatus ;
CardStatus[12:9] <=3;
end
end
end // case: 7
8 : begin // SEND_INTERFACE_CONDITION (IC)
response_CMD[127:96] <= {20'h00000 , inCmd[19:8]}; //not supported by V1.0 card
response_S<=48;
$fdisplay(sdModel_file_desc, "**Warning Unofficially Supported CMD, %h",inCmd[45:40]);
$display(sdModel_file_desc, "**Warning Unofficially Supported CMD, %h",inCmd[45:40]);
end
9 : begin // SEND_CARD_SPECIFIC_DATA (CSD)
if (lastCMD != 41 & outDelayCnt==0) begin
$fdisplay(sdModel_file_desc, "**Error in sequence, ACMD 41 should precede 9 in Start-up state") ;
//$display(sdModel_file_desc, "**Error in sequence, ACMD 41 should precede 9 in Start-up state") ;
CardStatus[3]<=1; // AKE_SEQ_ERROR = ERROR in sequence of authentication process
end
response_CMD[127:8] <= CSD;
appendCrc<=0;
CardStatus[12:9] <=2;
end
12: begin // STOP_TRANSMISSION
response_CMD[127:96] <= CardStatus ;
stop<=1;
mult_write <= 0;
mult_read <=0;
CardStatus[12:9] <= `TRAN;
end
16 : begin // SET_BLOCK_LENGTH (Does nothing for SDHC/SDXC)
response_CMD[127:96] <= CardStatus ;
end
17 : begin // READ_SINGLE_BLOCK of data from card
if (outDelayCnt==0) begin
if (CardStatus[12:9] == `TRAN) begin //If card is in transfer state
CardStatus[12:9] <=`DATAS;//Put card in data state
response_CMD[127:96] <= CardStatus ;
BLOCK_WIDTH <= 11'd1044;
ByteAddr = inCmd[39:8] << 9;
if (ByteAddr%512 !=0)
$display("**Block Misalign Error");
end
else begin
response_S <= 0;
response_CMD[127:96] <= 0;
end
end
end
18 : begin // READ_MULTIPLE_BLOCKS of data from card
if (outDelayCnt==0) begin
if (CardStatus[12:9] == `TRAN) begin //If card is in transfer state
CardStatus[12:9] <=`DATAS;//Put card in data state
response_CMD[127:96] <= CardStatus ;
mult_read <= 1;
ByteAddr = inCmd[39:8] << 9;
if (ByteAddr%512 !=0)
$display("**Block Misalign Error");
end
else begin
response_S <= 0;
response_CMD[127:96] <= 0;
end
end
end
24 : begin // WRITE_BLOCK of data to card
if (outDelayCnt==0) begin
if (CardStatus[12:9] == `TRAN) begin //If card is in transfer state
if (CardStatus[8]) begin //If Free write buffer
CardStatus[12:9] <=`RCV;//Put card in Rcv state
response_CMD[127:96] <= CardStatus ;
ByteAddr = inCmd[39:8] << 9;
if (ByteAddr%512 !=0)
$display("**Block Misalign Error");
end
else begin
response_CMD[127:96] <= CardStatus;
$fdisplay(sdModel_file_desc, "**Error Try to blockwrite when No Free Writebuffer") ;
$display("**Error Try to blockwrite when No Free Writebuffer") ;
end
end
else begin
response_S <= 0;
response_CMD[127:96] <= 0;
end
end
end // case: 24
25 : begin // WRITE_MULTIPLE_BLOCKS of data to card
if (outDelayCnt==0) begin
if (CardStatus[12:9] == `TRAN) begin //If card is in transfer state
if (CardStatus[8]) begin //If Free write buffer
CardStatus[12:9] <=`RCV;//Put card in Rcv state
response_CMD[127:96] <= CardStatus ;
ByteAddr = inCmd[39:8] << 9;
mult_write <= 1;
if (ByteAddr%512 !=0)
$display("**Block Misalign Error");
end
else begin
response_CMD[127:96] <= CardStatus;
$fdisplay(sdModel_file_desc, "**Error Try to blockwrite when No Free Writebuffer") ;
$display("**Error Try to blockwrite when No Free Writebuffer") ;
end // else: !if(CardStatus[8])
end // if (CardStatus[12:9] == `TRAN)
else begin
response_S <= 0;
response_CMD[127:96] <= 0;
end // else: !if(CardStatus[12:9] == `TRAN)
end // if (outDelayCnt==0)
end // case: 25
33 : response_CMD[127:96] <= 48; // ERASE_WR_BLK_END
55 :
begin // APP_CMD
response_CMD[127:96] <= CardStatus ;
CardStatus[5] <=1; //Next CMD is AP specific CMD
appendCrc<=1;
end
41 : // CMD41 - SD_SEND_OCR
begin
if (cardIdentificationState) begin
if (lastCMD != 55 & outDelayCnt==0) begin // CMD41 - Reserved/Invalid
$fdisplay(sdModel_file_desc, "**Error in sequence, CMD 55 should precede 41 in Start-up state") ;
$display( "**Error in sequence, CMD 55 should precede 41 in Start-up state") ;
CardStatus[3]<=1; // AKE_SEQ_ERROR = ERROR in sequence of authentication process
end
else begin // CMD41 - SD_SEND_OCR
responseType=3;
response_CMD[127:96] <= OCR;
appendCrc<=0;
CardStatus[5] <=0; // not expecting next command to be ACMD
if (Busy==1)
CardStatus[12:9] <=1; // READY
end // else: !if(lastCMD != 55 & outDelayCnt==0)
end // if (cardIdentificationState)
end // case: 41
endcase // case (inCmd[45:40])
ValidCmd<=1;
crcIn<=0;
outDelayCnt<=outDelayCnt+1;
if (outDelayCnt==`outDelay) // if (outDelayCnt == 4)
crcRst<=1;
oeCmd<=1;
cmdOut<=1;
response_CMD[135:134] <=0; // Start bit = 0, tx bit = 0 (response from card)
// for those who aren't keeping track, we are still in 'else: !if(inCmd[0] != 1)'
if (responseType != 3)
if (!add_wrong_cmd_indx)
response_CMD[133:128] <=inCmd[45:40];
else
response_CMD[133:128] <=0;
if (responseType == 3)
response_CMD[133:128] <=6'b111111;
lastCMD <=inCmd[45:40];
end // else: !if(inCmd[0] != 1)
end // case: ANALYZE_CMD
endcase // case (state)
end // always @ (posedge sdClk)
always @ ( negedge sdClk) begin
case(state)
SEND_CMD: begin
crcRst<=0;
crcEn<=1;
cmdWrite<=cmdWrite+1;
if (response_S!=0)
cmdOut<=0;
else
cmdOut<=1;
if ((cmdWrite>0) & (cmdWrite < response_S-8)) begin
cmdOut<=response_CMD[135-cmdWrite];
crcIn<=response_CMD[134-cmdWrite];
if (cmdWrite >= response_S-9)
crcEn<=0;
end
else if (cmdWrite!=0) begin
crcEn<=0;
if (add_wrong_cmd_crc) begin
cmdOut<=0;
crcCnt<=crcCnt+1;
end
else begin
cmdOut<=crcOut[6-crcCnt];
crcCnt<=crcCnt+1;
if (responseType == 3)
cmdOut<=1;
end
end // if (cmdWrite!=0)
if (cmdWrite == response_S-1)
cmdOut<=1;
end // case: SEND_CMD
endcase // case (state)
end // always @ ( negedge sdClk)
integer outdly_cnt;
always @ (posedge sdClk) begin // Read DATA from host on positive clock edge
case (dataState)
DATA_IDLE: begin
crcDat_rst<=1;
crcDat_en<=0;
crcDat_in<=0;
end
READ_WAITS: begin
oeDat<=0;
crcDat_rst<=0;
crcDat_en<=1;
crcDat_in<=0;
crc_c<=15;//
crc_ok<=1;
end
READ_DATA: begin
InbuffStatus<=1;
if (transf_cnt<`BIT_BLOCK_REC) begin
if (wptr)
Inbuff[block_cnt][3:0] <= dat;
else
Inbuff[block_cnt][7:4] <= dat;
if (!add_wrong_data_crc)
crcDat_in<=dat;
else
crcDat_in<=4'b1010;
crc_ok<=1;
transf_cnt<=transf_cnt+1;
if (wptr)
block_cnt<=block_cnt+1;
wptr<=~wptr;
end // if (transf_cnt<`BIT_BLOCK_REC)
else if ( transf_cnt <= (`BIT_BLOCK_REC +`BIT_CRC_CYCLE-1)) begin
transf_cnt<=transf_cnt+1;
crcDat_en<=0;
last_din <=dat;
if (transf_cnt> `BIT_BLOCK_REC) begin
crc_c<=crc_c-1;
if (crcDat_out[0][crc_c] != last_din[0])
crc_ok<=0;
if (crcDat_out[1][crc_c] != last_din[1])
crc_ok<=0;
if (crcDat_out[2][crc_c] != last_din[2])
crc_ok<=0;
if (crcDat_out[3][crc_c] != last_din[3])
crc_ok<=0;
end // if (transf_cnt> `BIT_BLOCK_REC)
end // if ( transf_cnt <= (`BIT_BLOCK_REC +`BIT_CRC_CYCLE-1))
end // case: READ_DATA
WRITE_FLASH: begin
oeDat<=1;
block_cnt <=0;
wptr<=0;
transf_cnt<=0;
crcDat_rst<=1;
crcDat_en<=0;
crcDat_in<=0;
end
endcase // case (dataState)
end // always @ (posedge sdClk)
reg data_send_index;
integer write_out_index;
always @ (negedge sdClk) begin // Write DATA to Host on negative clock edge
case (dataState)
DATA_IDLE: begin
write_out_index<=0;
transf_cnt<=0;
data_send_index<=0;
outdly_cnt<=0;
flash_write_cnt<=0;
end
WRITE_DATA: begin
oeDat<=1;
outdly_cnt<=outdly_cnt+1;
datOut <= 4'b1111; // listen... until I tell you otherwise, DAT bus is all high (thanks Rose)
if ( outdly_cnt > `DLY_TO_OUTP) begin // if (outdly_cnt > 47) NAC cycles elapsed
transf_cnt <= transf_cnt+1; // start counting bits transferred
crcDat_en<=1; // Enable CRC16
crcDat_rst<=0; // Stop reset of CRC16
oeDat<=1; // Enable output
end
else begin // NAC cycles have not elapsed
crcDat_en<=0; // Disable CRC16 generation
crcDat_rst<=1; // Reset CRC16 generators
oeDat<=0; // Do NOT enable output (I REALLY DO AGREE WITH THIS!)
crc_c<=16; // point to bit 16 of CRC16
end // else: !if( outdly_cnt > `DLY_TO_OUTP)
if (transf_cnt==1) begin // first nibble
if (BLOCK_WIDTH == 11'd1044) begin
last_din <= FLASHmem[ByteAddr+(write_out_index)][7:4]; // LOAD register with upper nibble
crcDat_in<= FLASHmem[ByteAddr+(write_out_index)][7:4]; // LOAD CRC16 with upper nibble
end
else begin
// code for wide width data
last_din <= wide_data[write_out_index][7:4];
crcDat_in <= wide_data[write_out_index][7:4];
end
datOut<=0; // Send nothing yet
data_send_index<=1; // Next nibble is lower nibble
end
else if ( (transf_cnt>=2) & (transf_cnt<=BLOCK_WIDTH -`CRC_OFF )) begin // if (2 <= transf_cnt <= 1025)
data_send_index<=~data_send_index; //toggle
if (!data_send_index) begin //upper nibble
if (BLOCK_WIDTH == 11'd1044) begin
last_din <= FLASHmem[ByteAddr+(write_out_index)][7:4]; // LOAD register with upper nibble
crcDat_in<= FLASHmem[ByteAddr+(write_out_index)][7:4]; // LOAD CRC16 with upper nibble
end
else begin
// code for wide width data
last_din <= wide_data[write_out_index][7:4];
crcDat_in <= wide_data[write_out_index][7:4];
end
end // if (!data_send_index)
else begin //lower nibble
if (BLOCK_WIDTH == 11'd1044) begin
last_din<=FLASHmem[ByteAddr+(write_out_index)][3:0];
end
else begin
last_din <= wide_data[write_out_index][3:0];
end
if (!add_wrong_data_crc)
if (BLOCK_WIDTH == 11'd1044) begin
crcDat_in<= FLASHmem[ByteAddr+(write_out_index)][3:0];
end
else begin
crcDat_in <= wide_data[write_out_index][3:0];
end
else // SNAFU
crcDat_in<=4'b1010;
write_out_index<=write_out_index+1; // Having sent the lower nibble, increment the byte counter
end // else: !if(!data_send_index)
datOut<= last_din; // output content of register
if ( transf_cnt >=BLOCK_WIDTH-`CRC_OFF ) begin // if (trans_cnt >= 1025)
crcDat_en<=0; // Disable CRC16 Generators
end
end // if ( (transf_cnt>=2) & (transf_cnt<=`BIT_BLOCK-`CRC_OFF ))
else if (transf_cnt>BLOCK_WIDTH-`CRC_OFF & crc_c!=0) begin // if ((transf_cnt > 1025) and (crc_c /= 0))
datOut<= last_din; // if sent all data bitsbut not crc16 bits yet
crcDat_en<=0; // Disable CRC16 generators
crc_c<=crc_c-1; // point to next bit of CRC16 to begin transmission of CRC16
if (crc_c<= 16) begin // begin sending CRC16 (16 downto 1)
datOut[0]<=crcDat_out[0][crc_c-1];
datOut[1]<=crcDat_out[1][crc_c-1];
datOut[2]<=crcDat_out[2][crc_c-1];
datOut[3]<=crcDat_out[3][crc_c-1];
end
end // if (transf_cnt>`BIT_BLOCK-`CRC_OFF & crc_c!=0)
else if (transf_cnt==BLOCK_WIDTH-2) begin // if (transf_cnt = 1042) Last CRC16 bit is 1041
datOut<=4'b1111; // send end bits
end
else if ((transf_cnt !=0) & (crc_c == 0 ))begin // if sent data bits and crc_c points past last bit of CRC
oeDat<=0; // disable output on DAT bus
CardStatus[12:9] <= `TRAN; // put card in transfer state
end
end // case: WRITE_DATA
WRITE_FLASH: begin
flash_write_cnt<=flash_write_cnt+1;
CardStatus[12:9] <= `PRG;
datOut[0]<=0;
datOut[1]<=1;
datOut[2]<=1;
datOut[3]<=1;
if (flash_write_cnt == 0)
datOut<=1;
else if(flash_write_cnt == 1)
datOut[0]<=1;
else if(flash_write_cnt == 2)
datOut[0]<=0;
else if ((flash_write_cnt > 2) & (flash_write_cnt < 7)) begin
if (crc_ok)
datOut[0] <=okcrctoken[6-flash_write_cnt];
else
datOut[0] <= invalidcrctoken[6-flash_write_cnt];
end
else if ((flash_write_cnt >= 7) & (flash_write_cnt < 264)) begin
datOut[0]<=0;
flash_blockwrite_cnt<=flash_blockwrite_cnt+2;
FLASHmem[ByteAddr+(flash_blockwrite_cnt)]=Inbuff[flash_blockwrite_cnt];
FLASHmem[ByteAddr+(flash_blockwrite_cnt+1)]=Inbuff[flash_blockwrite_cnt+1];
end
else begin
datOut<=1;
InbuffStatus<=0;
CardStatus[12:9] <= `TRAN;
end // else: !if((flash_write_cnt >= 7) & (flash_write_cnt < 264))
end // case: WRITE_FLASH
endcase // case (dataState)
end // always @ (negedge sdClk)
initial
begin
sdModel_file_desc = $fopen("sd_model.log");
if (sdModel_file_desc < 2)
begin
$display("*E Could not open/create testbench log file in /log/ directory!");
$finish;
end
end
task ResetCard; // MAC registers
begin
add_wrong_data_crc<=0;
add_wrong_cmd_indx<=0;
add_wrong_cmd_crc<=0;
cardIdentificationState<=1;
state<=IDLE;
dataState<=DATA_IDLE;
Busy<=0;
oeCmd<=0;
crcCnt<=0;
CardTransferActive<=0;
qCmd<=1;
oeDat<=0;
cmdOut<=0;
cmdWrite<=0;
startUppCnt<=0;
InbuffStatus<=0;
datOut<=0;
inCmd<=0;
BusWidth<=1;
responseType=0;
crcIn<=0;
response_S<=0;
crcEn<=0;
crcRst<=0;
cmdRead<=0;
ValidCmd<=0;
inValidCmd=0;
appendCrc<=0;
RCA<= `RCASTART;
OCR<= `OCRSTART;
CardStatus <= `STATUSSTART;
CID<=`CIDSTART;
CSD<=`CSDSTART;
response_CMD<=0;
outDelayCnt<=0;
crcDat_rst<=1;
crcDat_en<=0;
crcDat_in<=0;
transf_cnt<=0;
ByteAddr<=0;
block_cnt <=0;
wptr<=0;
transf_cnt<=0;
crcDat_rst<=1;
crcDat_en<=0;
crcDat_in<=0;
flash_write_cnt<=0;
flash_blockwrite_cnt<=0;
end
endtask
endmodule // sdModel