mirror of
https://github.com/WangXuan95/FPGA-SDcard-Reader.git
synced 2025-01-13 20:02:53 +08:00
134 lines
4.1 KiB
Systemverilog
134 lines
4.1 KiB
Systemverilog
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
// Module : sdcmd_ctrl
|
||
|
// Type : synthesizable, IP's sub module
|
||
|
// Standard: SystemVerilog 2005 (IEEE1800-2005)
|
||
|
// Function: sdcmd signal control,
|
||
|
// instantiated by sd_reader
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
module sdcmd_ctrl (
|
||
|
input wire rstn,
|
||
|
input wire clk,
|
||
|
// SDcard signals (sdclk and sdcmd)
|
||
|
output reg sdclk,
|
||
|
inout sdcmd,
|
||
|
// config clk freq
|
||
|
input wire [15:0] clkdiv,
|
||
|
// user input signal
|
||
|
input wire start,
|
||
|
input wire [15:0] precnt,
|
||
|
input wire [ 5:0] cmd,
|
||
|
input wire [31:0] arg,
|
||
|
// user output signal
|
||
|
output reg busy,
|
||
|
output reg done,
|
||
|
output reg timeout,
|
||
|
output reg syntaxe,
|
||
|
output wire [31:0] resparg
|
||
|
);
|
||
|
|
||
|
initial {busy, done, timeout, syntaxe} = '0;
|
||
|
initial sdclk = '0;
|
||
|
|
||
|
localparam [7:0] TIMEOUT = 8'd250;
|
||
|
|
||
|
reg sdcmdoe = 1'b0;
|
||
|
reg sdcmdout = 1'b1;
|
||
|
|
||
|
// sdcmd tri-state driver
|
||
|
assign sdcmd = sdcmdoe ? sdcmdout : 1'bz;
|
||
|
wire sdcmdin = sdcmdoe ? 1'b1 : sdcmd;
|
||
|
|
||
|
function automatic logic [6:0] CalcCrc7(input logic [6:0] crc, input logic inbit);
|
||
|
return {crc[5:0],crc[6]^inbit} ^ {3'b0,crc[6]^inbit,3'b0};
|
||
|
endfunction
|
||
|
|
||
|
reg [ 5:0] req_cmd = '0; // request[45:40]
|
||
|
reg [31:0] req_arg = '0; // request[39: 8]
|
||
|
reg [ 6:0] req_crc = '0; // request[ 7: 1]
|
||
|
wire [51:0] request = {6'b111101, req_cmd, req_arg, req_crc, 1'b1};
|
||
|
|
||
|
struct packed {
|
||
|
logic st;
|
||
|
logic [ 5:0] cmd;
|
||
|
logic [31:0] arg;
|
||
|
} response = '0;
|
||
|
|
||
|
assign resparg = response.arg;
|
||
|
|
||
|
reg [17:0] clkdivr = '1;
|
||
|
reg [17:0] clkcnt = '0;
|
||
|
reg [15:0] cnt1 = '0;
|
||
|
reg [ 5:0] cnt2 = '1;
|
||
|
reg [ 7:0] cnt3 = '0;
|
||
|
reg [ 7:0] cnt4 = '1;
|
||
|
|
||
|
|
||
|
always @ (posedge clk or negedge rstn)
|
||
|
if(~rstn) begin
|
||
|
{busy, done, timeout, syntaxe} <= '0;
|
||
|
sdclk <= 1'b0;
|
||
|
{sdcmdoe, sdcmdout} <= 2'b01;
|
||
|
{req_cmd, req_arg, req_crc} <= '0;
|
||
|
response <= '0;
|
||
|
clkdivr <= '1;
|
||
|
clkcnt <= '0;
|
||
|
cnt1 <= '0;
|
||
|
cnt2 <= '1;
|
||
|
cnt3 <= '0;
|
||
|
cnt4 <= '1;
|
||
|
end else begin
|
||
|
{done, timeout, syntaxe} <= '0;
|
||
|
|
||
|
clkcnt <= ( clkcnt < {clkdivr[16:0],1'b1} ) ? clkcnt+18'd1 : '0;
|
||
|
|
||
|
if (clkcnt == '0)
|
||
|
clkdivr <= {2'h0, clkdiv} + 18'd1;
|
||
|
|
||
|
if(clkcnt == clkdivr)
|
||
|
sdclk <= 1'b0;
|
||
|
else if(clkcnt == {clkdivr[16:0],1'b1} )
|
||
|
sdclk <= 1'b1;
|
||
|
|
||
|
if(~busy) begin
|
||
|
if(start) busy <= '1;
|
||
|
req_cmd <= cmd;
|
||
|
req_arg <= arg;
|
||
|
req_crc <= '0;
|
||
|
cnt1 <= precnt;
|
||
|
cnt2 <= 6'd51;
|
||
|
cnt3 <= TIMEOUT;
|
||
|
cnt4 <= 8'd134;
|
||
|
end else if(done) begin
|
||
|
busy <= '0;
|
||
|
end else if( clkcnt == clkdivr) begin
|
||
|
{sdcmdoe, sdcmdout} <= 2'b01;
|
||
|
if (cnt1 != '0) begin
|
||
|
cnt1 <= cnt1 - 16'd1;
|
||
|
end else if(cnt2 != '1) begin
|
||
|
cnt2 <= cnt2 - 6'd1;
|
||
|
{sdcmdoe, sdcmdout} <= {1'b1, request[cnt2]};
|
||
|
if(cnt2>=8 && cnt2<48) req_crc <= CalcCrc7(req_crc, request[cnt2]);
|
||
|
end
|
||
|
end else if( clkcnt == {clkdivr[16:0],1'b1} && cnt1=='0 && cnt2=='1 ) begin
|
||
|
if(cnt3 != '0) begin
|
||
|
cnt3 <= cnt3 - 8'd1;
|
||
|
if(~sdcmdin)
|
||
|
cnt3 <= '0;
|
||
|
else if(cnt3 == 8'd1)
|
||
|
{done, timeout, syntaxe} <= 3'b110;
|
||
|
end else if(cnt4 != '1) begin
|
||
|
cnt4 <= cnt4 - 8'd1;
|
||
|
if(cnt4 >= 8'd96)
|
||
|
response <= {response[37:0], sdcmdin};
|
||
|
if(cnt4 == '0) begin
|
||
|
{done, timeout} <= 2'b10;
|
||
|
syntaxe <= response.st || ((response.cmd!=req_cmd) && (response.cmd!='1) && (response.cmd!='0));
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
endmodule
|