Added command signal driver module
All checks were successful
ci/woodpecker/push/test-workflow Pipeline was successful
All checks were successful
ci/woodpecker/push/test-workflow Pipeline was successful
This commit is contained in:
parent
71f08bdf15
commit
e32563131f
30
SDVD.xpr
30
SDVD.xpr
@ -45,7 +45,7 @@
|
||||
<Option Name="SimulatorGccVersionActiveHdl" Val="9.3.0"/>
|
||||
<Option Name="BoardPart" Val=""/>
|
||||
<Option Name="SourceMgmtMode" Val="DisplayOnly"/>
|
||||
<Option Name="ActiveSimSet" Val="crc_gen_tb"/>
|
||||
<Option Name="ActiveSimSet" Val="send_command_tb"/>
|
||||
<Option Name="DefaultLib" Val="xil_defaultlib"/>
|
||||
<Option Name="ProjectType" Val="Default"/>
|
||||
<Option Name="IPRepoPath" Val="$PPRDIR/../../../fpga/vivado-library"/>
|
||||
@ -61,7 +61,7 @@
|
||||
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
|
||||
<Option Name="EnableBDX" Val="FALSE"/>
|
||||
<Option Name="DSABoardId" Val="nexys-a7-100t"/>
|
||||
<Option Name="WTXSimLaunchSim" Val="138"/>
|
||||
<Option Name="WTXSimLaunchSim" Val="145"/>
|
||||
<Option Name="WTModelSimLaunchSim" Val="0"/>
|
||||
<Option Name="WTQuestaLaunchSim" Val="0"/>
|
||||
<Option Name="WTIesLaunchSim" Val="0"/>
|
||||
@ -483,6 +483,32 @@
|
||||
<Option Name="xsim.simulate.runtime" Val="1s"/>
|
||||
</Config>
|
||||
</FileSet>
|
||||
<FileSet Name="send_command_tb" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/send_command_tb" RelGenDir="$PGENDIR/send_command_tb">
|
||||
<File Path="$PPRDIR/verification/sd/send_command_tb.sv">
|
||||
<FileInfo>
|
||||
<Attr Name="UsedIn" Val="synthesis"/>
|
||||
<Attr Name="UsedIn" Val="implementation"/>
|
||||
<Attr Name="UsedIn" Val="simulation"/>
|
||||
</FileInfo>
|
||||
</File>
|
||||
<Config>
|
||||
<Option Name="DesignMode" Val="RTL"/>
|
||||
<Option Name="TopModule" Val="send_command_tb"/>
|
||||
<Option Name="TopLib" Val="xil_defaultlib"/>
|
||||
<Option Name="TransportPathDelay" Val="0"/>
|
||||
<Option Name="TransportIntDelay" Val="0"/>
|
||||
<Option Name="SelectedSimModel" Val="rtl"/>
|
||||
<Option Name="PamDesignTestbench" Val=""/>
|
||||
<Option Name="PamDutBypassFile" Val="xil_dut_bypass"/>
|
||||
<Option Name="PamSignalDriverFile" Val="xil_bypass_driver"/>
|
||||
<Option Name="PamPseudoTop" Val="pseudo_tb"/>
|
||||
<Option Name="SrcSet" Val="sources_1"/>
|
||||
<Option Name="CosimPdi" Val=""/>
|
||||
<Option Name="CosimPlatform" Val=""/>
|
||||
<Option Name="CosimElf" Val=""/>
|
||||
<Option Name="xsim.simulate.runtime" Val="1s"/>
|
||||
</Config>
|
||||
</FileSet>
|
||||
</FileSets>
|
||||
<Simulators>
|
||||
<Simulator Name="XSim">
|
||||
|
||||
@ -1,14 +1,103 @@
|
||||
module send_command(
|
||||
input clk,
|
||||
// The crc should be clocked way faster than the sender
|
||||
input crc_clk,
|
||||
input reset,
|
||||
input start,
|
||||
input [5:0] command,
|
||||
input [31:0] arguments
|
||||
input [31:0] arguments,
|
||||
output logic ready,
|
||||
output logic sd_cmd
|
||||
);
|
||||
|
||||
logic [47:0] to_send;
|
||||
|
||||
logic crc_start;
|
||||
wire crc_ready;
|
||||
logic [6:0] crc;
|
||||
|
||||
logic [$clog2(48):0] counter;
|
||||
|
||||
logic send_sd_cmd;
|
||||
|
||||
enum logic [2:0] {READY, SEND_CRC, DELAY, WAIT_CRC, SEND_DATA} cur_state, next_state;
|
||||
|
||||
// We theoretically could speed up sd card initialization by hardcoding the
|
||||
// CRCs for it, but wasting an extra couple of cycles at 400khz shouldn't
|
||||
// really matter
|
||||
crc_gen crcGen(crc_clk,reset,crc_start,to_send[47-:40],crc_ready,crc);
|
||||
|
||||
// State transitions
|
||||
always_comb begin
|
||||
case (cur_state)
|
||||
READY:
|
||||
if (start)
|
||||
next_state = SEND_CRC;
|
||||
else
|
||||
next_state = READY;
|
||||
SEND_CRC:
|
||||
next_state = DELAY;
|
||||
DELAY:
|
||||
next_state = WAIT_CRC;
|
||||
WAIT_CRC:
|
||||
if (crc_ready)
|
||||
next_state = SEND_DATA;
|
||||
else
|
||||
next_state = WAIT_CRC;
|
||||
SEND_DATA:
|
||||
if (counter != 0)
|
||||
next_state = SEND_DATA;
|
||||
else
|
||||
next_state = READY;
|
||||
default:
|
||||
next_state = READY;
|
||||
endcase
|
||||
|
||||
end
|
||||
|
||||
assign sd_cmd = send_sd_cmd ? 'z : 0;
|
||||
assign ready = (cur_state == READY);
|
||||
// Sequential logic
|
||||
always_ff @(posedge clk) begin
|
||||
// Default to high-z
|
||||
send_sd_cmd <= 1;
|
||||
|
||||
case (cur_state)
|
||||
READY:
|
||||
begin
|
||||
counter <= 48;
|
||||
end
|
||||
SEND_CRC:
|
||||
begin
|
||||
to_send <= {1'b0, 1'b1, command, arguments, 8'b1};
|
||||
crc_start <= 1;
|
||||
end
|
||||
|
||||
DELAY:
|
||||
crc_start <= 0;
|
||||
WAIT_CRC:
|
||||
to_send[7:1] <= crc;
|
||||
|
||||
SEND_DATA:
|
||||
begin
|
||||
counter <= counter - 1;
|
||||
send_sd_cmd <= to_send[counter-1];
|
||||
end
|
||||
|
||||
default: ;
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (reset) begin
|
||||
cur_state <= READY;
|
||||
counter <= 48;
|
||||
end
|
||||
else begin
|
||||
cur_state <= next_state;
|
||||
end
|
||||
end
|
||||
|
||||
// Some commands have hardcoded crcs, and as such they can be found in a LUT,
|
||||
// otherwise we need to shell out to the crc module and wait a while for it to
|
||||
// run
|
||||
|
||||
endmodule
|
||||
|
||||
@ -26,3 +26,7 @@
|
||||
- clocked too slow
|
||||
- initial goal of 16-bit audio isn't feasible because 100MHz isn't fast enough
|
||||
to pwm based on a 16-bit counter, would give a sample rate of 1.5khz
|
||||
|
||||
### command_sender
|
||||
- output ready signal was delay a cycle because it was set by sequential logic,
|
||||
detected in testing, changed it to a combinational output for 1 cycle speedup
|
||||
|
||||
63
verification/sd/send_command_tb.sv
Normal file
63
verification/sd/send_command_tb.sv
Normal file
@ -0,0 +1,63 @@
|
||||
module send_command_tb;
|
||||
|
||||
bit clk;
|
||||
// The crc should be clocked way faster than the sender
|
||||
bit crc_clk;
|
||||
logic reset;
|
||||
logic start;
|
||||
logic [5:0] command;
|
||||
logic [31:0] arguments;
|
||||
wire ready;
|
||||
wire sd_cmd;
|
||||
|
||||
logic [47:0] fill_me;
|
||||
int counter;
|
||||
|
||||
logic sd_cmd_real;
|
||||
|
||||
assign sd_cmd_real = (sd_cmd === 'z) ? 1 : 0;
|
||||
|
||||
send_command dut(.*);
|
||||
|
||||
initial forever #100 clk = ~clk;
|
||||
initial forever #20 crc_clk = ~crc_clk;
|
||||
|
||||
|
||||
|
||||
initial begin
|
||||
reset = 1;
|
||||
start = 0;
|
||||
|
||||
repeat (2) @(posedge clk);
|
||||
|
||||
reset = 0;
|
||||
@(posedge clk);
|
||||
|
||||
start = 1;
|
||||
command = 8;
|
||||
arguments = 'h1AA;
|
||||
|
||||
counter = 48;
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
// Try receiving the CMD8
|
||||
while (counter != 0) begin
|
||||
// Check for the start bit, or that we're receiving a message
|
||||
if (sd_cmd_real != 1 || counter != 48) begin
|
||||
fill_me = {fill_me[46:0], sd_cmd_real};
|
||||
counter--;
|
||||
end
|
||||
@(posedge clk);
|
||||
end
|
||||
|
||||
assert (fill_me === {2'b01, 6'd8, 32'h1AA, 8'h87})
|
||||
else $error("Received wrong command, got 0x%x",fill_me);
|
||||
|
||||
assert (ready)
|
||||
else $error("SD command sender not ready");
|
||||
|
||||
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Loading…
x
Reference in New Issue
Block a user