mirror of
https://github.com/WangXuan95/FPGA-SDcard-Reader.git
synced 2025-01-13 20:02:53 +08:00
140 lines
4.3 KiB
Verilog
140 lines
4.3 KiB
Verilog
|
|
//--------------------------------------------------------------------------------------------------------
|
|
// Module : sdcmd_ctrl
|
|
// Type : synthesizable, IP's sub module
|
|
// Standard: Verilog 2001 (IEEE1364-2001)
|
|
// 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 = 1'b0;
|
|
|
|
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 [6:0] CalcCrc7;
|
|
input [6:0] crc;
|
|
input [0:0] inbit;
|
|
//function automatic logic [6:0] CalcCrc7(input logic [6:0] crc, input logic inbit);
|
|
begin
|
|
CalcCrc7 = ( {crc[5:0],crc[6]^inbit} ^ {3'b0,crc[6]^inbit,3'b0} );
|
|
end
|
|
endfunction
|
|
|
|
reg [ 5:0] req_cmd = 6'd0; // request[45:40]
|
|
reg [31:0] req_arg = 0; // request[39: 8]
|
|
reg [ 6:0] req_crc = 7'd0; // request[ 7: 1]
|
|
wire [51:0] request = {6'b111101, req_cmd, req_arg, req_crc, 1'b1};
|
|
|
|
//struct packed {
|
|
reg resp_st;
|
|
reg [ 5:0] resp_cmd;
|
|
reg [31:0] resp_arg;
|
|
//} response = 0;
|
|
|
|
assign resparg = resp_arg;
|
|
|
|
reg [17:0] clkdivr = 18'h3FFFF;
|
|
reg [17:0] clkcnt = 0;
|
|
reg [15:0] cnt1 = 0;
|
|
reg [ 5:0] cnt2 = 6'h3F;
|
|
reg [ 7:0] cnt3 = 0;
|
|
reg [ 7:0] cnt4 = 8'hFF;
|
|
|
|
|
|
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;
|
|
{resp_st, resp_cmd, resp_arg} <= 0;
|
|
clkdivr <= 18'h3FFFF;
|
|
clkcnt <= 0;
|
|
cnt1 <= 0;
|
|
cnt2 <= 6'h3F;
|
|
cnt3 <= 0;
|
|
cnt4 <= 8'hFF;
|
|
end else begin
|
|
{done, timeout, syntaxe} <= 0;
|
|
|
|
clkcnt <= ( clkcnt < {clkdivr[16:0],1'b1} ) ? (clkcnt+18'd1) : 18'd0;
|
|
|
|
if (clkcnt == 18'd0)
|
|
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'b1;
|
|
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 <= 1'b0;
|
|
end else if( clkcnt == clkdivr) begin
|
|
{sdcmdoe, sdcmdout} <= 2'b01;
|
|
if (cnt1 != 16'd0) begin
|
|
cnt1 <= cnt1 - 16'd1;
|
|
end else if(cnt2 != 6'h3F) 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==16'd0 && cnt2==6'h3F ) begin
|
|
if(cnt3 != 8'd0) begin
|
|
cnt3 <= cnt3 - 8'd1;
|
|
if(~sdcmdin)
|
|
cnt3 <= 8'd0;
|
|
else if(cnt3 == 8'd1)
|
|
{done, timeout, syntaxe} <= 3'b110;
|
|
end else if(cnt4 != 8'hFF) begin
|
|
cnt4 <= cnt4 - 8'd1;
|
|
if(cnt4 >= 8'd96)
|
|
{resp_st, resp_cmd, resp_arg} <= {resp_cmd, resp_arg, sdcmdin};
|
|
if(cnt4 == 8'd0) begin
|
|
{done, timeout} <= 2'b10;
|
|
syntaxe <= resp_st || ((resp_cmd!=req_cmd) && (resp_cmd!=6'h3F) && (resp_cmd!=6'd0));
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
endmodule
|