library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity sdCtrl_io is port ( -- global clk : in std_logic; reset : in std_logic; -- SDCARD SD_CMD : inout std_logic; SD_WP_N : in std_logic; -- clk in clk_write_edge : in std_logic; clk_read_edge : in std_logic; -- send send_cmd_arg : in std_logic_vector(37 downto 0); send_start : in std_logic; send_in_progress : out std_logic; -- recive recive_mode : in std_logic; -- 0 = 48 / 1 = 136 bit recive_reset : in std_logic; recive_error : out std_logic; recive_ok : out std_logic; recive_cmd : out std_logic_vector(5 downto 0); recive_crc7 : out std_logic_vector(6 downto 0); recive_exp_crc7 : out std_logic_vector(6 downto 0); recive_data : out std_logic_vector(126 downto 0) ); end entity; architecture rtl of sdCtrl_io is component sdCtrl_crc7t is port ( -- global clk : in std_logic; reset : in std_logic; -- dclr : in std_logic; din : in std_logic; din_en : in std_logic; dout : out std_logic_vector(6 downto 0) ); end component; signal crc7_cmd_out_dclr : std_logic := '0'; signal crc7_cmd_out_din : std_logic := '0'; signal crc7_cmd_out_din_en : std_logic := '0'; signal crc7_cmd_out_dout : std_logic_vector(6 downto 0) := (others => '0'); signal crc7_cmd_in_dclr : std_logic := '0'; signal crc7_cmd_in_din : std_logic := '0'; signal crc7_cmd_in_din_en : std_logic := '0'; signal crc7_cmd_in_dout : std_logic_vector(6 downto 0) := (others => '0'); -- write signal cmd_start_write : std_logic := '0'; signal cmd_write_in_progress : std_logic := '0'; signal cmd_write_state : integer range 0 to 48 := 0; -- read signal cmd_read : std_logic_vector(5 downto 0) := (others => '0'); signal crc7_read : std_logic_vector(6 downto 0) := (others => '0'); signal data_read : std_logic_vector(126 downto 0) := (others => '0'); signal exp_crc7_read : std_logic_vector(6 downto 0) := (others => '0'); signal cmd_cnt_read : integer range 0 to 136 := 0; signal sd_read : std_logic := '1'; signal ok_read : std_logic := '0'; signal error_read : std_logic := '0'; begin -- recive recive_cmd <= cmd_read; recive_crc7 <= crc7_read; recive_exp_crc7 <= exp_crc7_read; recive_data <= data_read; recive_error <= error_read; recive_ok <= ok_read; -- send send_in_progress <= cmd_write_in_progress; -- crc7 crc7_cmd_out : sdCtrl_crc7t port map ( clk, reset, crc7_cmd_out_dclr, crc7_cmd_out_din, crc7_cmd_out_din_en, crc7_cmd_out_dout ); crc7_cmd_in : sdCtrl_crc7t port map ( clk, reset, crc7_cmd_in_dclr, crc7_cmd_in_din, crc7_cmd_in_din_en, crc7_cmd_in_dout ); ----------------------------------------------------------------------------------------------------------- -- write out ----------------------------------------------------------------------------------------------------------- process(clk) begin if rising_edge(clk) then if reset = '1' then crc7_cmd_out_din_en <= '0'; crc7_cmd_out_dclr <= '1'; cmd_start_write <= '0'; cmd_write_in_progress <= '0'; cmd_write_state <= 0; SD_CMD <= 'Z'; -- start bit else -- default crc7_cmd_out_din_en <= '0'; crc7_cmd_out_dclr <= '0'; -- start ctrl if send_start = '1' then cmd_start_write <= '1'; cmd_write_in_progress <= '1'; -- in progress cmd_write_state <= 0; crc7_cmd_out_dclr <= '1'; -- clear crc7 end if; -- data ctrl if clk_write_edge = '1' then -- if cmd_write_state = 0 then -- start bit if cmd_start_write = '1' then SD_CMD <= '0'; -- start bit crc7_cmd_out_din <= '0'; -- crc in crc7_cmd_out_din_en <= '1'; -- crc en cmd_start_write <= '0'; -- disable start cmd_write_state <= cmd_write_state + 1; -- next state else SD_CMD <= 'Z'; cmd_write_in_progress<= '0'; -- nothing in progress cmd_write_state <= 0; end if; elsif cmd_write_state = 1 then -- host bit SD_CMD <= '1'; -- host bit crc7_cmd_out_din <= '1'; -- crc in crc7_cmd_out_din_en <= '1'; -- crc en cmd_write_state <= cmd_write_state + 1; -- next state elsif cmd_write_state>=2 and cmd_write_state<=39 then-- cmd and argument SD_CMD <= send_cmd_arg(37-(cmd_write_state-2)); -- data crc7_cmd_out_din <= send_cmd_arg(37-(cmd_write_state-2)); -- crc in crc7_cmd_out_din_en <= '1'; -- crc en cmd_write_state <= cmd_write_state + 1; -- next state elsif cmd_write_state>=40 and cmd_write_state<=46 then -- crc7 SD_CMD <= crc7_cmd_out_dout(6-(cmd_write_state-40)); -- data cmd_write_state <= cmd_write_state + 1; -- next state elsif cmd_write_state=47 then -- stop SD_CMD <= '1'; -- stop cmd_write_state <= 48; -- next state elsif cmd_write_state=48 then -- hiz SD_CMD <= 'Z'; cmd_write_state <= 0; -- next state end if; end if; end if; end if; end process; ----------------------------------------------------------------------------------------------------------- -- get in 48 bit (R1/R3/R6) ----------------------------------------------------------------------------------------------------------- process(clk) begin if rising_edge(clk) then if reset = '1' or recive_reset = '1' then sd_read <= '1'; else sd_read <= SD_CMD; end if; end if; end process; process(clk) begin if rising_edge(clk) then if reset = '1' or recive_reset = '1' then cmd_cnt_read <= 0; error_read <= '0'; ok_read <= '0'; crc7_cmd_in_dclr <= '1'; else -- default crc7_cmd_in_din_en <= '0'; crc7_cmd_in_dclr <= '0'; -- if clk_read_edge = '1' then -- if cmd_cnt_read = 0 then if cmd_write_in_progress = '0' then -- capture not self sended data if sd_read = '0' then -- start bit cmd_cnt_read <= cmd_cnt_read + 1; crc7_cmd_in_din <= sd_read; crc7_cmd_in_din_en <= '1'; end if; end if; end if; if cmd_cnt_read = 1 then if sd_read = '0' then -- transmission bit cmd_cnt_read <= cmd_cnt_read + 1; crc7_cmd_in_din <= sd_read; crc7_cmd_in_din_en <= '1'; else -- wrong transmition goto start(could happen if switch Z is too slow) crc7_cmd_in_dclr <= '1'; -- clear crc cmd_cnt_read <= 0; end if; end if; if cmd_cnt_read>=2 and cmd_cnt_read <=7 then -- 6 bit cmd cmd_read(5-(cmd_cnt_read-2)) <= sd_read; cmd_cnt_read <= cmd_cnt_read + 1; crc7_cmd_in_din <= sd_read; crc7_cmd_in_din_en <= '1'; end if; -- 48 bit if recive_mode = '0' then if cmd_cnt_read>=8 and cmd_cnt_read <=39 then -- 32 bit arg at mode 0 (48 bit) data_read(126-(cmd_cnt_read-8)) <= sd_read; crc7_cmd_in_din <= sd_read; crc7_cmd_in_din_en <= '1'; cmd_cnt_read <= cmd_cnt_read + 1; end if; if cmd_cnt_read>=40 and cmd_cnt_read <=46 then -- 7 bit crc at mode 0 (48 bit) crc7_read(6-(cmd_cnt_read-40)) <= sd_read; cmd_cnt_read <= cmd_cnt_read + 1; end if; else -- 136 bit mode if cmd_cnt_read>=8 and cmd_cnt_read <=134 then data_read(126-(cmd_cnt_read-8)) <= sd_read; cmd_cnt_read <= cmd_cnt_read + 1; end if; end if; if (cmd_cnt_read = 47 and recive_mode = '0') or (cmd_cnt_read = 135 and recive_mode = '1') then -- end bit if sd_read = '1' then cmd_cnt_read <= 0; exp_crc7_read <= crc7_cmd_in_dout; ok_read <= '1'; else error_read <= '1'; -- wrong end bit cmd_cnt_read <= 136; end if; end if; if cmd_cnt_read = 136 then -- error -- nothing to do end if; end if; end if; end if; end process; end rtl;