FPGA-SDcard-Reader/RTL/sdcmd_ctrl.v

140 lines
4.3 KiB
Coq
Raw Normal View History

2022-09-29 14:19:00 +08:00
//--------------------------------------------------------------------------------------------------------
// Module : sdcmd_ctrl
// Type : synthesizable, IP's sub module
2023-06-08 20:40:07 +08:00
// Standard: Verilog 2001 (IEEE1364-2001)
2022-09-29 14:19:00 +08:00
// 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
);
2023-06-08 20:40:07 +08:00
initial {busy, done, timeout, syntaxe} = 0;
initial sdclk = 1'b0;
2022-09-29 14:19:00 +08:00
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;
2023-06-08 20:40:07 +08:00
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
2022-09-29 14:19:00 +08:00
endfunction
2023-06-08 20:40:07 +08:00
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]
2022-09-29 14:19:00 +08:00
wire [51:0] request = {6'b111101, req_cmd, req_arg, req_crc, 1'b1};
2023-06-08 20:40:07 +08:00
//struct packed {
reg resp_st;
reg [ 5:0] resp_cmd;
reg [31:0] resp_arg;
//} response = 0;
2022-09-29 14:19:00 +08:00
2023-06-08 20:40:07 +08:00
assign resparg = resp_arg;
2022-09-29 14:19:00 +08:00
2023-06-08 20:40:07 +08:00
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;
2022-09-29 14:19:00 +08:00
always @ (posedge clk or negedge rstn)
if(~rstn) begin
2023-06-08 20:40:07 +08:00
{busy, done, timeout, syntaxe} <= 0;
2022-09-29 14:19:00 +08:00
sdclk <= 1'b0;
{sdcmdoe, sdcmdout} <= 2'b01;
2023-06-08 20:40:07 +08:00
{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;
2022-09-29 14:19:00 +08:00
end else begin
2023-06-08 20:40:07 +08:00
{done, timeout, syntaxe} <= 0;
2022-09-29 14:19:00 +08:00
2023-06-08 20:40:07 +08:00
clkcnt <= ( clkcnt < {clkdivr[16:0],1'b1} ) ? (clkcnt+18'd1) : 18'd0;
2022-09-29 14:19:00 +08:00
2023-06-08 20:40:07 +08:00
if (clkcnt == 18'd0)
2022-09-29 14:19:00 +08:00
clkdivr <= {2'h0, clkdiv} + 18'd1;
2023-06-08 20:40:07 +08:00
if (clkcnt == clkdivr)
2022-09-29 14:19:00 +08:00
sdclk <= 1'b0;
2023-06-08 20:40:07 +08:00
else if (clkcnt == {clkdivr[16:0],1'b1} )
2022-09-29 14:19:00 +08:00
sdclk <= 1'b1;
if(~busy) begin
2023-06-08 20:40:07 +08:00
if(start) busy <= 1'b1;
2022-09-29 14:19:00 +08:00
req_cmd <= cmd;
req_arg <= arg;
2023-06-08 20:40:07 +08:00
req_crc <= 0;
2022-09-29 14:19:00 +08:00
cnt1 <= precnt;
cnt2 <= 6'd51;
cnt3 <= TIMEOUT;
cnt4 <= 8'd134;
end else if(done) begin
2023-06-08 20:40:07 +08:00
busy <= 1'b0;
2022-09-29 14:19:00 +08:00
end else if( clkcnt == clkdivr) begin
{sdcmdoe, sdcmdout} <= 2'b01;
2023-06-08 20:40:07 +08:00
if (cnt1 != 16'd0) begin
2022-09-29 14:19:00 +08:00
cnt1 <= cnt1 - 16'd1;
2023-06-08 20:40:07 +08:00
end else if(cnt2 != 6'h3F) begin
2022-09-29 14:19:00 +08:00
cnt2 <= cnt2 - 6'd1;
{sdcmdoe, sdcmdout} <= {1'b1, request[cnt2]};
if(cnt2>=8 && cnt2<48) req_crc <= CalcCrc7(req_crc, request[cnt2]);
end
2023-06-08 20:40:07 +08:00
end else if( clkcnt == {clkdivr[16:0],1'b1} && cnt1==16'd0 && cnt2==6'h3F ) begin
if(cnt3 != 8'd0) begin
2022-09-29 14:19:00 +08:00
cnt3 <= cnt3 - 8'd1;
if(~sdcmdin)
2023-06-08 20:40:07 +08:00
cnt3 <= 8'd0;
2022-09-29 14:19:00 +08:00
else if(cnt3 == 8'd1)
{done, timeout, syntaxe} <= 3'b110;
2023-06-08 20:40:07 +08:00
end else if(cnt4 != 8'hFF) begin
2022-09-29 14:19:00 +08:00
cnt4 <= cnt4 - 8'd1;
if(cnt4 >= 8'd96)
2023-06-08 20:40:07 +08:00
{resp_st, resp_cmd, resp_arg} <= {resp_cmd, resp_arg, sdcmdin};
if(cnt4 == 8'd0) begin
2022-09-29 14:19:00 +08:00
{done, timeout} <= 2'b10;
2023-06-08 20:40:07 +08:00
syntaxe <= resp_st || ((resp_cmd!=req_cmd) && (resp_cmd!=6'h3F) && (resp_cmd!=6'd0));
2022-09-29 14:19:00 +08:00
end
end
end
end
endmodule