FPGA-SDcard-Reader/RTL/sdcmd_ctrl.sv
WangXuan95 c561f2def9 update
2022-09-29 14:19:00 +08:00

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