ossc/ip/altera_up_sd_card_avalon_in.../hdl/Altera_UP_SD_Card_Buffer.vhd

383 lines
13 KiB
VHDL

-- (C) 2001-2015 Altera Corporation. All rights reserved.
-- Your use of Altera Corporation's design tools, logic functions and other
-- software and tools, and its AMPP partner logic functions, and any output
-- files any of the foregoing (including device programming or simulation
-- files), and any associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License Subscription
-- Agreement, Altera MegaCore Function License Agreement, or other applicable
-- license agreement, including, without limitation, that your use is for the
-- sole purpose of programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the applicable
-- agreement for further details.
-------------------------------------------------------------------------------------
-- This module is a dual port memory block. It has a 16-bit port and a 1-bit port.
-- The 1-bit port is used to either send or receive data, while the 16-bit port is used
-- by Avalon interconnet to store and retrieve data.
--
-- NOTES/REVISIONS:
-------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity Altera_UP_SD_Card_Buffer is
generic (
TIMEOUT : std_logic_vector(15 downto 0) := "1111111111111111";
BUSY_WAIT : std_logic_vector(15 downto 0) := "0000001111110000"
);
port
(
i_clock : in std_logic;
i_reset_n : in std_logic;
-- 1 bit port to transmit and receive data on the data line.
i_begin : in std_logic;
i_sd_clock_pulse_trigger : in std_logic;
i_transmit : in std_logic;
i_1bit_data_in : in std_logic;
o_1bit_data_out : out std_logic;
o_operation_complete : out std_logic;
o_crc_passed : out std_logic;
o_timed_out : out std_logic;
o_dat_direction : out std_logic; -- set to 1 to send data, set to 0 to receive it.
-- 16 bit port to be accessed by a user circuit.
i_enable_16bit_port : in std_logic;
i_address_16bit_port : in std_logic_vector(7 downto 0);
i_write_16bit : in std_logic;
i_16bit_data_in : in std_logic_vector(15 downto 0);
o_16bit_data_out : out std_logic_vector(15 downto 0)
);
end entity;
architecture rtl of Altera_UP_SD_Card_Buffer is
component Altera_UP_SD_CRC16_Generator
port
(
i_clock : in std_logic;
i_enable : in std_logic;
i_reset_n : in std_logic;
i_sync_reset : in std_logic;
i_shift : in std_logic;
i_datain : in std_logic;
o_dataout : out std_logic;
o_crcout : out std_logic_vector(15 downto 0)
);
end component;
component Altera_UP_SD_Card_Memory_Block
PORT
(
address_a : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
address_b : IN STD_LOGIC_VECTOR (11 DOWNTO 0);
clock_a : IN STD_LOGIC ;
clock_b : IN STD_LOGIC ;
data_a : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
data_b : IN STD_LOGIC_VECTOR (0 DOWNTO 0);
enable_a : IN STD_LOGIC := '1';
enable_b : IN STD_LOGIC := '1';
wren_a : IN STD_LOGIC := '1';
wren_b : IN STD_LOGIC := '1';
q_a : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
q_b : OUT STD_LOGIC_VECTOR (0 DOWNTO 0)
);
END component;
-- Build an enumerated type for the state machine. On reset always reset the DE2 and read the state
-- of the switches.
type state_type is (s_RESET, s_WAIT_REQUEST, s_SEND_START_BIT, s_SEND_DATA, s_SEND_CRC, s_SEND_STOP, s_WAIT_BUSY, s_WAIT_BUSY_END,
s_WAIT_DATA_START, s_RECEIVING_LEADING_BITS, s_RECEIVING_DATA, s_RECEIVING_STOP_BIT, s_WAIT_DEASSERT);
-- Register to hold the current state
signal current_state : state_type;
signal next_state : state_type;
-- Local wires
-- REGISTERED
signal crc_counter : std_logic_vector(3 downto 0);
signal local_mode : std_logic;
signal dataout_1bit : std_logic;
signal bit_counter : std_logic_vector(2 downto 0);
signal byte_counter : std_logic_vector(8 downto 0);
signal shift_register : std_logic_vector(16 downto 0);
signal timeout_register : std_logic_vector(15 downto 0);
signal data_in_reg : std_logic;
-- UNREGISTERED
signal crc_out : std_logic_vector(15 downto 0);
signal single_bit_conversion, single_bit_out : std_logic_vector( 0 downto 0);
signal packet_mem_addr_b : std_logic_vector(11 downto 0);
signal local_reset, to_crc_generator, from_crc_generator, from_mem_1_bit, shift_crc,
recv_data, crc_generator_enable : std_logic;
begin
-- State transitions
state_transitions: process( current_state, i_begin, i_sd_clock_pulse_trigger, i_transmit, byte_counter,
bit_counter, crc_counter, i_1bit_data_in, timeout_register, data_in_reg)
begin
case (current_state) is
when s_RESET =>
-- Reset local registers and begin waiting for user input.
next_state <= s_WAIT_REQUEST;
when s_WAIT_REQUEST =>
-- Wait for i_begin to be high
if ((i_begin = '1') and (i_sd_clock_pulse_trigger = '1')) then
if (i_transmit = '1') then
next_state <= s_SEND_START_BIT;
else
next_state <= s_WAIT_DATA_START;
end if;
else
next_state <= s_WAIT_REQUEST;
end if;
when s_SEND_START_BIT =>
-- Send a 0 first, followed by 4096 bits of data, 16 CRC bits, and stop bit.
if (i_sd_clock_pulse_trigger = '1') then
next_state <= s_SEND_DATA;
else
next_state <= s_SEND_START_BIT;
end if;
when s_SEND_DATA =>
-- Send 4096 data bits
if ((i_sd_clock_pulse_trigger = '1') and (bit_counter = "000") and (byte_counter = "111111111")) then
next_state <= s_SEND_CRC;
else
next_state <= s_SEND_DATA;
end if;
when s_SEND_CRC =>
-- Send 16 CRC bits
if ((i_sd_clock_pulse_trigger = '1') and (crc_counter = "1111")) then
next_state <= s_SEND_STOP;
else
next_state <= s_SEND_CRC;
end if;
when s_SEND_STOP =>
-- Send stop bit.
if (i_sd_clock_pulse_trigger = '1') then
next_state <= s_WAIT_BUSY;
else
next_state <= s_SEND_STOP;
end if;
when s_WAIT_BUSY =>
-- After a write, wait for the busy signal. Do not return a done signal until you receive a busy signal.
-- If you do not and a long time expires, then the data must have been rejected (due to CRC error maybe).
-- In such a case return failure.
if ((i_sd_clock_pulse_trigger = '1') and (data_in_reg = '0') and (timeout_register = "0000000000010000")) then
next_state <= s_WAIT_BUSY_END;
else
if (timeout_register = BUSY_WAIT) then
next_state <= s_WAIT_DEASSERT;
else
next_state <= s_WAIT_BUSY;
end if;
end if;
when s_WAIT_BUSY_END =>
if (i_sd_clock_pulse_trigger = '1') then
if (data_in_reg = '1') then
next_state <= s_WAIT_DEASSERT;
else
next_state <= s_WAIT_BUSY_END;
end if;
else
next_state <= s_WAIT_BUSY_END;
end if;
when s_WAIT_DATA_START =>
-- Wait for the start bit
if ((i_sd_clock_pulse_trigger = '1') and (data_in_reg = '0')) then
next_state <= s_RECEIVING_LEADING_BITS;
else
if (timeout_register = TIMEOUT) then
next_state <= s_WAIT_DEASSERT;
else
next_state <= s_WAIT_DATA_START;
end if;
end if;
when s_RECEIVING_LEADING_BITS =>
-- shift the start bit in as well as the next 16 bits. Once they are all in you can start putting data into memory.
if ((i_sd_clock_pulse_trigger = '1') and (crc_counter = "1111")) then
next_state <= s_RECEIVING_DATA;
else
next_state <= s_RECEIVING_LEADING_BITS;
end if;
when s_RECEIVING_DATA =>
-- Wait until all bits arrive.
if ((i_sd_clock_pulse_trigger = '1') and (bit_counter = "000") and (byte_counter = "111111111")) then
next_state <= s_RECEIVING_STOP_BIT;
else
next_state <= s_RECEIVING_DATA;
end if;
when s_RECEIVING_STOP_BIT =>
-- Wait until all bits arrive.
if (i_sd_clock_pulse_trigger = '1')then
next_state <= s_WAIT_DEASSERT;
else
next_state <= s_RECEIVING_STOP_BIT;
end if;
when s_WAIT_DEASSERT =>
if (i_begin = '1') then
next_state <= s_WAIT_DEASSERT;
else
next_state <= s_WAIT_REQUEST;
end if;
when others =>
next_state <= s_RESET;
end case;
end process;
-- State registers
state_regs: process(i_clock, i_reset_n, local_reset)
begin
if (i_reset_n = '0') then
current_state <= s_RESET;
elsif (rising_edge(i_clock)) then
current_state <= next_state;
end if;
end process;
-- FSM outputs
to_crc_generator <= shift_register(16) when (current_state = s_RECEIVING_DATA) else
from_mem_1_bit when (current_state = s_SEND_DATA) else
'0';
shift_crc <= '1' when (current_state = s_SEND_CRC) else '0';
local_reset <= '1' when ((current_state = s_RESET) or (current_state = s_WAIT_REQUEST)) else '0';
recv_data <= '1' when (current_state = s_RECEIVING_DATA) else '0';
single_bit_conversion(0) <= shift_register(15);
crc_generator_enable <= '0' when (current_state = s_WAIT_DEASSERT) else i_sd_clock_pulse_trigger;
o_operation_complete <= '1' when (current_state = s_WAIT_DEASSERT) else '0';
o_dat_direction <= '1' when ( (current_state = s_SEND_START_BIT) or
(current_state = s_SEND_DATA) or
(current_state = s_SEND_CRC) or
(current_state = s_SEND_STOP))
else '0';
o_1bit_data_out <= dataout_1bit;
o_crc_passed <= '1' when ((crc_out = shift_register(16 downto 1)) and (shift_register(0) = '1')) else '0';
o_timed_out <= '1' when (timeout_register = TIMEOUT) else '0';
-- Local components
local_regs: process(i_clock, i_reset_n, local_reset)
begin
if (i_reset_n = '0') then
bit_counter <= (OTHERS => '1');
byte_counter <= (OTHERS => '0');
dataout_1bit <= '1';
crc_counter <= (OTHERS => '0');
shift_register <= (OTHERS => '0');
elsif (rising_edge(i_clock)) then
-- counters and serial output
if (local_reset = '1') then
bit_counter <= (OTHERS => '1');
byte_counter <= (OTHERS => '0');
dataout_1bit <= '1';
data_in_reg <= '1';
crc_counter <= (OTHERS => '0');
shift_register <= (OTHERS => '0');
elsif (i_sd_clock_pulse_trigger = '1') then
if ((not (current_state = s_RECEIVING_LEADING_BITS)) and (not (current_state = s_SEND_CRC))) then
crc_counter <= (OTHERS => '0');
else
if (not (crc_counter = "1111")) then
crc_counter <= crc_counter + '1';
end if;
end if;
if ((current_state = s_RECEIVING_DATA) or (current_state = s_SEND_DATA)) then
if (not ((bit_counter = "000") and (byte_counter = "111111111"))) then
if (bit_counter = "000") then
byte_counter <= byte_counter + '1';
bit_counter <= "111";
else
bit_counter <= bit_counter - '1';
end if;
end if;
end if;
-- Output data bit.
if (current_state = s_SEND_START_BIT) then
dataout_1bit <= '0';
elsif (current_state = s_SEND_DATA) then
dataout_1bit <= from_mem_1_bit;
elsif (current_state = s_SEND_CRC) then
dataout_1bit <= from_crc_generator;
else
dataout_1bit <= '1'; -- Stop bit.
end if;
-- Shift register to store the CRC bits once the message is received.
if ((current_state = s_RECEIVING_DATA) or
(current_state = s_RECEIVING_LEADING_BITS) or
(current_state = s_RECEIVING_STOP_BIT)) then
shift_register(16 downto 1) <= shift_register(15 downto 0);
shift_register(0) <= data_in_reg;
end if;
data_in_reg <= i_1bit_data_in;
end if;
end if;
end process;
-- Register holding the timeout value for data transmission.
timeout_reg: process(i_clock, i_reset_n, current_state, i_sd_clock_pulse_trigger)
begin
if (i_reset_n = '0') then
timeout_register <= (OTHERS => '0');
elsif (rising_edge(i_clock)) then
if ((current_state = s_SEND_STOP) or
(current_state = s_WAIT_REQUEST)) then
timeout_register <= (OTHERS => '0');
elsif (i_sd_clock_pulse_trigger = '1') then
-- Increment the timeout counter
if (((current_state = s_WAIT_DATA_START) or
(current_state = s_WAIT_BUSY)) and (not (timeout_register = TIMEOUT))) then
timeout_register <= timeout_register + '1';
end if;
end if;
end if;
end process;
-- Instantiated components.
crc16_checker: Altera_UP_SD_CRC16_Generator
port map
(
i_clock => i_clock,
i_reset_n => i_reset_n,
i_sync_reset => local_reset,
i_enable => crc_generator_enable,
i_shift => shift_crc,
i_datain => to_crc_generator,
o_dataout => from_crc_generator,
o_crcout => crc_out
);
packet_memory: Altera_UP_SD_Card_Memory_Block
PORT MAP
(
address_a => i_address_16bit_port,
address_b => packet_mem_addr_b,
clock_a => i_clock,
clock_b => i_clock,
data_a => i_16bit_data_in,
data_b => single_bit_conversion,
enable_a => i_enable_16bit_port,
enable_b => '1',
wren_a => i_write_16bit,
wren_b => recv_data,
q_a => o_16bit_data_out,
q_b => single_bit_out
);
from_mem_1_bit <= single_bit_out(0);
packet_mem_addr_b <= (byte_counter & bit_counter);
end rtl;