URL
https://opencores.org/ocsvn/sdhc-sc-core/sdhc-sc-core/trunk
Subversion Repositories sdhc-sc-core
Compare Revisions
- This comparison shows the changes necessary to convert path
/sdhc-sc-core/trunk/src/grpSd/unitSdCardModel/src
- from Rev 149 to Rev 150
- ↔ Reverse comparison
Rev 149 → Rev 150
/SdData.sv
File deleted
/SdBusTrans.sv
1,17 → 1,24
`ifndef SDBUSTRANS_SV |
`define SDBUSTRANS_SV |
|
`include "SdDataBlock.sv" |
|
const logic cSdStartbit = 0; |
const logic cSdEndbit = 1; |
|
typedef logic SdBusTransData[$]; |
|
virtual class SdBusTrans; |
class SdBusTrans; |
|
SdDataBlock DataBlocks[]; |
bit SendBusy = 0; |
|
virtual function SdBusTransData packToData(); |
endfunction |
|
virtual function void unpackFromData(ref SdBusTransData data); |
endfunction |
|
endclass |
|
class SdBusTransToken extends SdBusTrans; |
/SdBFM-impl.sv
1,7 → 1,7
`ifndef SDBFMIMPL_SV |
`define SDBFMIMPL_SV |
|
function SdBFM::new(virtual ISdCard card); |
function SdBFM::new(virtual ISdBus card); |
this.ICard = card; |
this.Log = new; |
this.Sem = new(1); |
15,9 → 15,7
StopAfter = AfterCount; |
endfunction |
|
task SdBFM::send(input SdBusTrans token); |
this.Sem.get(1); |
|
task SdBFM::sendCmd(inout SdBusTransData data); |
// startbit |
@ICard.cb; |
ICard.cb.Cmd <= cSdStartbit; |
24,7 → 22,6
|
// data |
begin |
SdBusTransData data = token.packToData(); |
|
foreach(data[i]) begin |
@ICard.cb; |
39,7 → 36,95
|
@ICard.cb; |
ICard.cb.Cmd <= 'z; |
|
waitUntilReady(); |
endtask |
|
task SdBFM::sendAllDataBlocks(SdDataBlock blocks[]); |
foreach(blocks[i]) begin |
sendDataBlock(blocks[i]); |
waitUntilReady(); |
end |
endtask |
|
task SdBFM::waitUntilReady(); |
repeat (8) @ICard.cb; |
endtask |
|
task SdBFM::sendDataBlock(SdDataBlock block); |
if (Mode == standard) sendStandardDataBlock(block.data); |
else sendWideDataBlock(block.data); |
endtask |
|
task SdBFM::sendStandardDataBlock(logic data[$]); |
data.push_front(0); // startbit |
CrcOnContainer(data); |
data.push_back(1); // endbit |
|
foreach(data[i]) begin |
@ICard.cb; |
ICard.cb.Data[0] <= data[i]; |
end |
|
@ICard.cb; |
ICard.cb.Data <= 'z; |
endtask |
|
task SdBFM::sendWideDataBlock(logic data[$]); |
logic dat0[$]; |
logic dat1[$]; |
logic dat2[$]; |
logic dat3[$]; |
|
for (int i = 0; i < data.size(); i+=4) begin |
dat3.push_back(data[i]); |
dat2.push_back(data[i+1]); |
dat1.push_back(data[i+2]); |
dat0.push_back(data[i+3]); |
end |
CrcOnContainer(dat0); |
CrcOnContainer(dat1); |
CrcOnContainer(dat2); |
CrcOnContainer(dat3); |
|
@ICard.cb; |
ICard.cb.Data <= 0; |
|
for(int i = 0; i < dat0.size(); i++) begin |
@ICard.cb; |
ICard.cb.Data <= (dat3[i]<<3) + (dat2[i] <<2) + (dat1[i] <<1) + dat0[i]; |
end |
|
@ICard.cb; |
ICard.cb.Data <= 0; |
|
@ICard.cb; |
ICard.cb.Data <= 'z; |
endtask |
|
task SdBFM::sendBusy(); |
@ICard.cb; |
|
// 10 busy cycles |
ICard.cb.Data[0] <= 0; |
|
repeat (10) @ICard.cb; |
ICard.cb.Data[0] <= 1; |
|
@ICard.cb; |
ICard.cb.Data <= 'z; |
endtask |
|
task SdBFM::send(input SdBusTrans token); |
SdBusTransData data; |
|
this.Sem.get(1); |
data = token.packToData(); |
|
if (data.size() > 0) sendCmd(data); |
if (token.DataBlocks.size() > 0) sendAllDataBlocks(token.DataBlocks); |
else if (token.SendBusy == 1) sendBusy(); |
|
this.Sem.put(1); |
endtask |
|
73,9 → 158,54
begin |
this.Log.error("Received invalid endbit during SdBFM.receive.\n"); |
end |
endtask |
|
task SdBFM::receiveDataBlock(output SdDataBlock block); |
ICard.cb.Data <= 'bzzzz; |
|
if (Mode == wide) wait (ICard.cb.Data == 'b0000); |
else wait (ICard.cb.Data[0] == '0); |
|
recvDataBlock(block); |
endtask |
|
task SdBFM::recvDataBlock(output SdDataBlock block); |
if (Mode == standard) recvStandardDataBlock(block); |
else recvWideDataBlock(block); |
endtask |
|
task SdBFM::recvStandardDataBlock(output SdDataBlock block); |
Log.error("recvStandardDataBlock not implemented"); |
endtask |
|
task SdBFM::recvWideDataBlock(output SdDataBlock block); |
aCrc16 crc[4]; |
block = new(); |
|
$display("Startbits: %t", $time); |
for (int j = 0; j <= 512*2; j++) begin |
@ICard.cb; |
for(int i = 0; i < 4; i++) begin |
block.data.push_back(ICard.cb.Data[i]); |
end |
end |
|
// crc |
for (int j = 0; j < 16; j++) begin |
@ICard.cb; |
for(int i = 0; i < 4; i++) begin |
crc[i] = ICard.cb.Data[i]; |
end |
end |
|
// TODO: check crc |
|
// end bits |
@ICard.cb; |
$display("Endbits: %h, %t", ICard.cb.Data, $time); |
assert(ICard.cb.Data == 'b1111); |
endtask |
|
task SdBFM::receiveOrSend(); |
if(ICard.cb.Cmd == cSdStartbit) begin |
SdBusTransToken token; |
/SdBFM.sv
8,7 → 8,7
`ifndef SDBFM_SV |
`define SDBFM_SV |
|
`include "SdCmdInterface.sv" |
`include "SdBusInterface.sv" |
`include "Crc.sv" |
`include "Logger.sv" |
`include "SDCommandArg.sv" |
15,28 → 15,44
`include "SdBusTrans.sv" |
|
typedef mailbox #(SdBusTrans) SdBfmMb; |
typedef enum { |
standard, |
wide |
} Mode_t; |
|
class SdBFM; |
|
virtual ISdCard.card ICard; |
virtual ISdBus.card ICard; |
SdBfmMb ReceivedTransMb; |
SdBfmMb SendTransMb; |
local semaphore Sem; |
local Logger Log; |
local int StopAfter = -1; |
Mode_t Mode; |
|
extern function new(virtual ISdBus card); |
|
extern function new(virtual ISdCard card); |
|
extern task start(); // starts a thread for receiving and sending via mailboxes |
extern function stop(int AfterCount); // stop the thread |
|
extern task send(input SdBusTrans token); |
extern task sendBusy(); |
extern task receive(output SdBusTransToken token); |
extern task receiveDataBlock(output SdDataBlock block); |
extern task waitUntilReady(); |
|
extern local task sendCmd(inout SdBusTransData data); |
extern local task sendAllDataBlocks(SdDataBlock blocks[]); |
extern local task sendDataBlock(SdDataBlock block); |
extern local task sendStandardDataBlock(logic data[$]); |
extern local task sendWideDataBlock(logic data[$]); |
extern local task recvDataBlock(output SdDataBlock block); |
extern local task recvStandardDataBlock(output SdDataBlock block); |
extern local task recvWideDataBlock(output SdDataBlock block); |
extern local task recv(output SdBusTransToken token); |
extern local task receiveOrSend(); |
extern local task run(); |
|
local semaphore Sem; |
local Logger Log; |
local int StopAfter = -1; |
endclass |
|
`include "SdBFM-impl.sv"; |
/SdDataBlock.sv
0,0 → 1,29
// |
// file: SdData.sv |
// author: Rainer Kastl |
// |
// Class for sending and receiving data (SD spec 2.00) |
// |
|
`ifndef SDDATA |
`define SDDATA |
|
typedef enum { |
usual, |
widewidth |
} DataMode_t; |
|
function automatic void CrcOnContainer(ref logic data[$]); |
aCrc16 crc = 0; |
crc = calcCrc16(data); |
|
for (int i = 15; i >= 0; i--) |
data.push_back(crc[i]); |
endfunction |
|
class SdDataBlock; |
DataMode_t Mode; |
logic data[$]; |
endclass |
|
`endif |
/SdCardModel.sv
13,13 → 13,11
|
`include "Crc.sv"; |
`include "SdCommand.sv"; |
`include "SdData.sv"; |
`include "SdBFM.sv"; |
`include "Logger.sv"; |
|
class SDCard; |
local SdBFM bfm; |
local virtual ISdCard.card ICard; |
local SDCardState state; |
local RCA_t rca; |
local logic CCS; |
27,8 → 25,6
local DataMode_t datamode; |
local Logger log; |
|
local event CmdReceived, InitDone; |
|
local rand int datasize; // ram addresses = 2^datasize - 1; 512 byte blocks |
constraint cdatasize {datasize > 1; datasize <= 32;} |
|
38,12 → 34,9
this.ram = new[2^(datasize-1)]; |
endfunction |
|
function new(virtual ISdCard CardInterface, event CmdReceived, event InitDone); |
ICard = CardInterface; |
bfm = new(CardInterface); |
function new(SdBFM bfm); |
this.bfm = bfm; |
state = new(); |
this.CmdReceived = CmdReceived; |
this.InitDone = InitDone; |
this.CCS = 1; |
rca = 0; |
mode = standard; |
61,7 → 54,6
SDOCR ocr; |
SDCommandR6 rcaresponse; |
logic data[$]; |
SdData sddata; |
SdBusTransToken token; |
|
log.note("Expecting CMD0"); |
156,21 → 148,19
this.bfm.receive(token); |
assert(token.id == cSdCmdSendSCR); |
|
// respond with R1 |
// respond with R1 and dummy SCR |
response = new(cSdCmdSendSCR, state); |
this.bfm.send(response); |
|
repeat(2) @ICard.cb; |
|
response.DataBlocks = new[1]; |
response.DataBlocks[0] = new(); |
|
// send dummy SCR |
for (int i = 0; i < 64; i++) |
data.push_back(0); |
response.DataBlocks[0].data.push_back(0); |
|
data[63-50] = 1; |
data[63-48] = 1; |
response.DataBlocks[0].data[63-50] = 1; |
response.DataBlocks[0].data[63-48] = 1; |
|
sddata = new(standard, widewidth); |
sddata.send(ICard, data); |
this.bfm.send(response); |
|
// expect ACMD6 |
recvCMD55(rca); |
182,7 → 172,7
response = new(cSdCmdSetBusWidth, state); |
this.bfm.send(response); |
|
sddata.mode = wide; |
this.bfm.Mode = wide; |
mode = wide; |
|
// expect CMD6 |
190,18 → 180,18
this.bfm.receive(token); |
assert(token.id == cSdCmdSwitchFuntion); |
assert(token.arg == 'h00FFFFF1); |
this.bfm.send(response); |
|
// send status data structure |
data = {}; |
response.DataBlocks = new[1]; |
response.DataBlocks[0] = new(); |
|
for (int i = 0; i < 512; i++) |
data.push_back(0); |
response.DataBlocks[0].data.push_back(0); |
|
data[511-401] = 1; |
data[511-376] = 1; |
sddata.send(ICard, data); |
response.DataBlocks[0].data[511-401] = 1; |
response.DataBlocks[0].data[511-376] = 1; |
|
this.bfm.send(response); |
|
// expect CMD6 with set |
log.note("Expect CMD6 with set"); |
this.bfm.receive(token); |
209,16 → 199,6
assert(token.arg == 'h80FFFFF1); |
this.bfm.send(response); |
|
// send status data structure |
data = {}; |
|
for (int i = 0; i < 512; i++) |
data.push_back(0); |
|
data[511-401] = 1; |
data[511-376] = 1; |
sddata.send(ICard, data); |
|
// switch to 50MHz |
// expect CMD13 |
log.note("Expect CMD13"); |
228,8 → 208,6
response = new(cSdCmdSendStatus, state); |
this.bfm.send(response); |
|
-> InitDone; |
|
endtask |
|
task run(); |
253,9 → 231,7
|
task read(SdBusTransToken token); |
SDCommandR1 response; |
logic data[$]; |
logic[31:0] addr; |
SdData sddata = new(mode, usual); |
|
// expect Read |
assert(token.id == cSdCmdReadSingleBlock); |
262,48 → 238,48
addr = token.arg[0]; |
assert(addr < ram.size()); |
response = new(cSdCmdReadSingleBlock, state); |
this.bfm.send(response); |
|
data = {}; |
response.DataBlocks = new[1]; |
response.DataBlocks[0] = new(); |
|
for (int i = 0; i < 512; i++) begin |
for (int j = 7; j >= 0; j--) begin |
data.push_back(ram[addr][i*8 + j]); |
response.DataBlocks[0].data.push_back(ram[addr][i*8 + j]); |
end |
end |
|
sddata.send(ICard, data); |
this.bfm.send(response); |
endtask |
|
task write(SdBusTransToken token); |
SDCommandR1 response; |
SdData sddata = new(this.mode, widewidth); |
logic rddata[$]; |
SdDataBlock rdblock; |
logic[31:0] addr; |
|
// expect Write |
assert(token.id == cSdCmdWriteSingleBlock); |
addr = token.arg[0]; |
addr = token.arg; |
assert(addr < ram.size()); |
response = new(cSdCmdWriteSingleBlock, state); |
this.bfm.send(response); |
|
// recv data |
sddata.recv(ICard, rddata); |
$display("rddata: %p", rddata); |
this.bfm.receiveDataBlock(rdblock); |
$display("rddata: %p", rdblock.data); |
|
$display("datasize: %h", datasize); |
$display("Address (token): %h", token.arg); |
$display("Address: %h", addr); |
|
// write into ram |
for (int i = 0; i < 512; i++) begin |
for (int j = 7; j >= 0; j--) begin |
ram[addr][i * 8 + j] = rddata.pop_front(); |
ram[addr][i * 8 + j] = rdblock.data.pop_front(); |
end |
end |
|
repeat (8) @ICard.cb; |
sddata.sendBusy(ICard); |
|
this.bfm.waitUntilReady(); |
this.bfm.sendBusy(); |
|
$display("Ram at write address: %h", ram[addr]); |
|
endtask |
327,8 → 303,8
|
class NoSDCard extends SDCard; |
|
function new(virtual ISdCard CardInterface, event CmdReceived, event InitDone); |
super.new(CardInterface, CmdReceived, InitDone); |
function new(SdBFM bfm); |
super.new(bfm); |
endfunction |
|
task automatic init(); |
/SdBusInterface.sv
0,0 → 1,26
// |
// file: ../../unitSdVerificationTestbench/src/SdCmdInterface.sv |
// author: Rainer Kastl |
// |
// Interface for the SdCmd entity |
// |
|
`ifndef SDBUSINTERFACE_SV |
`define SDBUSINTERFACE_SV |
|
interface ISdBus; |
wire Cmd; |
logic SClk; |
wire[3:0] Data; |
|
clocking cb @(posedge SClk); |
inout Cmd; |
inout Data; |
endclocking |
|
modport card (clocking cb); |
|
endinterface |
|
`endif |
|