OpenCores
URL https://opencores.org/ocsvn/sd_mmc_emulator/sd_mmc_emulator/trunk

Subversion Repositories sd_mmc_emulator

[/] [sd_mmc_emulator/] [trunk/] [rtl/] [sd_host_pack.vhd] - Rev 2

Compare with Previous | Blame | View Log

--------------------------------------------------------------------------
-- Package containing SD Card interface modules,
-- and related support modules.
--
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
package sd_host_pack is
 
-- Constants relating to the SD Card interface
 
  -- Register size constants
constant BLKSIZE_W    : integer := 12;
constant BLKCNT_W     : integer := 16;
 
  -- cmd module interrupts
constant INT_CMD_CC    : integer := 0;
constant INT_CMD_EI    : integer := 1;
constant INT_CMD_CTE   : integer := 2;
constant INT_CMD_CCRCE : integer := 3;
constant INT_CMD_CIE   : integer := 4;
constant INT_CMD_SIZE  : integer := 5; -- Size of register field, in bits
 
  -- data module interrupts
constant INT_DATA_CC    : integer := 0;
constant INT_DATA_CCRCE : integer := 1;
constant INT_DATA_CFE   : integer := 2;
constant INT_DATA_SIZE  : integer := 3; -- Size of register field, in bits
 
  component sd_cmd_host
  port(
    sys_rst      : in  std_logic;
    sd_clk       : in  std_logic;
    -- Control and settings
    start_i      : in  std_logic;
    int_rst_i    : in std_logic;
    busy_i       : in  std_logic; --direct signal from data sd data input (data[0])
    cmd_index_i  : in  unsigned(5 downto 0);
    argument_i   : in  unsigned(31 downto 0);
    timeout_i    : in  unsigned(15 downto 0);
    int_status_o : out unsigned(4 downto 0);
    response_0_o : out unsigned(31 downto 0);
    response_1_o : out unsigned(31 downto 0);
    response_2_o : out unsigned(31 downto 0);
    response_3_o : out unsigned(31 downto 0);
    -- SD/MMC card command signals
    sd_cmd_i     : in  std_logic;
    sd_cmd_o     : out std_logic;
    sd_cmd_oe_o  : out std_logic
  );
  end component;
 
  component sd_data_8bit_host
  port(
    sd_clk        : in  std_logic;
    sys_rst       : in  std_logic;
    --Tx Fifo
    tx_dat_i      : in  unsigned(7 downto 0);
    tx_dat_rd_o   : out std_logic;
    --Rx Fifo
    rx_dat_o      : out unsigned(7 downto 0);
    rx_dat_we_o   : out std_logic;
    --SD data
    sd_dat_siz_o  : out unsigned(1 downto 0);
    sd_dat_oe_o   : out std_logic;
    sd_dat_o      : out unsigned(7 downto 0);
    sd_dat_i      : in  unsigned(7 downto 0);
    --Control signals
    blksize_i     : in  unsigned(BLKSIZE_W-1 downto 0);
    bus_size_i    : in  unsigned(1 downto 0);
    blkcnt_i      : in  unsigned(BLKCNT_W-1 downto 0);
    d_stop_i      : in  std_logic;
    d_read_i      : in  std_logic;
    d_write_i     : in  std_logic;
    bustest_w_i   : in  std_logic;
    bustest_r_i   : in  std_logic;
    bustest_res_o : out unsigned(2 downto 0);
    sd_dat_busy_o : out std_logic;
    fsm_busy_o    : out std_logic;
    crc_ok_o      : out std_logic
  );
  end component;
 
  component sd_controller_8bit_bram
  port (
    -- WISHBONE common
    wb_clk_i     : in  std_logic;
    wb_rst_i     : in  std_logic;
    -- WISHBONE slave (register interface)
    wb_dat_i     : in  unsigned(31 downto 0);
    wb_dat_o     : out unsigned(31 downto 0);
    wb_adr_i     : in  unsigned(3 downto 0);
    wb_we_i      : in  std_logic;
    wb_cyc_i     : in  std_logic;
    wb_ack_o     : out std_logic;
    -- Dedicated BRAM port without acknowledge.
    -- Access cycles must complete immediately.
    -- (data to cross clock domains by this dual-ported BRAM)
    bram_clk_o   : out std_logic; -- Same as sd_clk_o_pad
    bram_dat_o   : out unsigned(7 downto 0);
    bram_dat_i   : in  unsigned(7 downto 0);
    bram_adr_o   : out unsigned(31 downto 0);
    bram_we_o    : out std_logic;
    bram_cyc_o   : out std_logic;
    --SD Card Interface
    sd_cmd_i     : in  std_logic;
    sd_cmd_o     : out std_logic;
    sd_cmd_oe_o  : out std_logic;
    sd_dat_i     : in  unsigned(7 downto 0);
    sd_dat_o     : out unsigned(7 downto 0);
    sd_dat_oe_o  : out std_logic;
    sd_dat_siz_o : out unsigned(1 downto 0);
    sd_clk_o_pad : out std_logic;
    -- Interrupt outputs
    int_cmd_o    : out std_logic;
    int_data_o   : out std_logic
  );
  end component;
 
end sd_host_pack;
 
package body sd_host_pack is
end sd_host_pack;
 
-------------------------------------------------------------------------------
-- SD/MMC Command Host
-------------------------------------------------------------------------------
--
-- Author: John Clayton
-- Update: June 11, 2016 Combined sd_cmd_master with sd_cmd_serial_host from
--                       the opencores.org VHDL code, in order to make this
--                       unit.  The reason for combining them is that eight
--                       interface signals were shared only between those two
--                       modules when they were instantiated, and they are not
--                       needed individually.
--
-- Description
-------------------------------------------------------------------------------
-- This module handles generating the serial SD/MMC command output, and
-- receiving the SD/MMC responses from the card.
--
-- This unit runs entirely within the sd_clk_i clock domain.
--
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
library work;
use work.ucrc_pack.all;
use work.sd_host_pack.all;
 
entity sd_cmd_host is
  port(
    sys_rst      : in  std_logic;
    sd_clk       : in  std_logic;
    -- Control and settings
    start_i      : in  std_logic;
    int_rst_i    : in std_logic;
    busy_i       : in  std_logic; --direct signal from data sd data input (data[0])
    cmd_index_i  : in  unsigned(5 downto 0);
    argument_i   : in  unsigned(31 downto 0);
    timeout_i    : in  unsigned(15 downto 0);
    int_status_o : out unsigned(4 downto 0);
    response_0_o : out unsigned(31 downto 0);
    response_1_o : out unsigned(31 downto 0);
    response_2_o : out unsigned(31 downto 0);
    response_3_o : out unsigned(31 downto 0);
    -- SD/MMC card command signals
    sd_cmd_i     : in  std_logic;
    sd_cmd_o     : out std_logic;
    sd_cmd_oe_o  : out std_logic
  );
end sd_cmd_host;
 
architecture beh of sd_cmd_host is
 
---------------Internal Constants-------------
constant INIT_DELAY   : integer := 4;
constant BITS_TO_SEND : integer := 48;
constant CMD_SIZE     : integer := 40;
constant RESP_SIZE    : integer := 128;
 
-----------------Internal Signals-----------
signal cmd_dat_reg   : std_logic;
signal resp_len      : integer;
signal cmd_buff      : unsigned(CMD_SIZE-1 downto 0);
signal resp_buff     : unsigned(RESP_SIZE-1 downto 0);
signal resp_idx      : integer;
  --CRC related
signal crc_rst_n  : std_logic;
signal crc_in     : unsigned(6 downto 0);
signal crc_val    : unsigned(6 downto 0);
signal crc_enable : std_logic;
signal crc_bit    : std_logic;
signal crc_ok     : std_logic;
  --Internal Counters
signal counter    : integer;
  --State Machines
type SERIAL_STATE_TYPE is (INIT, IDLE, SETUP_CRC, WRITE, READ_WAIT, READ, FINISH_WR);
signal serial_state : SERIAL_STATE_TYPE;
type CMD_STATE_TYPE is (IDLE, EXECUTE, BUSY_WAIT);
signal cmd_state    : CMD_STATE_TYPE;
 
signal expect_response : std_logic;
signal watchdog        : unsigned(15 downto 0);
 
-- Signals originally from sd_cmd_master (DELETE THIS COMMENT SOON)
signal timeout_reg : unsigned(15 downto 0);
signal int_status_reg  : unsigned(4 downto 0);
 
begin
 
-- Form a signal indicating when a response is expected
expect_response <= '0' when (cmd_index_i=0 or cmd_index_i=4 or cmd_index_i=15) else '1';
 
-- Command Finite State Machine
cmd_fsm_proc : process(sys_rst,sd_clk)
begin
  if (sys_rst='1') then
    response_0_o <= (others=>'0');
    response_1_o <= (others=>'0');
    response_2_o <= (others=>'0');
    response_3_o <= (others=>'0');
    int_status_reg  <= (others=>'0');
    resp_len    <= 0;
    watchdog    <= (others=>'0');
    timeout_reg <= (others=>'0');
    cmd_state   <= IDLE;
    cmd_buff    <= (others=>'0');
  elsif (sd_clk'event and sd_clk='1') then
    watchdog <= watchdog+1;
    case (cmd_state) is
      when IDLE =>
        -- Only CMD2, CMD9 and CMD10 have long responses...
        if (cmd_index_i=2 or cmd_index_i=9 or cmd_index_i=10) then
          resp_len <= 127;
        else
          resp_len <= 39;
        end if;
        cmd_buff(39 downto 38) <= "01";
        cmd_buff(37 downto 32) <= cmd_index_i;
        cmd_buff(31 downto 0)  <= argument_i; --CMD_Argument
        timeout_reg <= timeout_i;
        watchdog <= (others=>'0');
        if (start_i='1') then
            int_status_reg <= (others=>'0');
        end if;
        -- State transition
        if (start_i='1') then
          response_0_o <= (others=>'0');
          response_1_o <= (others=>'0');
          response_2_o <= (others=>'0');
          response_3_o <= (others=>'0');
          cmd_state <= EXECUTE;
        end if;
 
      when EXECUTE =>
        if (watchdog > timeout_reg) then
          int_status_reg(INT_CMD_CTE) <= '1';
          int_status_reg(INT_CMD_EI) <= '1';
          response_0_o <= to_unsigned(16#55555555#,32);
          response_1_o <= to_unsigned(16#55555555#,32);
          response_2_o <= to_unsigned(16#55555555#,32);
          response_3_o <= to_unsigned(16#55555555#,32);
          cmd_state <= IDLE;
        else --Incoming New Status
          if (serial_state=FINISH_WR) then --Data available
            -- CMD1 has "1111111" for the CRC field...
            if (cmd_index_i/=1 and crc_ok='0') then
              int_status_reg(INT_CMD_CCRCE) <= '1';
              int_status_reg(INT_CMD_EI) <= '1';
            end if;
            if (resp_len=39 and cmd_index_i/=1 and cmd_buff(37 downto 32)/=resp_buff(125 downto 120)) then
              int_status_reg(INT_CMD_CIE) <= '1';
              int_status_reg(INT_CMD_EI) <= '1';
            end if;
            int_status_reg(INT_CMD_CC) <= '1';
            if (expect_response/='0') then
              response_0_o <= resp_buff(119 downto 88);
              response_1_o <= resp_buff(87 downto 56);
              response_2_o <= resp_buff(55 downto 24);
              response_3_o <= resp_buff(23 downto 0) & "00000000";
            end if;
            -- end
          end if; --Data avaible
        end if; --Status change
        -- State transition
        if (watchdog > timeout_reg) then
          cmd_state <= IDLE;
        elsif (serial_state=FINISH_WR) then
          cmd_state <= BUSY_WAIT;
        end if;
 
      when BUSY_WAIT =>
        if (watchdog > timeout_reg) then
          int_status_reg(INT_CMD_CTE) <= '1';
          int_status_reg(INT_CMD_EI) <= '1';
          cmd_state <= IDLE;
        end if;
        -- State transition
        if (busy_i='0') then
          cmd_state <= IDLE;
        end if;
 
      when others =>
        cmd_state <= IDLE;
 
    end case;
 
    if (int_rst_i='1') then
      int_status_reg <= (others=>'0');
    end if;
 
  end if;
end process;
int_status_o <= int_status_reg;
 
 
 
--sd cmd input pad register
process(sd_clk, sys_rst)  -- JLC added sys_rst to sensitivity list.
begin
  if (sys_rst='1') then
    cmd_dat_reg <= '0';
--  elsif (sd_clk'event and sd_clk='0') then -- use falling edge, when data is stable
  elsif (sd_clk'event and sd_clk='0') then -- use rising edge, per the specification
    cmd_dat_reg <= sd_cmd_i;
  end if;
end process;
 
--------------------------------------------
-- CRC generator
 
  crc0 : ucrc_ser
  generic map (
    POLYNOMIAL => "0001001",
    INIT_VALUE => "0000000"
  )
  port map (
    -- System clock and asynchronous reset
    sys_clk    => sd_clk,
    sys_rst_n  => crc_rst_n,
    sys_clk_en => crc_enable,
 
    -- Input and Control
    clear_i    => '0',
    data_i     => crc_bit,
    flush_i    => '0',
 
    -- Output
    match_o    => open,
    crc_o      => crc_val
  );
 
--------------------------------------------
-- This is the serial_state machine
--------------------------------------------
serial_fsm_proc : process(sd_clk, sys_rst)
begin
  if (sys_rst='1') then
    serial_state <= INIT;
    crc_enable   <= '0';
    resp_idx     <= 0;
    sd_cmd_oe_o  <= '1';
    sd_cmd_o     <= '1';
    resp_buff    <= (others=>'0');
    crc_rst_n    <= '0';
    crc_bit      <= '0';
    crc_in       <= (others=>'0');
    crc_ok       <= '0';
    counter      <= 0;
  elsif (sd_clk'event and sd_clk='1') then
 
    case (serial_state) is
 
      when INIT =>
        counter <= counter+1;
        sd_cmd_oe_o <= '1';
        sd_cmd_o    <= '1';
        if (counter >= INIT_DELAY) then
          serial_state <= IDLE;
        end if;
 
      when IDLE =>
        sd_cmd_oe_o <= '0'; --Put CMD to Z
        counter    <= 0;
        crc_rst_n  <= '0';
        crc_enable <= '0';
        resp_idx   <= 0;
        if (start_i='1') then
          serial_state <= SETUP_CRC;
          resp_buff    <= (others=>'0');
        end if;
 
      when SETUP_CRC =>
        crc_rst_n  <= '1';
        crc_enable <= '1';
        crc_bit    <= cmd_buff(CMD_SIZE-1-counter);
        serial_state <= WRITE;
 
      when WRITE =>
        if (counter < BITS_TO_SEND-8) then  -- 1->40 CMD, (41 <= CNT <=47) CRC, 48 stop_bit
          sd_cmd_oe_o <= '1';
          sd_cmd_o    <= cmd_buff(CMD_SIZE-1-counter);
          if (counter < BITS_TO_SEND-9) then --1 step ahead
            crc_bit <= cmd_buff((CMD_SIZE-1-counter)-1);
          else
            crc_enable <= '0';
          end if;
        elsif (counter < BITS_TO_SEND-1) then
          crc_enable  <= '0';
          sd_cmd_o    <= crc_val(BITS_TO_SEND-counter-2);
          sd_cmd_oe_o <= '1';
        elsif (counter = BITS_TO_SEND-1) then
          sd_cmd_oe_o <= '1';
          sd_cmd_o    <= '1';
        else
          sd_cmd_oe_o <= '0';
          sd_cmd_o    <= '1';
        end if;
        counter <= counter+1;
 
        if (counter >= BITS_TO_SEND and expect_response='1') then
          serial_state <= READ_WAIT;
        elsif (counter >= BITS_TO_SEND) then
          serial_state <= FINISH_WR;
        end if;
 
      when READ_WAIT =>
        crc_enable  <= '0';
        crc_rst_n   <= '0';
        counter     <= 1;
        sd_cmd_oe_o <= '0';
        resp_buff(RESP_SIZE-1) <= cmd_dat_reg;
        if (cmd_dat_reg='0') then
          serial_state <= READ;
        end if;
 
      when READ =>
        crc_rst_n <= '1';
        if ((resp_len/=RESP_SIZE-1) or (counter>7)) then
          crc_enable <= '1';
        end if;
        sd_cmd_oe_o <= '0';
        if (counter <= resp_len) then
          if (counter < 8) then --1+1+6 (S,T,Index)
            resp_buff(RESP_SIZE-1-counter) <= cmd_dat_reg;
          else
            resp_idx <= resp_idx + 1;
            resp_buff(RESP_SIZE-9-resp_idx) <= cmd_dat_reg;
          end if;
          crc_bit <= cmd_dat_reg;
        elsif (counter-resp_len <= 7) then
          crc_in((resp_len+7)-counter) <= cmd_dat_reg;
          crc_enable <= '0';
        else
          crc_enable <= '0';
          if (crc_in = crc_val) then
            crc_ok <= '1';
          else
            crc_ok <= '0';
          end if;
        end if;
        counter <= counter + 1;
        if (counter >= resp_len+8) then
          serial_state <= FINISH_WR;
        end if;
 
      when FINISH_WR =>
        crc_enable   <= '0';
        crc_rst_n    <= '0';
        counter      <= 0;
        sd_cmd_oe_o  <= '0';
        serial_state <= IDLE;
 
      when others =>
        serial_state <= INIT;
 
    end case;
 
  end if;
end process;
 
end beh;
 
----------------------------------------------------------------------
----                                                              ----
---- WISHBONE SD Card Controller IP Core                          ----
----                                                              ----
---- sd_data_8bit_host.vhd                                        ----
----                                                              ----
---- This file is part of the WISHBONE SD Card                    ----
---- Controller IP Core project                                   ----
---- http:--opencores.org/project,sd_card_controller              ----
----                                                              ----
---- Description                                                  ----
---- Module resposible for sending and receiving data through     ----
---- sd/mmc card data interface                                   ----
----                                                              ----
---- Author(s):                                                   ----
----     - John Clayton, morianton@gmail.com                      ----
----                                                              ----
----------------------------------------------------------------------
----                                                              ----
---- Copyright (C) 2016 Authors                                   ----
----                                                              ----
---- Based on original work by                                    ----
----     Adam Edvardsson (adam.edvardsson@orsoc.se)               ----
----                                                              ----
----     Copyright (C) 2009 Authors                               ----
----                                                              ----
---- This source file may be used and distributed without         ----
---- restriction provided that this copyright statement is not    ----
---- removed from the file and that any derivative work contains  ----
---- the original copyright notice and the associated disclaimer. ----
----                                                              ----
---- This source file is free software; you can redistribute it   ----
---- and/or modify it under the terms of the GNU Lesser General   ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any   ----
---- later version.                                               ----
----                                                              ----
---- This source is distributed in the hope that it will be       ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied   ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ----
---- PURPOSE. See the GNU Lesser General Public License for more  ----
---- details.                                                     ----
----                                                              ----
---- You should have received a copy of the GNU Lesser General    ----
---- Public License along with this source; if not, download it   ----
---- from http:--www.opencores.org/lgpl.shtml                     ----
----                                                              ----
-- Author: John Clayton                                             --
-- Update: June 11, 2016 Added bustest_w_i and bustest_r_i, plus    --
--                       bustest_res_o result output.               --
----                                                              ----
----------------------------------------------------------------------
--
-- Explanation:
--   bustest_res_o values are:
--     000 = BUSTEST_R (CMD14) not yet performed
--     001 = 1 bit data width
--     010 = 4 bit data width
--     011 = 8 bit data width
--     100 = Unspecified Error
--
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
library work;
use work.sd_host_pack.all;
use work.ucrc_pack.all;
 
entity sd_data_8bit_host is
  port(
    sd_clk        : in  std_logic;
    sys_rst       : in  std_logic;
    --Tx Fifo
    tx_dat_i      : in  unsigned(7 downto 0);
    tx_dat_rd_o   : out std_logic;
    --Rx Fifo
    rx_dat_o      : out unsigned(7 downto 0);
    rx_dat_we_o   : out std_logic;
    --SD data
    sd_dat_siz_o  : out unsigned(1 downto 0);
    sd_dat_oe_o   : out std_logic;
    sd_dat_o      : out unsigned(7 downto 0);
    sd_dat_i      : in  unsigned(7 downto 0);
    --Control signals
    blksize_i     : in  unsigned(BLKSIZE_W-1 downto 0);
    bus_size_i    : in  unsigned(1 downto 0);
    blkcnt_i      : in  unsigned(BLKCNT_W-1 downto 0);
    d_stop_i      : in  std_logic;
    d_read_i      : in  std_logic;
    d_write_i     : in  std_logic;
    bustest_w_i   : in  std_logic;
    bustest_r_i   : in  std_logic;
    bustest_res_o : out unsigned(2 downto 0);
    sd_dat_busy_o : out std_logic;
    fsm_busy_o    : out std_logic;
    crc_ok_o      : out std_logic
  );
end sd_data_8bit_host;
 
architecture beh of sd_data_8bit_host is
 
-- Internal constants
 
-- Internal signals
signal dat_reg      : unsigned(7 downto 0);
signal data_cycles  : unsigned(BLKSIZE_W+2 downto 0);
signal bus_size_reg : unsigned(1 downto 0);
--CRC16
signal crc_in     : unsigned(7 downto 0);
signal crc_enable : std_logic;
signal crc_rst_n  : std_logic;
type crc_out_type is
  array (integer range 0 to 7) of unsigned(15 downto 0);
signal crc_out    : crc_out_type;
signal crc_ok_l   : std_logic;
signal transf_cnt : unsigned(BLKSIZE_W+3 downto 0);
  --State Machine
type FSM_STATE_TYPE is (IDLE, WRITE_DAT, CHECK_CRC_STATUS, WRITE_BUSY,
                        READ_WAIT, READ_DAT,  SEND_BUSTEST,
                        READ_BUSTEST_WAIT, READ_BUSTEST, ANALYZE_BUSTEST);
signal state : FSM_STATE_TYPE;
 
signal crc_s_cnt  : unsigned(2 downto 0);
signal busy_int   : std_logic;
signal blkcnt_reg : unsigned(BLKCNT_W-1 downto 0);
signal start_bit  : std_logic;
signal crc_c      : unsigned(4 downto 0);
signal crc_s      : unsigned(3 downto 0);
signal data_index : unsigned(2 downto 0);
signal last_din   : unsigned(7 downto 0);
 
signal bustest_0  : unsigned(7 downto 0);
signal bustest_1  : unsigned(7 downto 0);
signal bustest_x  : unsigned(7 downto 0);
 
begin
 
--sd data input pad register
process(sd_clk)
begin
  if (sd_clk'event and sd_clk='1') then
    dat_reg <= sd_dat_i;
  end if;
end process;
 
-- There are eight different CRC generators
sd_crc_gen : for nvar in 0 to 7 generate
begin
  crc_unit : ucrc_ser
  generic map (
    POLYNOMIAL => "0001000000100001",
    INIT_VALUE => "0000000000000000"
  )
  port map (
    -- System clock and asynchronous reset
    sys_clk    => sd_clk,
    sys_rst_n  => crc_rst_n,
    sys_clk_en => crc_enable,
 
    -- Input and Control
    clear_i    => '0',
    data_i     => crc_in(nvar),
    flush_i    => '0',
 
    -- Output
    match_o    => open,
    crc_o      => crc_out(nvar)
  );
end generate;
 
crc_ok_o   <= crc_ok_l;
fsm_busy_o <= '1' when (state/=IDLE) else '0';
start_bit  <= '1' when (dat_reg(0)='0') else '0';
sd_dat_busy_o <= '1' when (dat_reg(0)='0') else '0';
-- Provide external bus size signals, for controlling data bus tri-states
sd_dat_siz_o <= "10" when state=SEND_BUSTEST else bus_size_i;
 
-- Create bus test analysis, by XORing the two returned patterns
-- together.
bustest_x <= bustest_0 xor bustest_1;
 
fsm_proc : process(sys_rst,sd_clk)
begin
  if (sys_rst='1') then
    state <= IDLE;
    sd_dat_oe_o <= '0';
    crc_enable <= '0';
    crc_rst_n <= '0';
    transf_cnt <= (others=>'0');
    tx_dat_rd_o <= '0';
    last_din <= (others=>'0');
    crc_c <= (others=>'0');
    crc_in <= (others=>'0');
    sd_dat_o <= (others=>'0');
    crc_s_cnt <= (others=>'0');
    crc_s <= (others=>'0');
    rx_dat_we_o <= '0';
    rx_dat_o <= (others=>'0');
    crc_ok_l <= '0';
    busy_int <= '0';
    data_index <= (others=>'0');
    blkcnt_reg <= (others=>'0');
    data_cycles <= (others=>'0');
    bus_size_reg <= (others=>'0');
    bustest_0 <= (others=>'0');
    bustest_1 <= (others=>'0');
    bustest_res_o <= (others=>'0');
  elsif (sd_clk'event and sd_clk='1') then
    case(state) is
      when IDLE =>
        sd_dat_oe_o <= '0';
        sd_dat_o <= "11111111";
        crc_enable <= '0';
        crc_rst_n <= '0';
        transf_cnt <= (others=>'0');
        crc_c <= to_unsigned(16,crc_c'length);
        crc_s_cnt <= (others=>'0');
        crc_s <= (others=>'0');
        rx_dat_we_o <= '0';
        tx_dat_rd_o <= '0';
        data_index <= (others=>'1');
        blkcnt_reg <= blkcnt_i;
        if (bus_size_i=2) then
          data_cycles <= "000" & blksize_i; -- (<<0) operation
        elsif (bus_size_i=1) then
          data_cycles <= "00" & blksize_i & '0'; -- (<<1) operation
        else
          data_cycles <= blksize_i & "000"; -- (<<3) operation
        end if;
        bus_size_reg <= bus_size_i;
        -- state transition
        if (d_read_i='0' and d_write_i='1' and bustest_w_i='0' and bustest_r_i='0') then
          state <= WRITE_DAT;
        elsif  (d_read_i='1' and d_write_i='0' and bustest_w_i='0' and bustest_r_i='0') then
          state <= READ_WAIT;
        elsif  (d_read_i='0' and d_write_i='0' and bustest_w_i='1' and bustest_r_i='0') then
          data_cycles <= to_unsigned(24,data_cycles'length);
          state <= SEND_BUSTEST;
        elsif  (d_read_i='0' and d_write_i='0' and bustest_w_i='0' and bustest_r_i='1') then
          state <= READ_BUSTEST_WAIT;
        end if;
 
      when SEND_BUSTEST =>
        transf_cnt <= transf_cnt+1;
        tx_dat_rd_o <= '0';
        -- Send out start bits
        if (transf_cnt = 1) then
          sd_dat_oe_o <= '1';
          sd_dat_o <= "00000000";
        end if;
        -- Send out first pattern
        if (transf_cnt = 2) then
          sd_dat_o <= "10101010";
        end if;
        -- Send out second pattern
        if (transf_cnt = 3) then
          sd_dat_o <= "01010101";
        end if;
        -- Send out zeros
        if ((transf_cnt >= 4) and (transf_cnt < data_cycles)) then
          sd_dat_o <= "00000000";
        end if;
        if (transf_cnt = data_cycles) then -- stop bits
          sd_dat_o <= "11111111";
        end if;
        if (transf_cnt = data_cycles+1) then
          sd_dat_oe_o <= '0';
        end if;
        -- state transition
        if (transf_cnt >= data_cycles+1) then
          transf_cnt <= (others=>'0');
          state <= IDLE;
        end if;
 
      when READ_BUSTEST_WAIT =>
        sd_dat_oe_o <= '0';
        transf_cnt <= (others=>'0');
        bustest_0 <= (others=>'0');
        bustest_1 <= (others=>'0');
        bustest_res_o <= (others=>'0');
        -- state transition
        if (start_bit='1') then
          state <= READ_BUSTEST;
        end if;
 
      when READ_BUSTEST =>
        transf_cnt <= transf_cnt+1;
        if (transf_cnt = 0) then
          bustest_0 <= dat_reg;
        end if;
        if (transf_cnt = 1) then
          bustest_1 <= dat_reg;
        end if;
        -- state transition
        -- No CRC status response is needed
        -- Look for stop bits
        if (dat_reg = "11111111") then
          state <= ANALYZE_BUSTEST;
        end if;
 
      when ANALYZE_BUSTEST =>
        if (bustest_x="00000001") then
          bustest_res_o <= "001";
        elsif (bustest_x="00001111") then
          bustest_res_o <= "010";
        elsif (bustest_x="11111111") then
          bustest_res_o <= "011";
        else
          bustest_res_o <= "100";
        end if;
        state <= IDLE;
 
      when WRITE_DAT =>
        crc_ok_l <= '0';
        transf_cnt <= transf_cnt+1;
        tx_dat_rd_o <= '0';
        -- Load values for last_din and crc_in
        if (bus_size_reg=2) then
          last_din <= tx_dat_i;
          crc_in <= tx_dat_i;
          if (transf_cnt<data_cycles-1) then
            tx_dat_rd_o <= '1';
          else
            tx_dat_rd_o <= '0';
          end if;
        elsif (bus_size_reg=1) then
          last_din <=
            "1111" &
            tx_dat_i(7-(4*to_integer(data_index(0 downto 0)))) & 
            tx_dat_i(6-(4*to_integer(data_index(0 downto 0)))) & 
            tx_dat_i(5-(4*to_integer(data_index(0 downto 0)))) & 
            tx_dat_i(4-(4*to_integer(data_index(0 downto 0))));
          crc_in <=
            "1111" &
            tx_dat_i(7-(4*to_integer(data_index(0 downto 0)))) &
            tx_dat_i(6-(4*to_integer(data_index(0 downto 0)))) &
            tx_dat_i(5-(4*to_integer(data_index(0 downto 0)))) &
            tx_dat_i(4-(4*to_integer(data_index(0 downto 0))));
          if (transf_cnt<data_cycles) and (data_index(0 downto 0)=0) then
            tx_dat_rd_o <= '1';
          end if;
          if (data_index(0 downto 0)=1) then
            data_index <= (others=>'0');
          else
            data_index <= data_index+1;
          end if;
        else
          last_din <= "1111111" & tx_dat_i(7-to_integer(data_index));
          crc_in <= "1111111" & tx_dat_i(7-to_integer(data_index));
          if (transf_cnt<data_cycles) and (data_index = 6) then
            tx_dat_rd_o <= '1';
          end if;
          if (data_index = 7) then
            data_index <= (others=>'0');
          else
            data_index <= data_index+1;
          end if;
        end if;
        -- Treat first transfer differently
        if (transf_cnt = 1) then
          crc_rst_n <= '1';
          crc_enable <= '1';
          if (bus_size_reg=2) then
            last_din <= tx_dat_i;
            crc_in <= tx_dat_i;
          elsif (bus_size_reg=1) then
            last_din <= "1111" & tx_dat_i(7 downto 4);
            crc_in <= "1111" & tx_dat_i(7 downto 4);
          else
            last_din <= "1111111" & tx_dat_i(7);
            crc_in <= "1111111" & tx_dat_i(7);
          end if;
          sd_dat_oe_o <= '1';
          if (bus_size_reg=2) then -- start bits
            sd_dat_o <= "00000000";
          elsif (bus_size_reg=1) then
            sd_dat_o <= "11110000";
          else
            sd_dat_o <= "11111110";
          end if;
          data_index <= to_unsigned(1,data_index'length);
        elsif ((transf_cnt >= 2) and (transf_cnt <= data_cycles+1)) then
          sd_dat_o <= last_din;
          if (transf_cnt = data_cycles+1) then
            crc_enable <= '0';
          end if;
        elsif (transf_cnt > data_cycles+1) and (crc_c/=0) then
          crc_enable <= '0';
          crc_c <= crc_c-1;
          sd_dat_o(0) <= crc_out(0)(to_integer(crc_c)-1);
          if (bus_size_reg=2) then
            sd_dat_o(7 downto 1) <= crc_out(7)(to_integer(crc_c)-1) & crc_out(6)(to_integer(crc_c)-1) &
                                    crc_out(5)(to_integer(crc_c)-1) & crc_out(4)(to_integer(crc_c)-1) &
                                    crc_out(3)(to_integer(crc_c)-1) & crc_out(2)(to_integer(crc_c)-1) &
                                    crc_out(1)(to_integer(crc_c)-1);
          elsif (bus_size_reg=1) then
            sd_dat_o(3 downto 1) <= crc_out(3)(to_integer(crc_c)-1) & crc_out(2)(to_integer(crc_c)-1) &
                                    crc_out(1)(to_integer(crc_c)-1);
            sd_dat_o(7 downto 4) <= (others=>'1');
          else
            sd_dat_o(7 downto 1) <= (others=>'1');
          end if;
        elsif (transf_cnt = data_cycles+18) then -- stop bits
          sd_dat_o <= "11111111";
        elsif (transf_cnt >= data_cycles+19) then
          sd_dat_oe_o <= '0';
        end if;
        -- state transition
        -- There are two clocks of bus turnaround time, plus one extra
        -- because of the data input register, then the start bit of
        -- the CRC status occurs.
        if (d_stop_i='1') then
          state <= IDLE;
        elsif (transf_cnt = data_cycles+23) then
          if (start_bit='1') then
            state <= CHECK_CRC_STATUS;
          else
            transf_cnt <= (others=>'0');
            blkcnt_reg <= blkcnt_reg-1;
            crc_rst_n <= '0';
            crc_c <= to_unsigned(16,crc_c'length);
            crc_s_cnt <= (others=>'0');
            if (blkcnt_reg>1) then
              state <= WRITE_DAT;
            else
              state <= IDLE;
            end if;
          end if;
        end if;
 
      when CHECK_CRC_STATUS =>
        if (crc_s_cnt < 4) then
          crc_s(to_integer(crc_s_cnt)) <= dat_reg(0);
        end if;
        crc_s_cnt <= crc_s_cnt+1;
        busy_int <= '1';
        -- state transition
        if (crc_s_cnt = 4) then
          if (crc_s="1010") then
            crc_ok_l <= '1';
          else
            crc_ok_l <= '0';
          end if;
          state <= WRITE_BUSY;
        end if;
 
      when WRITE_BUSY =>
        busy_int <= not dat_reg(0);
        transf_cnt <= (others=>'0');
        -- state transition
        if (busy_int='0') then
          blkcnt_reg <= blkcnt_reg-1;
          crc_rst_n <= '0';
          crc_c <= to_unsigned(16,crc_c'length);
          crc_s_cnt <= (others=>'0');
          if (blkcnt_reg>1 and crc_ok_l='1') then
            state <= WRITE_DAT;
          elsif (busy_int='0') then
            state <= IDLE;
          end if;
        end if;
 
      when READ_WAIT =>
        crc_rst_n  <= '1';
        crc_enable <= '1';
        crc_in     <= (others=>'0');
        crc_c      <= to_unsigned(15,crc_c'length);-- end
        transf_cnt <= (others=>'0');
        -- state transition
        if (start_bit='1') then
          state <= READ_DAT;
        end if;
 
      when READ_DAT =>
        transf_cnt <= transf_cnt+1;
        if (transf_cnt < data_cycles) then
          if (bus_size_reg=2) then
            rx_dat_we_o <= '1';
            rx_dat_o <= dat_reg;
          elsif (bus_size_reg=1) then
            if (transf_cnt(0 downto 0)=1) then
              rx_dat_we_o <= '1';
            else
              rx_dat_we_o <= '0';
            end if;
            rx_dat_o(7-(4*to_integer(transf_cnt(0 downto 0)))) <= dat_reg(3);
            rx_dat_o(6-(4*to_integer(transf_cnt(0 downto 0)))) <= dat_reg(2);
            rx_dat_o(5-(4*to_integer(transf_cnt(0 downto 0)))) <= dat_reg(1);
            rx_dat_o(4-(4*to_integer(transf_cnt(0 downto 0)))) <= dat_reg(0);
          else
            if (transf_cnt(2 downto 0)=7) then
              rx_dat_we_o <= '1';
            else
              rx_dat_we_o <= '0';
            end if;
            rx_dat_o(7-to_integer(transf_cnt(2 downto 0))) <= dat_reg(0);
          end if;
          crc_in <= dat_reg;
          crc_ok_l <= '1';
        elsif (transf_cnt <= data_cycles+16) then
          crc_enable <= '0';
          last_din <= dat_reg;
          rx_dat_we_o <= '0';
          if (transf_cnt > data_cycles) then
            crc_c <= crc_c-1;
            if  (crc_out(0)(to_integer(crc_c)) /= last_din(0)) then
              crc_ok_l <= '0';
            end if;
            if  (crc_out(1)(to_integer(crc_c)) /= last_din(1) and bus_size_reg>0) then
              crc_ok_l <= '0';
            end if;
            if  (crc_out(2)(to_integer(crc_c)) /= last_din(2) and bus_size_reg>0) then
              crc_ok_l <= '0';
            end if;
            if  (crc_out(3)(to_integer(crc_c)) /= last_din(3) and bus_size_reg>0) then
              crc_ok_l <= '0';
            end if;
            if  (crc_out(4)(to_integer(crc_c)) /= last_din(4) and bus_size_reg>1) then
              crc_ok_l <= '0';
            end if;
            if  (crc_out(5)(to_integer(crc_c)) /= last_din(5) and bus_size_reg>1) then
              crc_ok_l <= '0';
            end if;
            if  (crc_out(6)(to_integer(crc_c)) /= last_din(6) and bus_size_reg>1) then
              crc_ok_l <= '0';
            end if;
            if  (crc_out(7)(to_integer(crc_c)) /= last_din(7) and bus_size_reg>1) then
              crc_ok_l <= '0';
            end if;
            if (crc_c=0) then
              crc_rst_n <= '0';
            end if;
          end if;
        end if;
        -- state transition
        if (d_stop_i='1') then
          state <= IDLE;
        elsif (transf_cnt=(data_cycles+17) and blkcnt_reg>1 and crc_ok_l='1') then
          blkcnt_reg <= blkcnt_reg-1;
          state <= READ_WAIT;
        elsif (transf_cnt=data_cycles+17) then
          state <= IDLE;
        end if;
 
    when others =>
      null;
 
    end case;
  end if;
end process;
 
end beh;
 
----------------------------------------------------------------------
----                                                              ----
---- WISHBONE SD Card Controller IP Core                          ----
----                                                              ----
---- sd_controller_8bit.vhd                                      ----
----                                                              ----
---- This file is part of the WISHBONE SD Card                    ----
---- Controller IP Core project                                   ----
---- http:--opencores.org/project,sd_card_controller              ----
----                                                              ----
---- Description                                                  ----
---- Top level entity.                                            ----
---- This core is based on the "sd card controller" project from  ----
---- http:--opencores.org/project,sdcard_mass_storage_controller  ----
---- but has been largely rewritten. A lot of effort has been     ----
---- made to make the core more generic and easily usable         ----
---- with OSs like Linux.                                         ----
---- - data transfer commands are not fixed                       ----
---- - data transfer block size is configurable                   ----
---- - multiple block transfer support                            ----
---- - R2 responses (136 bit) support                             ----
----                                                              ----
---- Author(s):                                                   ----
----     - John Clayton, morianton@gmail.com                      ----
----                                                              ----
----------------------------------------------------------------------
----                                                              ----
---- Copyright (C) 2016 Authors                                   ----
----                                                              ----
---- Based on original work by                                    ----
----     Adam Edvardsson (adam.edvardsson@orsoc.se)               ----
----                                                              ----
----     Copyright (C) 2009 Authors                               ----
----                                                              ----
---- This source file may be used and distributed without         ----
---- restriction provided that this copyright statement is not    ----
---- removed from the file and that any derivative work contains  ----
---- the original copyright notice and the associated disclaimer. ----
----                                                              ----
---- This source file is free software; you can redistribute it   ----
---- and/or modify it under the terms of the GNU Lesser General   ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any   ----
---- later version.                                               ----
----                                                              ----
---- This source is distributed in the hope that it will be       ----
---- useful, but WITHOUT ANY WARRANTY; without even the implied   ----
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ----
---- PURPOSE. See the GNU Lesser General Public License for more  ----
---- details.                                                     ----
----                                                              ----
---- You should have received a copy of the GNU Lesser General    ----
---- Public License along with this source; if not, download it   ----
---- from http:--www.opencores.org/lgpl.shtml                     ----
----                                                              ----
----------------------------------------------------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
library work;
use work.sd_host_pack.all;
use work.dds_pack.all;
use work.fifo_pack.all;
use work.convert_pack.all;
use work.signal_conditioning_pack.all;
 
entity sd_controller_8bit_bram is
  port (
    -- WISHBONE common
    wb_clk_i     : in  std_logic; -- system clock
    wb_rst_i     : in  std_logic; -- asynchronous
    -- WISHBONE slave (register interface)
    wb_dat_i     : in  unsigned(31 downto 0);
    wb_dat_o     : out unsigned(31 downto 0);
    wb_adr_i     : in  unsigned(3 downto 0);
    wb_we_i      : in  std_logic;
    wb_cyc_i     : in  std_logic;
    wb_ack_o     : out std_logic;
    -- Dedicated BRAM port without acknowledge.
    -- Access cycles must complete immediately.
    -- (data to cross clock domains by this dual-ported BRAM)
    bram_clk_o   : out std_logic; -- Same as sd_clk_o_pad
    bram_dat_o   : out unsigned(7 downto 0);
    bram_dat_i   : in  unsigned(7 downto 0);
    bram_adr_o   : out unsigned(31 downto 0);
    bram_we_o    : out std_logic;
    bram_cyc_o   : out std_logic;
    --SD Card Interface
    sd_cmd_i     : in  std_logic;
    sd_cmd_o     : out std_logic;
    sd_cmd_oe_o  : out std_logic;
    sd_dat_i     : in  unsigned(7 downto 0);
    sd_dat_o     : out unsigned(7 downto 0);
    sd_dat_oe_o  : out std_logic;
    sd_dat_siz_o : out unsigned(1 downto 0);
    sd_clk_o_pad : out std_logic;
    -- Interrupt outputs
    int_cmd_o    : out std_logic;
    int_data_o   : out std_logic
  );
end sd_controller_8bit_bram;
 
architecture beh of sd_controller_8bit_bram is
 
--SD clock
signal sd_clk_l    : std_logic; --sd_clk used in the system
signal sd_clk_en_l : std_logic; --clock enable pulse of sd_clk
signal combo_rst   : std_logic; -- combines two reset signals
signal combo_rst_n : std_logic;
signal wb_ack_r1   : std_logic;
signal wb_ack_r2   : std_logic;
 
signal cmd_start_pend  : std_logic;
signal cmd_start       : std_logic;
signal cmd_start_r1    : std_logic;
signal cmd_with_data   : std_logic;
signal sd_data_rd      : std_logic;
 
  -- Related to BRAM interface port
signal bram_cyc_l    : std_logic;
signal offset        : unsigned(31 downto 0);
 
  -- Related to data master
signal d_write       : std_logic;
signal d_read        : std_logic;
signal bustest_r     : std_logic;
signal bustest_w     : std_logic;
signal bustest_res   : unsigned(2 downto 0);
signal sd_dat_busy   : std_logic;
signal data_busy     : std_logic;
signal data_crc_ok   : std_logic;
signal bram_rd       : std_logic;
signal bram_we       : std_logic;
 
signal cmd_int_rst_pend  : std_logic;
signal cmd_int_rst       : std_logic;
signal cmd_int_rst_edge  : std_logic;
signal data_int_rst_pend : std_logic;
signal data_int_rst      : std_logic;
signal data_int_rst_edge : std_logic;
 
  --SD Data Master State Machine
type DM_STATE_TYPE is (IDLE, WAIT_FOR_CMD_INT, DATA_TX_START, DATA_TX,
                       DATA_RX, BUSTEST_ACTIVE, BUSTEST_W_START);
signal dm_state : DM_STATE_TYPE;
 
-- registers
signal argument_reg  : unsigned(31 downto 0);
signal cmd_index_reg : unsigned(5 downto 0);
signal blk_size_reg  : unsigned(BLKSIZE_W-1 downto 0);
signal blk_count_reg : unsigned(BLKCNT_W-1 downto 0);
signal resp_0_reg    : unsigned(31 downto 0);
signal resp_1_reg    : unsigned(31 downto 0);
signal resp_2_reg    : unsigned(31 downto 0);
signal resp_3_reg    : unsigned(31 downto 0);
  -- Fields of the settings register
signal bus_siz_reg   : unsigned(1 downto 0);
signal sw_rst_reg    : std_logic;
signal d_stop        : std_logic;
signal sd_freq_reg   : unsigned(31 downto 0);
signal timeout_reg   : unsigned(15 downto 0);
  -- Registers 0x9..0xC are interrupt related
signal cmd_int_status_reg   : unsigned(4 downto 0);
signal cmd_int_enable_reg   : unsigned(4 downto 0);
signal data_int_status_reg  : unsigned(2 downto 0);
signal data_int_enable_reg  : unsigned(2 downto 0);
  -- Register holding current bus address
signal dma_adr_reg   : unsigned(31 downto 0);
 
begin
 
  -- Register read mux
  with (to_integer(wb_adr_i)) select
  wb_dat_o <=
    u_resize(blk_size_reg,32)  when 0,
    u_resize(blk_count_reg,32) when 1,
    u_resize(cmd_index_reg,32) when 2,
    argument_reg               when 3,
    resp_0_reg                 when 4,
    resp_1_reg                 when 5,
    resp_2_reg                 when 6,
    resp_3_reg                 when 7,
    timeout_reg & "00000" & bustest_res & "000" & sw_rst_reg & "00" & bus_siz_reg when 8,
    sd_freq_reg                when 9,
    u_resize(cmd_int_status_reg,32)  when 10,
    u_resize(cmd_int_enable_reg,32)  when 11,
    u_resize(data_int_status_reg,32) when 12,
    u_resize(data_int_enable_reg,32) when 13,
    dma_adr_reg                when 14,
    str2u("55555555",32)       when others;
 
  -- Register Writing Process
reg_wr_proc : process(wb_rst_i, wb_clk_i)
begin
  if (wb_rst_i='1') then
    argument_reg <= (others=>'0');
    cmd_index_reg <= (others=>'0');
    blk_size_reg <= to_unsigned(512,blk_size_reg'length);
    blk_count_reg <= to_unsigned(1,blk_count_reg'length);
    bus_siz_reg <= "00";
    sw_rst_reg <= '0';
    sd_freq_reg <= str2u("010624DD",sd_freq_reg'length); -- Set for 400 kHz default (100 MHz sys_clk)
    timeout_reg <= to_unsigned(1000,timeout_reg'length);
    cmd_int_rst_pend <= '0';
    cmd_int_rst <= '0';
    d_stop <= '0';
    cmd_int_enable_reg <= (others=>'0');
    data_int_rst_pend <= '0';
    data_int_rst <= '0';
    data_int_enable_reg <= (others=>'0');
    wb_ack_r1 <= '0';
    wb_ack_r2 <= '0';
    cmd_start_pend <= '0';
    cmd_start <= '0';
    cmd_start_r1 <= '0';
    dma_adr_reg <= (others=>'0');
  elsif (wb_clk_i'event and wb_clk_i='1') then
    -- default values, clocked on sd_clk_en_l
    if (sd_clk_en_l='1') then
      cmd_start    <= '0';
      data_int_rst <= '0';
      cmd_int_rst  <= '0';
      d_stop       <= '0';
    end if;
    -- signals raised on sd_clk_en_l
    -- higher priority than the default
    if (sd_clk_en_l='1') then
      if (cmd_start_pend='1') then
        cmd_start <= '1';
        cmd_start_pend <= '0';
      end if;
      if (data_int_rst_pend='1') then
        data_int_rst <= '1';
        data_int_rst_pend <= '0';
      end if;
      if (cmd_int_rst_pend='1') then
        cmd_int_rst <= '1';
        cmd_int_rst_pend <= '0';
      end if;
    end if;
    -- delayed version
    cmd_start_r1 <= cmd_start;
 
 
    if (wb_ack_r1='1' and wb_ack_r2='0') then
      if (wb_we_i='1') then
        case (to_integer(wb_adr_i)) is
          when 0 =>
            blk_size_reg <= wb_dat_i(BLKSIZE_W-1 downto 0);
 
          when 1 =>
            blk_count_reg <= wb_dat_i(BLKCNT_W-1 downto 0);
 
          when 2 =>
            cmd_index_reg <= wb_dat_i(5 downto 0);
 
          when 3 =>
            argument_reg <= wb_dat_i;
            cmd_start_pend <= '1';
 
          when 8 =>
            bus_siz_reg <= wb_dat_i(1 downto 0);
            sw_rst_reg  <= wb_dat_i(4);
            d_stop      <= wb_dat_i(5); -- write only bit
            timeout_reg <= wb_dat_i(31 downto 16);
 
          when 9 =>
            sd_freq_reg <= wb_dat_i;
 
          when 10 =>
            cmd_int_rst_pend <= '1';
 
          when 11 =>
            cmd_int_enable_reg <= wb_dat_i(cmd_int_enable_reg'length-1 downto 0);
 
          when 12 =>
            data_int_rst_pend <= '1';
 
          when 13 =>
            data_int_enable_reg <= wb_dat_i(data_int_enable_reg'length-1 downto 0);
 
          when 14 =>
            dma_adr_reg <= wb_dat_i;
 
          when others =>
            null;
        end case;
      end if;
    end if;
    -- Detect rising edge of wb_cyc_i
    wb_ack_r1 <= wb_cyc_i;
    wb_ack_r2 <= wb_ack_r1;
  end if;
end process;
 
  -- Provide Wishbone bus cycle acknowledge
  wb_ack_o <= wb_ack_r1;
 
  -- Form a combined reset signal
  combo_rst   <= wb_rst_i or sw_rst_reg;
  combo_rst_n <= not combo_rst;
 
-- SD Card clock generation
-- A DDS is used.
sd_clk_dds : dds_squarewave
  generic map(
    ACC_BITS => sd_freq_reg'length -- Bit width of DDS phase accumulator
  )
  port map( 
 
    sys_rst_n    => combo_rst_n,
    sys_clk      => wb_clk_i,
    sys_clk_en   => '1',
 
    -- Frequency setting
    freq_i       => sd_freq_reg,
 
    -- Output
    pulse_o      => sd_clk_en_l,
    squarewave_o => sd_clk_l
  );
sd_clk_o_pad <= sd_clk_l;
 
 
cmd_host_0 : sd_cmd_host
  port map(
    sd_clk       => sd_clk_l,
    sys_rst      => combo_rst,
    -- Control and settings
    start_i      => cmd_start_r1,
    int_rst_i    => cmd_int_rst_edge,
    busy_i       => sd_dat_busy,
    cmd_index_i  => cmd_index_reg,
    argument_i   => argument_reg,
    timeout_i    => timeout_reg,
    int_status_o => cmd_int_status_reg,
    response_0_o => resp_0_reg,
    response_1_o => resp_1_reg,
    response_2_o => resp_2_reg,
    response_3_o => resp_3_reg,
    -- SD/MMC card command signals
    sd_cmd_i     => sd_cmd_i,
    sd_cmd_o     => sd_cmd_o,
    sd_cmd_oe_o  => sd_cmd_oe_o
  );
 
cmd_with_data <= '1' when cmd_index_reg=20 or cmd_index_reg=24 or cmd_index_reg=25 or
                          cmd_index_reg=8  or cmd_index_reg=11 or cmd_index_reg=17 or
                          cmd_index_reg=18 or cmd_index_reg=14 or cmd_index_reg=19 else '0';
sd_data_rd    <= '1' when cmd_index_reg=8  or cmd_index_reg=11 or 
                          cmd_index_reg=17 or cmd_index_reg=18 else '0';
 
  -- SD Data Master Finite State Machine
d_read <= '1' when dm_state=IDLE and cmd_start_r1='1' and cmd_with_data='1' and sd_data_rd='1' else '0';
d_write <= '1' when dm_state=DATA_TX_START else '0';
bustest_r <= '1' when dm_state=IDLE and cmd_start_r1='1' and cmd_index_reg=14 else '0';
bustest_w <= '1' when dm_state=BUSTEST_W_START else '0';
 
dm_fsm_proc : process(combo_rst, sd_clk_l)
begin
  if (combo_rst='1') then
    offset <= (others=>'0');
    data_int_status_reg <= (others=>'0');
    dm_state <= IDLE;
  elsif (sd_clk_l'event and sd_clk_l='1') then
    case (dm_state) is
      when IDLE =>
        offset <= (others=>'0');
        -- state transition
        if (cmd_start_r1='1') then
          if (cmd_with_data='1') then
            if (cmd_index_reg=14) then -- BUSTEST_R
              dm_state <= BUSTEST_ACTIVE;
            elsif (sd_data_rd='1') then -- Reading
              dm_state <= DATA_RX;
            else
              dm_state <= WAIT_FOR_CMD_INT;
            end if;
          end if;
        end if;
 
      when BUSTEST_ACTIVE =>
        if (data_busy='0') then --Transfer complete
          dm_state <= IDLE;
        end if;
 
      when BUSTEST_W_START =>
        dm_state <= BUSTEST_ACTIVE;
 
      when WAIT_FOR_CMD_INT =>
        if (cmd_int_status_reg(INT_CMD_CC)='1') then
          if (cmd_index_reg=19) then
            dm_state <= BUSTEST_W_START;
          else
            dm_state <= DATA_TX_START;
          end if;
        elsif (cmd_int_status_reg(INT_CMD_EI)='1') then
          dm_state <= IDLE;
        end if;
 
      when DATA_TX_START =>
        dm_state <= DATA_TX;
 
      when DATA_TX =>
        if (bram_cyc_l='1') then
          offset <= offset+1;
        end if;
        if (data_busy='0') then --Transfer complete
          if (data_crc_ok='0') then --Wrong CRC
            data_int_status_reg(INT_DATA_CCRCE) <= '1';
          else
            data_int_status_reg(INT_DATA_CC) <= '1';
          end if;
          dm_state <= IDLE;
        end if;
 
      when DATA_RX =>
        if (bram_cyc_l='1') then
          offset <= offset+1;
        end if;
        if (data_busy='0') then --Transfer complete
          if (data_crc_ok='0') then --Wrong CRC
            data_int_status_reg(INT_DATA_CCRCE) <= '1';
          else
            data_int_status_reg(INT_DATA_CC) <= '1';
          end if;
          dm_state <= IDLE;
        end if;
 
      when others =>
        null;
 
    end case;
 
    if (data_int_rst_edge='1') then
      data_int_status_reg <= (others=>'0');
    end if;
  end if;
end process;
 
 
sd_data_host0 : sd_data_8bit_host
  port map(
    sd_clk         => sd_clk_l,
    sys_rst        => combo_rst,
    --Tx Fifo
    tx_dat_i       => bram_dat_i,
    tx_dat_rd_o    => bram_rd,
    --Rx Fifo
    rx_dat_o       => bram_dat_o,
    rx_dat_we_o    => bram_we,
    --tristate data
    sd_dat_siz_o   => sd_dat_siz_o,
    sd_dat_oe_o    => sd_dat_oe_o,
    sd_dat_o       => sd_dat_o,
    sd_dat_i       => sd_dat_i,
    --Control signals
    blksize_i      => blk_size_reg,
    bus_size_i     => bus_siz_reg,
    blkcnt_i       => blk_count_reg,
    d_stop_i       => d_stop,
    d_read_i       => d_read,
    d_write_i      => d_write,
    bustest_w_i    => bustest_w,
    bustest_r_i    => bustest_r,
    bustest_res_o  => bustest_res,
    sd_dat_busy_o  => sd_dat_busy,
    fsm_busy_o     => data_busy,
    crc_ok_o       => data_crc_ok
  );
 
bram_clk_o <= not sd_clk_l;
bram_we_o  <= bram_we;
bram_cyc_l <= bram_rd or bram_we;
bram_cyc_o <= bram_cyc_l;
bram_adr_o <= dma_adr_reg+offset;
 
cmd_int_rst_edge_detect : edge_detector
  generic map(
    DETECT_RISING  => 1,
    DETECT_FALLING => 0
  )
  port map(
    -- System Clock and Clock Enable
    sys_rst_n   => combo_rst_n,
    sys_clk     => sd_clk_l,
    sys_clk_en  => '1',
 
    -- Input Signal
    sig_i       => cmd_int_rst,
 
    -- Output pulse
    pulse_o     => cmd_int_rst_edge
  );
 
data_int_rst_edge_detect : edge_detector
  generic map(
    DETECT_RISING  => 1,
    DETECT_FALLING => 0
  )
  port map(
    -- System Clock and Clock Enable
    sys_rst_n   => combo_rst_n,
    sys_clk     => sd_clk_l,
    sys_clk_en  => '1',
 
    -- Input Signal
    sig_i       => data_int_rst,
 
    -- Output pulse
    pulse_o     => data_int_rst_edge
  );
 
-- provide outputs
int_cmd_o  <= '1' when (cmd_int_status_reg or cmd_int_enable_reg)/=0 else '0';
int_data_o <= '1' when (data_int_status_reg or data_int_enable_reg)/=0 else '0';
 
end beh;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.