initial commit
This commit is contained in:
260
fpga/strm_ddr2/strm_ddr2.vhd
Normal file
260
fpga/strm_ddr2/strm_ddr2.vhd
Normal file
@@ -0,0 +1,260 @@
|
||||
-- ---------------------------------------------------------------
|
||||
-- (2013) Benjamin Krill <benjamin@krll.de>
|
||||
-- ---------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use work.strm_package.all;
|
||||
|
||||
entity strm_ddr2 is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
rst_n : in std_logic;
|
||||
debug : out std_logic_vector( 7 downto 0);
|
||||
|
||||
-- streaming bus
|
||||
strm_in_data_i : in std_logic_vector(31 downto 0);
|
||||
strm_in_eop_i : in std_logic;
|
||||
strm_in_en_i : in std_logic;
|
||||
strm_in_busy_o : out std_logic;
|
||||
strm_out_req_o : out std_logic;
|
||||
strm_out_busy_i : in std_logic;
|
||||
strm_out_data_o : out std_logic_vector(31 downto 0);
|
||||
strm_out_eop_o : out std_logic;
|
||||
strm_out_en_o : out std_logic;
|
||||
|
||||
-- memory interface
|
||||
ddr2_cmd_en_o : out std_logic;
|
||||
ddr2_cmd_instr_o : out std_logic_vector( 2 downto 0);
|
||||
ddr2_cmd_bl_o : out std_logic_vector( 5 downto 0);
|
||||
ddr2_cmd_byte_addr_o : out std_logic_vector(29 downto 0);
|
||||
ddr2_cmd_empty_i : in std_logic;
|
||||
ddr2_cmd_full_i : in std_logic;
|
||||
ddr2_wr_en_o : out std_logic;
|
||||
ddr2_wr_mask_o : out std_logic_vector( 3 downto 0);
|
||||
ddr2_wr_data_o : out std_logic_vector(31 downto 0);
|
||||
ddr2_wr_full_i : in std_logic;
|
||||
ddr2_wr_empty_i : in std_logic;
|
||||
ddr2_wr_count_i : in std_logic_vector( 6 downto 0);
|
||||
ddr2_wr_underrun_i : in std_logic;
|
||||
ddr2_wr_error_i : in std_logic;
|
||||
ddr2_rd_en_o : out std_logic;
|
||||
ddr2_rd_data_i : in std_logic_vector(31 downto 0);
|
||||
ddr2_rd_full_i : in std_logic;
|
||||
ddr2_rd_empty_i : in std_logic;
|
||||
ddr2_rd_count_i : in std_logic_vector( 6 downto 0);
|
||||
ddr2_rd_overflow_i : in std_logic;
|
||||
ddr2_rd_error_i : in std_logic
|
||||
);
|
||||
end strm_ddr2;
|
||||
|
||||
architecture strm_ddr2 of strm_ddr2 is
|
||||
type sm_strm_t is (IDLE, DDR2_ADDRESS, RECV, DDR2_READ, DDR2_RD_SIZE, DDR2_RD_WAIT, DDR2_RD_ADJ, DDR2_RD_REQ, IGNORE);
|
||||
signal sm_strm : sm_strm_t;
|
||||
signal rst : std_logic;
|
||||
signal strm_in_data : std_logic_vector(31 downto 0);
|
||||
signal strm_in_eop : std_logic;
|
||||
signal strm_in_en : std_logic;
|
||||
signal strm_in_busy : std_logic;
|
||||
signal strm_type_vld : std_logic;
|
||||
signal strm_size : unsigned(23 downto 0);
|
||||
signal ddr2_wr_en : std_logic;
|
||||
signal ddr2_wr_mask : std_logic_vector( 3 downto 0);
|
||||
signal ddr2_wr_data : std_logic_vector(31 downto 0);
|
||||
signal dw_cnt : unsigned( 7 downto 0);
|
||||
signal dw_cnt_dec : unsigned( 7 downto 0);
|
||||
signal ddr2_adr : unsigned(27 downto 0);
|
||||
signal ddr2_size : unsigned(23 downto 0);
|
||||
signal ddr2_read_size : unsigned(23 downto 0);
|
||||
signal ddr2_cmd_en : std_logic;
|
||||
signal ddr2_cmd_instr : std_logic_vector( 2 downto 0);
|
||||
signal strm_out_size : unsigned(23 downto 0);
|
||||
signal strm_out_eop : std_logic;
|
||||
signal strm_out_hdr_en : std_logic;
|
||||
signal ddr2_rd_en : std_logic;
|
||||
signal bla_cnt : unsigned(7 downto 0);
|
||||
begin
|
||||
rst <= not rst_n;
|
||||
ddr2_rd_en_o <= ddr2_rd_en;
|
||||
ddr2_cmd_en_o <= ddr2_cmd_en;
|
||||
ddr2_cmd_instr_o <= ddr2_cmd_instr;
|
||||
ddr2_wr_en_o <= ddr2_wr_en;
|
||||
ddr2_wr_mask_o <= ddr2_wr_mask;
|
||||
ddr2_wr_data_o <= ddr2_wr_data;
|
||||
strm_in_data <= strm_in_data_i;
|
||||
strm_in_eop <= strm_in_eop_i;
|
||||
strm_in_en <= strm_in_en_i;
|
||||
strm_in_busy_o <= strm_in_busy;
|
||||
|
||||
strm_in_busy <= ddr2_wr_full_i or ddr2_cmd_full_i;
|
||||
strm_type_vld <= '1' when strm_in_data(STRM_TYPE_HIGH downto STRM_TYPE_LOW) = STRM_TYPE_DDR2 else '0';
|
||||
process (clk, rst_n)
|
||||
begin
|
||||
if rst_n = '0' then
|
||||
sm_strm <= IDLE;
|
||||
strm_size <= (others => '0');
|
||||
ddr2_cmd_instr <= (others => '0');
|
||||
ddr2_wr_en <= '0';
|
||||
ddr2_wr_mask <= (others => '0');
|
||||
ddr2_wr_data <= (others => '0');
|
||||
dw_cnt <= (others => '0');
|
||||
ddr2_adr <= (others => '0');
|
||||
ddr2_size <= (others => '0');
|
||||
ddr2_read_size <= (others => '0');
|
||||
strm_out_size <= (others => '0');
|
||||
bla_cnt <= (others => '0');
|
||||
strm_out_hdr_en <= '0';
|
||||
elsif rising_edge(clk) then
|
||||
-- STRM SIZE
|
||||
if sm_strm = IDLE and strm_in_en = '1' then
|
||||
strm_size <= unsigned(strm_in_data(STRM_LENGTH_HIGH downto STRM_LENGTH_LOW));
|
||||
end if;
|
||||
|
||||
-- SAVE DDR2 ADDRESS
|
||||
if sm_strm = DDR2_ADDRESS and strm_in_en = '1' then
|
||||
ddr2_adr <= unsigned(strm_in_data(STRM_DDR2_ADR_HIGH downto STRM_DDR2_ADR_LOW));
|
||||
elsif ddr2_cmd_en = '1' then
|
||||
ddr2_adr <= ddr2_adr + x"040";
|
||||
end if;
|
||||
|
||||
-- SAVE DDR2 READ SIZE
|
||||
if sm_strm = DDR2_RD_SIZE and strm_in_en = '1' then
|
||||
ddr2_size <= unsigned(strm_in_data(STRM_DDR2_SIZE_HIGH downto STRM_DDR2_SIZE_LOW));
|
||||
strm_out_size <= unsigned(strm_in_data(STRM_DDR2_SIZE_HIGH downto STRM_DDR2_SIZE_LOW));
|
||||
elsif sm_strm = DDR2_RD_REQ and ddr2_cmd_full_i = '0' then
|
||||
if ddr2_size > x"000040" then
|
||||
ddr2_size <= ddr2_size - x"40";
|
||||
else
|
||||
ddr2_size <= (others => '0');
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- DDR2 DW COUNT
|
||||
if sm_strm = RECV or sm_strm = IDLE then
|
||||
if strm_in_en = '1' and ddr2_cmd_en = '1' then
|
||||
dw_cnt <= x"01";
|
||||
elsif ddr2_cmd_en = '1' then
|
||||
dw_cnt <= (others => '0');
|
||||
elsif strm_in_en = '1' then
|
||||
dw_cnt <= dw_cnt + "1";
|
||||
end if;
|
||||
elsif sm_strm = DDR2_RD_ADJ and ddr2_cmd_full_i = '0' then
|
||||
if ddr2_size > x"000040" then
|
||||
dw_cnt <= x"40";
|
||||
else
|
||||
dw_cnt <= ddr2_size(7 downto 0);
|
||||
end if;
|
||||
elsif strm_out_eop = '1' then
|
||||
dw_cnt <= (others => '0');
|
||||
end if;
|
||||
|
||||
-- DDR2 instruction
|
||||
if sm_strm = DDR2_ADDRESS and strm_in_en = '1' then
|
||||
if strm_in_data(STRM_DDR2_ACCESS) = STRM_DDR2_ACC_WRITE then
|
||||
ddr2_cmd_instr <= "000";
|
||||
else
|
||||
ddr2_cmd_instr <= "001";
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if sm_strm = IDLE then
|
||||
strm_out_hdr_en <= '1';
|
||||
elsif sm_strm = DDR2_RD_WAIT and strm_out_busy_i = '0' then
|
||||
strm_out_hdr_en <= '0';
|
||||
end if;
|
||||
|
||||
-- RECV STATES
|
||||
case sm_strm is
|
||||
when IDLE =>
|
||||
if strm_in_en = '1' then
|
||||
if strm_type_vld = '1' then
|
||||
sm_strm <= DDR2_ADDRESS;
|
||||
else
|
||||
sm_strm <= IGNORE;
|
||||
end if;
|
||||
end if;
|
||||
when DDR2_ADDRESS =>
|
||||
if strm_in_en = '1' then
|
||||
if strm_in_data(STRM_DDR2_ACCESS) = STRM_DDR2_ACC_WRITE then
|
||||
sm_strm <= RECV;
|
||||
else
|
||||
sm_strm <= DDR2_RD_SIZE;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- DDR WRITE
|
||||
when RECV =>
|
||||
if strm_in_eop = '1' and strm_in_en = '1' then
|
||||
sm_strm <= IDLE;
|
||||
end if;
|
||||
|
||||
-- DDR READ
|
||||
when DDR2_RD_SIZE =>
|
||||
if strm_in_en = '1' then
|
||||
if strm_in_eop = '1' then
|
||||
sm_strm <= DDR2_RD_ADJ;
|
||||
else
|
||||
sm_strm <= IGNORE;
|
||||
end if;
|
||||
end if;
|
||||
when DDR2_RD_ADJ =>
|
||||
if ddr2_cmd_full_i = '0' then
|
||||
sm_strm <= DDR2_RD_REQ;
|
||||
end if;
|
||||
when DDR2_RD_REQ =>
|
||||
sm_strm <= DDR2_RD_WAIT;
|
||||
when DDR2_RD_WAIT =>
|
||||
if ddr2_rd_empty_i = '0' and strm_out_busy_i = '0' then
|
||||
sm_strm <= DDR2_READ;
|
||||
end if;
|
||||
when DDR2_READ =>
|
||||
if ddr2_rd_empty_i = '1' and ddr2_size /= x"000000" and bla_cnt = dw_cnt(6 downto 0) then
|
||||
sm_strm <= DDR2_RD_ADJ;
|
||||
elsif strm_out_eop = '1' then
|
||||
sm_strm <= IDLE;
|
||||
end if;
|
||||
|
||||
-- COMMON IGNORE
|
||||
when IGNORE =>
|
||||
if strm_in_eop = '1' and strm_in_en = '1' then
|
||||
sm_strm <= IDLE;
|
||||
end if;
|
||||
end case;
|
||||
|
||||
-- DDR REGISTERS
|
||||
ddr2_wr_en <= '0';
|
||||
if strm_in_en = '1' and sm_strm = RECV then
|
||||
ddr2_wr_en <= '1';
|
||||
ddr2_wr_mask <= (others => '0');
|
||||
ddr2_wr_data <= strm_in_data;
|
||||
end if;
|
||||
|
||||
if ddr2_cmd_en = '1' then
|
||||
bla_cnt <= (others => '0');
|
||||
elsif ddr2_rd_en = '1' then
|
||||
bla_cnt <= bla_cnt + "1";
|
||||
end if;
|
||||
|
||||
-- STRM OUT REGISTERS
|
||||
if sm_strm = DDR2_RD_SIZE then
|
||||
ddr2_read_size <= x"000001";
|
||||
elsif ddr2_rd_en = '1' then
|
||||
ddr2_read_size <= ddr2_read_size + "1";
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
ddr2_cmd_en <= '1' when (sm_strm = RECV and dw_cnt = x"40") or ((sm_strm = DDR2_RD_REQ or sm_strm = IDLE) and dw_cnt /= x"00") else '0';
|
||||
dw_cnt_dec <= dw_cnt - "1";
|
||||
ddr2_cmd_bl_o <= std_logic_vector(dw_cnt_dec(5 downto 0));
|
||||
ddr2_cmd_byte_addr_o <= std_logic_vector(ddr2_adr) & "00";
|
||||
|
||||
ddr2_rd_en <= not ddr2_rd_empty_i when sm_strm = DDR2_READ else '0';
|
||||
strm_out_req_o <= not ddr2_rd_empty_i and strm_out_busy_i when sm_strm = DDR2_RD_WAIT else '0';
|
||||
strm_out_en_o <= strm_out_hdr_en when sm_strm = DDR2_RD_WAIT and strm_out_busy_i = '0' else ddr2_rd_en;
|
||||
strm_out_eop <= ddr2_rd_en when ddr2_read_size >= strm_out_size and sm_strm = DDR2_READ else '0';
|
||||
strm_out_eop_o <= strm_out_eop;
|
||||
strm_out_data_o <= STRM_TYPE_DDR2 & (27 downto 24 => '0') & std_logic_vector(strm_out_size)
|
||||
when strm_out_hdr_en = '1' else ddr2_rd_data_i;
|
||||
|
||||
end strm_ddr2;
|
||||
Reference in New Issue
Block a user