Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72cc8491e7 |
@@ -24,8 +24,8 @@ ENTITY dcache IS
|
|||||||
CYC_O : out STD_LOGIC;
|
CYC_O : out STD_LOGIC;
|
||||||
en : in STD_LOGIC;
|
en : in STD_LOGIC;
|
||||||
cpu_en : in STD_LOGIC;
|
cpu_en : in STD_LOGIC;
|
||||||
cpu_we : in STD_LOGIC;
|
cpu_r_wn : in STD_LOGIC;
|
||||||
cpu_be : in unsigned(3 downto 0);
|
cpu_we : in unsigned(3 downto 0);
|
||||||
cpu_addr : in word_t;
|
cpu_addr : in word_t;
|
||||||
cpu_din : in word_t;
|
cpu_din : in word_t;
|
||||||
cpu_dout : out word_t;
|
cpu_dout : out word_t;
|
||||||
@@ -130,11 +130,12 @@ END COMPONENT;
|
|||||||
return result;
|
return result;
|
||||||
end to_tram_data;
|
end to_tram_data;
|
||||||
|
|
||||||
type cache_state_t is (init, ready, flush, mem_request, mem_access, mem_wait, mem_data, upd_cache, rd_cache);
|
type cache_state_t is (init, ready, flush, mem_request, mem_access, mem_wait, mem_data, upd_cache, rd_cache, wr_cache);
|
||||||
signal s, sn : cache_state_t;
|
signal s, sn : cache_state_t;
|
||||||
|
|
||||||
signal cache_busy : std_logic;
|
signal cache_busy : std_logic;
|
||||||
signal cache_hit : std_logic;
|
signal cache_read_miss : std_logic;
|
||||||
|
signal cache_write_miss : std_logic;
|
||||||
signal tag_match : std_logic;
|
signal tag_match : std_logic;
|
||||||
signal word_index_reg : unsigned(word_index_width-1 downto 0);
|
signal word_index_reg : unsigned(word_index_width-1 downto 0);
|
||||||
signal cache_index_reg : unsigned(cache_index_width-1 downto 0);
|
signal cache_index_reg : unsigned(cache_index_width-1 downto 0);
|
||||||
@@ -146,16 +147,15 @@ END COMPONENT;
|
|||||||
signal cpu_dram_dout : word_t;
|
signal cpu_dram_dout : word_t;
|
||||||
signal cpu_dram_din : word_t;
|
signal cpu_dram_din : word_t;
|
||||||
signal cpu_data_reg : word_t;
|
signal cpu_data_reg : word_t;
|
||||||
signal cpu_be_reg : unsigned(3 downto 0);
|
signal cpu_we_reg : unsigned(3 downto 0);
|
||||||
signal cpu_we_reg : std_logic;
|
signal ctrl_force_we : unsigned(3 downto 0);
|
||||||
signal ctrl_dram_en : std_logic;
|
signal cpu_was_write : std_logic;
|
||||||
signal ctrl_dram_addr : unsigned(lg2(cache_size)-1 downto 0);
|
signal ctrl_dram_addr : unsigned(lg2(cache_size)-1 downto 0);
|
||||||
signal ctrl_dram_din : word_t;
|
signal ctrl_dram_din : word_t;
|
||||||
signal ctrl_dram_we : unsigned(3 downto 0);
|
signal ctrl_dram_we : unsigned(3 downto 0);
|
||||||
signal cpu_dram_we : unsigned(3 downto 0);
|
signal cpu_dram_we : unsigned(3 downto 0);
|
||||||
signal cpu_dram_en : std_logic;
|
signal dram_en : std_logic;
|
||||||
signal cpu_en2 : std_logic;
|
signal cpu_was_en : std_logic;
|
||||||
signal cpu_we2 : std_logic;
|
|
||||||
|
|
||||||
signal tram_addr_rd : unsigned(cache_index_width-1 downto 0);
|
signal tram_addr_rd : unsigned(cache_index_width-1 downto 0);
|
||||||
signal tram_dout : tram_data_t;
|
signal tram_dout : tram_data_t;
|
||||||
@@ -174,64 +174,44 @@ END COMPONENT;
|
|||||||
signal cpu_reg_en : std_logic;
|
signal cpu_reg_en : std_logic;
|
||||||
signal was_miss : std_logic;
|
signal was_miss : std_logic;
|
||||||
signal data_write : std_logic;
|
signal data_write : std_logic;
|
||||||
signal cpu_hit_we : std_logic;
|
signal cpu_we2 : std_logic;
|
||||||
signal instant_raw : std_logic;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
cpu_hit_we <= cpu_we2 and cache_hit;
|
|
||||||
|
|
||||||
cpu_index_register:
|
cpu_index_reg:
|
||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
if RST_I = '1' then
|
if RST_I = '1' then
|
||||||
cache_index_reg <= (others => '0');
|
cache_index_reg <= (others => '0');
|
||||||
tag_index_reg <= (others => '0');
|
tag_index_reg <= (others => '0');
|
||||||
elsif cpu_reg_en = '1' and en = '1' and instant_raw = '0' then
|
cpu_was_write <= '0';
|
||||||
|
elsif cpu_reg_en = '1' and en = '1' then
|
||||||
word_index_reg <= cpu_word_index;
|
word_index_reg <= cpu_word_index;
|
||||||
cache_index_reg <= cpu_cache_index;
|
cache_index_reg <= cpu_cache_index;
|
||||||
tag_index_reg <= cpu_tag;
|
tag_index_reg <= cpu_tag;
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
cpu_data_register:
|
|
||||||
process(CLK_I)
|
|
||||||
begin
|
|
||||||
if rising_edge(CLK_I) then
|
|
||||||
if RST_I = '1' then
|
|
||||||
cpu_we_reg <= '0';
|
|
||||||
elsif cpu_reg_en = '1' and en = '1' then
|
|
||||||
cpu_data_reg <= cpu_din;
|
cpu_data_reg <= cpu_din;
|
||||||
cpu_be_reg <= cpu_be;
|
|
||||||
cpu_we_reg <= cpu_we;
|
cpu_we_reg <= cpu_we;
|
||||||
|
cpu_was_write <= not cpu_r_wn;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
cpu_was_wr_register:
|
cpu_was_wr_reg:
|
||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
cpu_en2 <= '0';
|
cpu_was_en <= '0';
|
||||||
cpu_we2 <= '0';
|
cpu_we2 <= '0';
|
||||||
if cpu_en = '1' and en = '1' then
|
if cpu_en = '1' and en = '1' then
|
||||||
cpu_we2 <= cpu_we;
|
cpu_we2 <= not cpu_r_wn;
|
||||||
cpu_en2 <= '1';
|
cpu_was_en <= '1';
|
||||||
cpu_dram_din <= cpu_din;
|
cpu_dram_din <= cpu_din;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
instant_raw_logic:
|
|
||||||
process(CLK_I)
|
|
||||||
begin
|
|
||||||
if rising_edge(CLK_I) then
|
|
||||||
instant_raw <= cpu_hit_we and cpu_en and en and not cpu_we;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
inst_tag_ram : dpram_1w1r
|
inst_tag_ram : dpram_1w1r
|
||||||
GENERIC MAP (
|
GENERIC MAP (
|
||||||
addr_width => tram_addr_width,
|
addr_width => tram_addr_width,
|
||||||
@@ -261,8 +241,8 @@ gen_data_ram:
|
|||||||
PORT MAP (
|
PORT MAP (
|
||||||
clk_a => CLK_I,
|
clk_a => CLK_I,
|
||||||
clk_b => CLK_I,
|
clk_b => CLK_I,
|
||||||
en_a => ctrl_dram_en,
|
en_a => '1',
|
||||||
en_b => '1',
|
en_b => dram_en,
|
||||||
we_a => ctrl_dram_we(i),
|
we_a => ctrl_dram_we(i),
|
||||||
we_b => cpu_dram_we(i),
|
we_b => cpu_dram_we(i),
|
||||||
addr_a => ctrl_dram_addr,
|
addr_a => ctrl_dram_addr,
|
||||||
@@ -286,24 +266,24 @@ cache_state_next:
|
|||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
cpu_busy <= cache_busy or instant_raw;
|
cpu_busy <= cache_busy;
|
||||||
cpu_dout <= cpu_dram_dout;
|
cpu_dout <= cpu_dram_dout;
|
||||||
|
|
||||||
tag_match <= '1' when tag_index_reg = cache_entry_out.tag else '0';
|
tag_match <= '1' when tag_index_reg = cache_entry_out.tag else '0';
|
||||||
cache_hit <= tag_match and cache_entry_out.valid;
|
cache_read_miss <= not (tag_match and cache_entry_out.valid) and not cpu_was_write;
|
||||||
|
cache_write_miss <= not (tag_match and cache_entry_out.valid and cpu_was_write);
|
||||||
tram_din <= to_tram_data(cache_entry_in);
|
tram_din <= to_tram_data(cache_entry_in);
|
||||||
tram_addr_rd <= cpu_cache_index when was_miss = '0' else cache_index_reg;
|
tram_addr_rd <= cpu_cache_index when was_miss = '0' else cache_index_reg;
|
||||||
cache_entry_out <= to_dcache_entry(tram_dout);
|
cache_entry_out <= to_dcache_entry(tram_dout);
|
||||||
cpu_dram_addr <= (cpu_cache_index & cpu_word_index) when (was_miss = '0' and cpu_hit_we = '0' and instant_raw = '0') else (cache_index_reg & word_index_reg);
|
cpu_dram_addr <= (cpu_cache_index & cpu_word_index) when (was_miss = '0' and cpu_we2 = '0') else (cache_index_reg & word_index_reg);
|
||||||
ADDR_O <= tag_index_reg & cache_index_reg & to_unsigned(mem_index_count, word_index_width) & "00";
|
ADDR_O <= tag_index_reg & cache_index_reg & to_unsigned(mem_index_count, word_index_width) & "00";
|
||||||
ctrl_dram_addr <= cache_index_reg & to_unsigned(ram_index_count, word_index_width);
|
ctrl_dram_addr <= cache_index_reg & to_unsigned(ram_index_count, word_index_width);
|
||||||
ctrl_dram_din <= DAT_I;
|
ctrl_dram_din <= DAT_I;
|
||||||
ctrl_dram_we <= (others => '1');
|
ctrl_dram_we <= (3 downto 0 => (data_write and ACK_I)) or ctrl_force_we;
|
||||||
ctrl_dram_en <= data_write and ACK_I;
|
cpu_dram_we <= cpu_we_reg when (cpu_we2 = '1' and cache_write_miss = '0') else (others => '0');
|
||||||
cpu_dram_we <= cpu_be_reg when (cpu_hit_we = '1') else (others => '0');
|
|
||||||
|
|
||||||
cache_state:
|
cache_state:
|
||||||
process(s, instant_raw, cache_hit, cache_index_count, ram_index_count, mem_index_count, cache_index_reg, ACK_I, tag_index_reg, cpu_en, SRDY_I, cpu_en2, cpu_we_reg)
|
process(s, cache_read_miss, cache_index_count, ram_index_count, mem_index_count, cache_index_reg, ACK_I, tag_index_reg, cpu_en, cpu_r_wn, SRDY_I, cpu_was_en, cpu_was_write, cpu_we_reg)
|
||||||
begin
|
begin
|
||||||
cpu_reg_en <= '0';
|
cpu_reg_en <= '0';
|
||||||
cache_busy <= '1';
|
cache_busy <= '1';
|
||||||
@@ -314,6 +294,7 @@ cache_state:
|
|||||||
mem_index_count_rst <= '0';
|
mem_index_count_rst <= '0';
|
||||||
CYC_O <= '0';
|
CYC_O <= '0';
|
||||||
STB_O <= '0';
|
STB_O <= '0';
|
||||||
|
dram_en <= '0';
|
||||||
tram_re <= '0';
|
tram_re <= '0';
|
||||||
was_miss <= '0';
|
was_miss <= '0';
|
||||||
data_write <= '0';
|
data_write <= '0';
|
||||||
@@ -322,6 +303,7 @@ cache_state:
|
|||||||
cache_entry_in.tag <= tag_index_reg;
|
cache_entry_in.tag <= tag_index_reg;
|
||||||
cache_entry_in.valid <= '0';
|
cache_entry_in.valid <= '0';
|
||||||
cache_entry_in.dirty <= '0';
|
cache_entry_in.dirty <= '0';
|
||||||
|
ctrl_force_we <= (others => '0');
|
||||||
sn <= s;
|
sn <= s;
|
||||||
|
|
||||||
case s is
|
case s is
|
||||||
@@ -330,9 +312,10 @@ cache_state:
|
|||||||
when ready =>
|
when ready =>
|
||||||
cache_busy <= '0';
|
cache_busy <= '0';
|
||||||
cpu_reg_en <= '1';
|
cpu_reg_en <= '1';
|
||||||
|
dram_en <= cpu_en or cpu_was_en;
|
||||||
tram_re <= cpu_en;
|
tram_re <= cpu_en;
|
||||||
if cpu_en2 = '1' then
|
if cpu_was_en = '1' then
|
||||||
if cache_hit = '0' and cpu_we_reg = '0' then
|
if cache_read_miss = '1' then
|
||||||
sn <= mem_request;
|
sn <= mem_request;
|
||||||
cpu_reg_en <= '0';
|
cpu_reg_en <= '0';
|
||||||
cache_busy <= '1';
|
cache_busy <= '1';
|
||||||
@@ -349,6 +332,7 @@ cache_state:
|
|||||||
sn <= ready;
|
sn <= ready;
|
||||||
if cpu_en = '1' then
|
if cpu_en = '1' then
|
||||||
cpu_reg_en <= '1';
|
cpu_reg_en <= '1';
|
||||||
|
dram_en <= '1';
|
||||||
tram_re <= '1';
|
tram_re <= '1';
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
@@ -382,12 +366,22 @@ cache_state:
|
|||||||
tram_addr_wr <= cache_index_reg;
|
tram_addr_wr <= cache_index_reg;
|
||||||
tram_we <= '1';
|
tram_we <= '1';
|
||||||
cache_entry_in.valid <= '1';
|
cache_entry_in.valid <= '1';
|
||||||
|
if cpu_was_write = '1' then
|
||||||
|
sn <= wr_cache;
|
||||||
|
else
|
||||||
sn <= rd_cache;
|
sn <= rd_cache;
|
||||||
|
end if;
|
||||||
|
|
||||||
when rd_cache =>
|
when rd_cache =>
|
||||||
tram_re <= '1';
|
tram_re <= '1';
|
||||||
|
dram_en <= '1';
|
||||||
was_miss <= '1';
|
was_miss <= '1';
|
||||||
sn <= ready;
|
sn <= ready;
|
||||||
|
|
||||||
|
when wr_cache =>
|
||||||
|
tram_re <= '1';
|
||||||
|
ctrl_force_we <= cpu_we_reg;
|
||||||
|
sn <= ready;
|
||||||
when others =>
|
when others =>
|
||||||
sn <= ready;
|
sn <= ready;
|
||||||
end case;
|
end case;
|
||||||
|
|||||||
+128
-192
@@ -51,8 +51,8 @@ entity bui is
|
|||||||
cpu_dmem_err : out STD_LOGIC;
|
cpu_dmem_err : out STD_LOGIC;
|
||||||
cpu_dmem_rdy : out STD_LOGIC;
|
cpu_dmem_rdy : out STD_LOGIC;
|
||||||
cpu_dmem_en : in STD_LOGIC;
|
cpu_dmem_en : in STD_LOGIC;
|
||||||
cpu_dmem_we : in STD_LOGIC;
|
cpu_dmem_re : in STD_LOGIC;
|
||||||
cpu_dmem_be : in unsigned(3 downto 0);
|
cpu_dmem_we : in unsigned(3 downto 0);
|
||||||
cpu_dmem_dout : in word_t;
|
cpu_dmem_dout : in word_t;
|
||||||
cpu_dmem_din : out word_t;
|
cpu_dmem_din : out word_t;
|
||||||
cpu_dmem_addr : in word_t
|
cpu_dmem_addr : in word_t
|
||||||
@@ -103,8 +103,8 @@ architecture behavior of bui is
|
|||||||
CYC_O : out STD_LOGIC;
|
CYC_O : out STD_LOGIC;
|
||||||
en : in STD_LOGIC;
|
en : in STD_LOGIC;
|
||||||
cpu_en : in STD_LOGIC;
|
cpu_en : in STD_LOGIC;
|
||||||
cpu_we : in STD_LOGIC;
|
cpu_r_wn : in STD_LOGIC;
|
||||||
cpu_be : in unsigned(3 downto 0);
|
cpu_we : in unsigned(3 downto 0);
|
||||||
cpu_addr : in word_t;
|
cpu_addr : in word_t;
|
||||||
cpu_din : in word_t;
|
cpu_din : in word_t;
|
||||||
cpu_dout : out word_t;
|
cpu_dout : out word_t;
|
||||||
@@ -112,36 +112,31 @@ architecture behavior of bui is
|
|||||||
);
|
);
|
||||||
END COMPONENT;
|
END COMPONENT;
|
||||||
|
|
||||||
type bus_state_t is (init, ready, icache_bus_access, dcache_bus_access, write_bus, read_bus, read_finish);
|
type bus_state_t is (init, ready, i_cache_bus_access, d_cache_bus_access, uncached_bus_access);
|
||||||
|
|
||||||
signal s, sn : bus_state_t;
|
signal s, sn : bus_state_t;
|
||||||
signal bus_idle : std_logic;
|
signal dmem_we : unsigned(3 downto 0);
|
||||||
signal busy : std_logic;
|
|
||||||
signal dmem_be : unsigned(3 downto 0);
|
|
||||||
signal dcache_dout : word_t;
|
signal dcache_dout : word_t;
|
||||||
signal dcache_mem_gnt : std_logic;
|
signal dcache_mem_gnt : std_logic;
|
||||||
signal icache_mem_gnt : std_logic;
|
signal icache_mem_gnt : std_logic;
|
||||||
signal dmem_mem_wr_gnt : std_logic;
|
signal dmem_mem_gnt : std_logic;
|
||||||
signal dmem_mem_rd_gnt : std_logic;
|
signal dcache_busy2 : std_logic;
|
||||||
signal dcache_busy : std_logic;
|
|
||||||
signal icache_busy : std_logic;
|
signal icache_busy : std_logic;
|
||||||
signal CYC_O_icache : std_logic;
|
signal CYC_O_icache : std_logic;
|
||||||
signal CYC_O_dcache : std_logic;
|
signal CYC_O_dcache : std_logic;
|
||||||
signal CYC_O_dmem_rd : std_logic;
|
signal CYC_O_dmem : std_logic;
|
||||||
signal CYC_O_dmem_wr : std_logic;
|
|
||||||
signal SRDY_I_icache : std_logic;
|
signal SRDY_I_icache : std_logic;
|
||||||
signal SRDY_I_dcache : std_logic;
|
signal SRDY_I_dcache : std_logic;
|
||||||
signal ADDR_O_icache : word_t;
|
signal ADDR_O_icache : word_t;
|
||||||
signal ADDR_O_dcache : word_t;
|
signal ADDR_O_dcache : word_t;
|
||||||
signal ADDR_O_dmem_rd : word_t;
|
signal ADDR_O_dmem : word_t;
|
||||||
signal ADDR_O_dmem_wr : word_t;
|
|
||||||
signal STB_O_icache : std_logic;
|
signal STB_O_icache : std_logic;
|
||||||
signal STB_O_dcache : std_logic;
|
signal STB_O_dcache : std_logic;
|
||||||
signal STB_O_dmem_rd : std_logic;
|
signal STB_O_dmem : std_logic;
|
||||||
signal STB_O_dmem_wr : std_logic;
|
signal DAT_I_dmem : word_t;
|
||||||
signal DAT_I_dmem_rd : word_t;
|
signal DAT_O_dmem : word_t;
|
||||||
signal DAT_O_dmem_wr : word_t;
|
signal SEL_O_dmem : unsigned(3 downto 0);
|
||||||
signal SEL_O_dmem_wr : unsigned(3 downto 0);
|
signal WE_O_dmem : std_logic;
|
||||||
signal dcached : std_logic;
|
signal dcached : std_logic;
|
||||||
signal dcache_en : std_logic;
|
signal dcache_en : std_logic;
|
||||||
signal uncached_access : std_logic;
|
signal uncached_access : std_logic;
|
||||||
@@ -150,52 +145,75 @@ architecture behavior of bui is
|
|||||||
signal bus_timeout_cnt : timeout_cnt_t;
|
signal bus_timeout_cnt : timeout_cnt_t;
|
||||||
signal bus_timeout : std_logic;
|
signal bus_timeout : std_logic;
|
||||||
|
|
||||||
signal bout_fifo_din : unsigned(68 downto 0);
|
|
||||||
signal bout_fifo_dout : unsigned(68 downto 0);
|
|
||||||
signal bout_fifo_re : std_logic;
|
|
||||||
signal bout_fifo_we : std_logic;
|
|
||||||
signal bout_fifo_full : std_logic;
|
|
||||||
signal bout_fifo_empty : std_logic;
|
|
||||||
signal bout_rdy : std_logic;
|
|
||||||
|
|
||||||
alias bout_fifo_addr_in is bout_fifo_din(31 downto 0);
|
|
||||||
alias bout_fifo_data_in is bout_fifo_din(63 downto 32);
|
|
||||||
alias bout_fifo_sel_in is bout_fifo_din(67 downto 64);
|
|
||||||
alias bout_fifo_we_in is bout_fifo_din(68);
|
|
||||||
alias bout_fifo_addr_out is bout_fifo_dout(31 downto 0);
|
|
||||||
alias bout_fifo_data_out is bout_fifo_dout(63 downto 32);
|
|
||||||
alias bout_fifo_sel_out is bout_fifo_dout(67 downto 64);
|
|
||||||
alias bout_fifo_we_out is bout_fifo_dout(68);
|
|
||||||
|
|
||||||
signal write_fifo_din : unsigned(67 downto 0);
|
|
||||||
signal write_fifo_dout : unsigned(67 downto 0);
|
|
||||||
signal write_fifo_re : std_logic;
|
|
||||||
signal write_fifo_we : std_logic;
|
|
||||||
signal write_fifo_full : std_logic;
|
|
||||||
signal write_fifo_empty : std_logic;
|
|
||||||
signal write_busy : std_logic;
|
|
||||||
|
|
||||||
alias write_fifo_addr_in is write_fifo_din(31 downto 0);
|
|
||||||
alias write_fifo_data_in is write_fifo_din(63 downto 32);
|
|
||||||
alias write_fifo_sel_in is write_fifo_din(67 downto 64);
|
|
||||||
alias write_fifo_addr_out is write_fifo_dout(31 downto 0);
|
|
||||||
alias write_fifo_data_out is write_fifo_dout(63 downto 32);
|
|
||||||
alias write_fifo_sel_out is write_fifo_dout(67 downto 64);
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
|
bus_strobe:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if RST_I = '1' then
|
||||||
|
STB_O <= '0';
|
||||||
|
elsif dmem_mem_gnt = '1' then
|
||||||
|
STB_O <= STB_O_dmem;
|
||||||
|
elsif SRDY_I_dcache = '1' then
|
||||||
|
STB_O <= STB_O_dcache;
|
||||||
|
elsif SRDY_I_icache = '1' then
|
||||||
|
STB_O <= STB_O_icache;
|
||||||
|
elsif SRDY_I = '1' then
|
||||||
|
STB_O <= '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
bus_cycle:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
CYC_O <= '0';
|
||||||
|
if dmem_mem_gnt = '1' then
|
||||||
|
CYC_O <= CYC_O_dmem;
|
||||||
|
elsif dcache_mem_gnt = '1' then
|
||||||
|
CYC_O <= CYC_O_dcache;
|
||||||
|
elsif icache_mem_gnt = '1' then
|
||||||
|
CYC_O <= CYC_O_icache;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
bus_out:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if RST_I = '1' then
|
||||||
|
ADDR_O <= (others => '0');
|
||||||
|
DAT_O <= (others => '0');
|
||||||
|
WE_O <= '0';
|
||||||
|
SEL_O <= (others => '0');
|
||||||
|
elsif dmem_mem_gnt = '1' then
|
||||||
|
ADDR_O <= ADDR_O_dmem;
|
||||||
|
DAT_O <= DAT_O_dmem;
|
||||||
|
WE_O <= WE_O_dmem;
|
||||||
|
SEL_O <= SEL_O_dmem;
|
||||||
|
elsif SRDY_I_dcache = '1' then
|
||||||
|
ADDR_O <= ADDR_O_dcache;
|
||||||
|
WE_O <= '0';
|
||||||
|
SEL_O <= (others => '0');
|
||||||
|
elsif SRDY_I_icache = '1' then
|
||||||
|
ADDR_O <= ADDR_O_icache;
|
||||||
|
WE_O <= '0';
|
||||||
|
SEL_O <= (others => '0');
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
MRDY_O <= '1';
|
MRDY_O <= '1';
|
||||||
CYC_O <= not bout_fifo_empty or dmem_mem_rd_gnt or dcache_mem_gnt or icache_mem_gnt;
|
|
||||||
STB_O <= not bout_fifo_empty;
|
SRDY_I_icache <= SRDY_I when icache_mem_gnt = '1' else '0';
|
||||||
ADDR_O <= bout_fifo_addr_out;
|
SRDY_I_dcache <= SRDY_I when dcache_mem_gnt = '1' else '0';
|
||||||
DAT_O <= bout_fifo_data_out;
|
-- SRDY_I_dmem <= SRDY_I when dmem_mem_gnt = '1' else '0';
|
||||||
SEL_O <= bout_fifo_sel_out;
|
|
||||||
WE_O <= bout_fifo_we_out;
|
|
||||||
|
|
||||||
cpu_imem_rdy <= not icache_busy after 4.5 ns;
|
cpu_imem_rdy <= not icache_busy after 4.5 ns;
|
||||||
busy <= CYC_O_dmem_rd or dcache_busy or (write_busy);
|
cpu_dmem_rdy <= not (CYC_O_dmem or dcache_busy2) after 4.5 ns;
|
||||||
cpu_dmem_rdy <= not busy after 4.5 ns;
|
|
||||||
|
|
||||||
inst_icache : icache
|
inst_icache : icache
|
||||||
GENERIC MAP
|
GENERIC MAP
|
||||||
@@ -220,8 +238,6 @@ inst_icache : icache
|
|||||||
cpu_busy => icache_busy
|
cpu_busy => icache_busy
|
||||||
);
|
);
|
||||||
|
|
||||||
SRDY_I_icache <= bout_rdy and icache_mem_gnt;
|
|
||||||
|
|
||||||
inst_dcache : dcache
|
inst_dcache : dcache
|
||||||
GENERIC MAP
|
GENERIC MAP
|
||||||
(
|
(
|
||||||
@@ -240,132 +256,64 @@ inst_dcache : dcache
|
|||||||
SRDY_I => SRDY_I_dcache,
|
SRDY_I => SRDY_I_dcache,
|
||||||
en => dcached,
|
en => dcached,
|
||||||
cpu_en => dcache_en,
|
cpu_en => dcache_en,
|
||||||
|
cpu_r_wn => cpu_dmem_re,
|
||||||
cpu_we => cpu_dmem_we,
|
cpu_we => cpu_dmem_we,
|
||||||
cpu_be => cpu_dmem_be,
|
|
||||||
cpu_addr => cpu_dmem_addr,
|
cpu_addr => cpu_dmem_addr,
|
||||||
cpu_din => cpu_dmem_dout,
|
cpu_din => cpu_dmem_dout,
|
||||||
cpu_dout => dcache_dout,
|
cpu_dout => dcache_dout,
|
||||||
cpu_busy => dcache_busy
|
cpu_busy => dcache_busy2
|
||||||
);
|
);
|
||||||
|
|
||||||
SRDY_I_dcache <= bout_rdy and dcache_mem_gnt;
|
|
||||||
|
|
||||||
dcached <= '1' when cpu_dmem_addr(31 downto 28) /= X"A" else '0';
|
dcached <= '1' when cpu_dmem_addr(31 downto 28) /= X"A" else '0';
|
||||||
cpu_dmem_din <= dcache_dout when uncached_access = '0' else DAT_I_dmem_rd;
|
cpu_dmem_din <= dcache_dout when uncached_access = '0' else DAT_I_dmem;
|
||||||
dcache_en <= cpu_dmem_en and not busy;
|
dcache_en <= cpu_dmem_en and not CYC_O_dmem;
|
||||||
|
|
||||||
-- Instantiate synchronous FIFO
|
dcache_flags:
|
||||||
inst_bout_fifo: entity work.fifo_sync
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
addr_width => 4,
|
|
||||||
data_width => 69
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
rst => RST_I,
|
|
||||||
clk => CLK_I,
|
|
||||||
we => bout_fifo_we,
|
|
||||||
re => bout_fifo_re,
|
|
||||||
fifo_full => bout_fifo_full,
|
|
||||||
fifo_empty => bout_fifo_empty,
|
|
||||||
fifo_afull => open,
|
|
||||||
fifo_aempty => open,
|
|
||||||
data_w => bout_fifo_din,
|
|
||||||
data_r => bout_fifo_dout
|
|
||||||
);
|
|
||||||
bout_rdy <= not bout_fifo_full;
|
|
||||||
bout_fifo_re <= not bout_fifo_empty and SRDY_I;
|
|
||||||
|
|
||||||
bout_fifo_we <= STB_O_dmem_wr when dmem_mem_wr_gnt = '1' else
|
|
||||||
STB_O_dmem_rd when dmem_mem_rd_gnt = '1' else
|
|
||||||
STB_O_dcache when dcache_mem_gnt = '1' else
|
|
||||||
STB_O_icache when icache_mem_gnt = '1' else '0';
|
|
||||||
|
|
||||||
|
|
||||||
bout_fifo_data_in <= DAT_O_dmem_wr when dmem_mem_wr_gnt = '1' else (others => '-');
|
|
||||||
|
|
||||||
bout_fifo_addr_in <= ADDR_O_dmem_wr when dmem_mem_wr_gnt = '1' else
|
|
||||||
ADDR_O_dmem_rd when dmem_mem_rd_gnt = '1' else
|
|
||||||
ADDR_O_dcache when dcache_mem_gnt = '1' else
|
|
||||||
ADDR_O_icache when icache_mem_gnt = '1' else (others => '-');
|
|
||||||
|
|
||||||
bout_fifo_sel_in <= SEL_O_dmem_wr when dmem_mem_wr_gnt = '1' else (others => '0');
|
|
||||||
bout_fifo_we_in <= '1' when dmem_mem_wr_gnt = '1' else '0';
|
|
||||||
|
|
||||||
-- Instantiate synchronous FIFO
|
|
||||||
inst_write_fifo: entity work.fifo_sync
|
|
||||||
GENERIC MAP
|
|
||||||
(
|
|
||||||
addr_width => 4,
|
|
||||||
data_width => 68,
|
|
||||||
almost_full_thresh => 12,
|
|
||||||
almost_empty_thresh => 4
|
|
||||||
)
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
rst => RST_I,
|
|
||||||
clk => CLK_I,
|
|
||||||
we => write_fifo_we,
|
|
||||||
re => write_fifo_re,
|
|
||||||
fifo_full => write_busy,
|
|
||||||
fifo_empty => write_fifo_empty,
|
|
||||||
fifo_afull => open,
|
|
||||||
fifo_aempty => open,
|
|
||||||
data_w => write_fifo_din,
|
|
||||||
data_r => write_fifo_dout
|
|
||||||
);
|
|
||||||
|
|
||||||
CYC_O_dmem_wr <= not write_fifo_empty;
|
|
||||||
DAT_O_dmem_wr <= write_fifo_data_out;
|
|
||||||
ADDR_O_dmem_wr <= write_fifo_addr_out;
|
|
||||||
SEL_O_dmem_wr <= write_fifo_sel_out;
|
|
||||||
|
|
||||||
write_fifo_data_in <= cpu_dmem_dout;
|
|
||||||
write_fifo_addr_in <= cpu_dmem_addr;
|
|
||||||
write_fifo_sel_in <= cpu_dmem_be;
|
|
||||||
write_fifo_re <= STB_O_dmem_wr;
|
|
||||||
write_fifo_we <= cpu_dmem_en and not busy and cpu_dmem_we;
|
|
||||||
|
|
||||||
dmem_rd_flags:
|
|
||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
uncached_access <= '0';
|
uncached_access <= '0';
|
||||||
if RST_I = '1' then
|
if RST_I = '1' then
|
||||||
CYC_O_dmem_rd <= '0';
|
CYC_O_dmem <= '0';
|
||||||
else
|
else
|
||||||
if ACK_I = '1' and dmem_mem_rd_gnt = '1' then
|
if ACK_I = '1' and dmem_mem_gnt = '1' then
|
||||||
uncached_access <= '1';
|
uncached_access <= not WE_O_dmem;
|
||||||
CYC_O_dmem_rd <= '0';
|
CYC_O_dmem <= '0';
|
||||||
end if;
|
end if;
|
||||||
if cpu_dmem_en = '1' and busy = '0' and cpu_dmem_we = '0' then
|
if cpu_dmem_en = '1' and CYC_O_dmem = '0' and dcache_busy2 = '0' then
|
||||||
if dcached = '0' then
|
CYC_O_dmem <= '1';
|
||||||
CYC_O_dmem_rd <= '1';
|
if dcached = '1' and cpu_dmem_re = '1' then
|
||||||
|
CYC_O_dmem <= '0';
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
dmem_rd_data:
|
dcache_data:
|
||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
if RST_I = '1' then
|
if RST_I = '1' then
|
||||||
DAT_I_dmem_rd <= (others => '0');
|
DAT_I_dmem <= (others => '0');
|
||||||
elsif ACK_I = '1' and CYC_O_dmem_rd = '1' then
|
elsif ACK_I = '1' and CYC_O_dmem = '1' then
|
||||||
DAT_I_dmem_rd <= DAT_I;
|
DAT_I_dmem <= DAT_I;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
dmem_rd_regs:
|
dcache_regs:
|
||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
if cpu_dmem_en = '1' and busy = '0' then
|
if RST_I = '1' then
|
||||||
ADDR_O_dmem_rd <= cpu_dmem_addr;
|
WE_O_dmem <= '0';
|
||||||
|
SEL_O_dmem <= (others => '0');
|
||||||
|
elsif cpu_dmem_en = '1' and CYC_O_dmem = '0' and dcache_busy2 = '0' then
|
||||||
|
DAT_O_dmem <= cpu_dmem_dout;
|
||||||
|
ADDR_O_dmem <= cpu_dmem_addr;
|
||||||
|
WE_O_dmem <= not cpu_dmem_re;
|
||||||
|
SEL_O_dmem <= cpu_dmem_we;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
@@ -383,60 +331,48 @@ bus_state_next:
|
|||||||
end process;
|
end process;
|
||||||
|
|
||||||
bus_state:
|
bus_state:
|
||||||
process(s, CYC_O_icache, CYC_O_dcache, CYC_O_dmem_wr, CYC_O_dmem_rd, bout_rdy, ACK_I)
|
process(s, CYC_O_icache, CYC_O_dcache, CYC_O_dmem, SRDY_I, ACK_I)
|
||||||
begin
|
begin
|
||||||
|
|
||||||
icache_mem_gnt <= '0';
|
icache_mem_gnt <= '0';
|
||||||
dcache_mem_gnt <= '0';
|
dcache_mem_gnt <= '0';
|
||||||
dmem_mem_rd_gnt <= '0';
|
dmem_mem_gnt <= '0';
|
||||||
dmem_mem_wr_gnt <= '0';
|
STB_O_dmem <= '0';
|
||||||
STB_O_dmem_rd <= '0';
|
|
||||||
STB_O_dmem_wr <= '0';
|
|
||||||
bus_idle <= '0';
|
|
||||||
sn <= s;
|
sn <= s;
|
||||||
case s is
|
case s is
|
||||||
when init =>
|
when init =>
|
||||||
sn <= ready;
|
sn <= ready;
|
||||||
when ready =>
|
when ready =>
|
||||||
bus_idle <= '1';
|
if CYC_O_dmem = '1' then
|
||||||
if CYC_O_dmem_wr = '1' then
|
dmem_mem_gnt <= '1';
|
||||||
sn <= write_bus;
|
if SRDY_I = '1' then
|
||||||
elsif CYC_O_dmem_rd = '1' then
|
STB_O_dmem <= '1';
|
||||||
sn <= read_bus;
|
sn <= uncached_bus_access;
|
||||||
elsif CYC_O_icache = '1' then
|
|
||||||
sn <= icache_bus_access;
|
|
||||||
elsif CYC_O_dcache = '1' then
|
|
||||||
sn <= dcache_bus_access;
|
|
||||||
end if;
|
end if;
|
||||||
when icache_bus_access =>
|
elsif CYC_O_icache = '1' then
|
||||||
|
sn <= i_cache_bus_access;
|
||||||
|
-- icache_mem_gnt <= '1';
|
||||||
|
elsif CYC_O_dcache = '1' then
|
||||||
|
sn <= d_cache_bus_access;
|
||||||
|
-- dcache_mem_gnt <= '1';
|
||||||
|
end if;
|
||||||
|
when i_cache_bus_access =>
|
||||||
icache_mem_gnt <= '1';
|
icache_mem_gnt <= '1';
|
||||||
if CYC_O_icache = '0' then
|
if CYC_O_icache = '0' then
|
||||||
sn <= ready;
|
sn <= ready;
|
||||||
|
-- icache_mem_gnt <= '0';
|
||||||
end if;
|
end if;
|
||||||
when dcache_bus_access =>
|
when d_cache_bus_access =>
|
||||||
dcache_mem_gnt <= '1';
|
dcache_mem_gnt <= '1';
|
||||||
if CYC_O_dcache = '0' then
|
if CYC_O_dcache = '0' then
|
||||||
sn <= ready;
|
sn <= ready;
|
||||||
|
-- dcache_mem_gnt <= '0';
|
||||||
end if;
|
end if;
|
||||||
when write_bus =>
|
when uncached_bus_access =>
|
||||||
dmem_mem_wr_gnt <= '1';
|
dmem_mem_gnt <= '1';
|
||||||
if CYC_O_dmem_wr = '1' then
|
|
||||||
if bout_rdy = '1' then
|
|
||||||
STB_O_dmem_wr <= '1';
|
|
||||||
end if;
|
|
||||||
else
|
|
||||||
sn <= ready;
|
|
||||||
end if;
|
|
||||||
when read_bus =>
|
|
||||||
dmem_mem_rd_gnt <= '1';
|
|
||||||
if bout_rdy = '1' then
|
|
||||||
STB_O_dmem_rd <= '1';
|
|
||||||
sn <= read_finish;
|
|
||||||
end if;
|
|
||||||
when read_finish =>
|
|
||||||
dmem_mem_rd_gnt <= '1';
|
|
||||||
if ACK_I = '1' then
|
if ACK_I = '1' then
|
||||||
sn <= ready;
|
sn <= ready;
|
||||||
|
-- dmem_mem_gnt <= '0';
|
||||||
end if;
|
end if;
|
||||||
when others =>
|
when others =>
|
||||||
sn <= ready;
|
sn <= ready;
|
||||||
@@ -448,7 +384,7 @@ bus_timeout_counter:
|
|||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
if bus_idle = '0' then
|
if (icache_mem_gnt or dcache_mem_gnt or dmem_mem_gnt) = '1' then
|
||||||
if bus_timeout_cnt /= 0 then
|
if bus_timeout_cnt /= 0 then
|
||||||
bus_timeout_cnt <= bus_timeout_cnt - 1;
|
bus_timeout_cnt <= bus_timeout_cnt - 1;
|
||||||
else
|
else
|
||||||
@@ -470,7 +406,7 @@ bus_err:
|
|||||||
cpu_dmem_err <= '0';
|
cpu_dmem_err <= '0';
|
||||||
elsif bus_timeout = '1' then
|
elsif bus_timeout = '1' then
|
||||||
cpu_imem_err <= icache_mem_gnt;
|
cpu_imem_err <= icache_mem_gnt;
|
||||||
cpu_dmem_err <= dcache_mem_gnt or dmem_mem_wr_gnt or dmem_mem_rd_gnt;
|
cpu_dmem_err <= dcache_mem_gnt or dmem_mem_gnt;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ entity pipeline is
|
|||||||
dmem_err : in STD_LOGIC;
|
dmem_err : in STD_LOGIC;
|
||||||
dmem_rdy : in STD_LOGIC;
|
dmem_rdy : in STD_LOGIC;
|
||||||
dmem_en : out STD_LOGIC;
|
dmem_en : out STD_LOGIC;
|
||||||
dmem_we : out STD_LOGIC;
|
dmem_re : out STD_LOGIC;
|
||||||
dmem_be : out unsigned(3 downto 0);
|
dmem_we : out unsigned(3 downto 0);
|
||||||
dmem_addr : out word_t;
|
dmem_addr : out word_t;
|
||||||
dmem_din : in word_t;
|
dmem_din : in word_t;
|
||||||
dmem_dout : out word_t
|
dmem_dout : out word_t
|
||||||
@@ -625,8 +625,8 @@ proc_stage_DMEM_ADDR:
|
|||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
dmem_be <= store_be(EX_stage.pa_off, EX_stage.ctrl.dmem_we, EX_stage.ctrl.word2_en, EX_stage.ctrl.word4_en, EX_stage.ctrl.align_left, EX_stage.ctrl.byte_en_byp) after 1 ns;
|
dmem_we <= store_be(EX_stage.pa_off, EX_stage.ctrl.dmem_we, EX_stage.ctrl.word2_en, EX_stage.ctrl.word4_en, EX_stage.ctrl.align_left, EX_stage.ctrl.byte_en_byp) after 1 ns;
|
||||||
dmem_we <= EX_stage.ctrl.dmem_we;
|
dmem_re <= not EX_stage.ctrl.dmem_we;
|
||||||
dmem_dout <= store_shift(EX_stage.reg_b, EX_stage.pa_off, EX_stage.ctrl.shift_offset, EX_stage.ctrl.shift_byp) after 1ns;
|
dmem_dout <= store_shift(EX_stage.reg_b, EX_stage.pa_off, EX_stage.ctrl.shift_offset, EX_stage.ctrl.shift_byp) after 1ns;
|
||||||
dmem_addr <= EX_stage.va;
|
dmem_addr <= EX_stage.va;
|
||||||
cop_din <= EX_stage.reg_b;
|
cop_din <= EX_stage.reg_b;
|
||||||
|
|||||||
@@ -66,8 +66,8 @@ architecture rtl of mips_top is
|
|||||||
dmem_err : in STD_LOGIC;
|
dmem_err : in STD_LOGIC;
|
||||||
dmem_rdy : in STD_LOGIC;
|
dmem_rdy : in STD_LOGIC;
|
||||||
dmem_en : out STD_LOGIC;
|
dmem_en : out STD_LOGIC;
|
||||||
dmem_we : out STD_LOGIC;
|
dmem_re : out STD_LOGIC;
|
||||||
dmem_be : out unsigned(3 downto 0);
|
dmem_we : out unsigned(3 downto 0);
|
||||||
dmem_addr : out word_t;
|
dmem_addr : out word_t;
|
||||||
dmem_din : in word_t;
|
dmem_din : in word_t;
|
||||||
dmem_dout : out word_t
|
dmem_dout : out word_t
|
||||||
@@ -81,11 +81,11 @@ architecture rtl of mips_top is
|
|||||||
signal dmem_err : std_logic;
|
signal dmem_err : std_logic;
|
||||||
signal dmem_rdy : std_logic;
|
signal dmem_rdy : std_logic;
|
||||||
signal dmem_en : std_logic;
|
signal dmem_en : std_logic;
|
||||||
signal dmem_we : std_logic;
|
signal dmem_re : std_logic;
|
||||||
signal dmem_addr : word_t;
|
signal dmem_addr : word_t;
|
||||||
signal dmem_dout : word_t;
|
signal dmem_dout : word_t;
|
||||||
signal dmem_din : word_t;
|
signal dmem_din : word_t;
|
||||||
signal dmem_be : unsigned(3 downto 0);
|
signal dmem_we : unsigned(3 downto 0);
|
||||||
|
|
||||||
|
|
||||||
COMPONENT bui
|
COMPONENT bui
|
||||||
@@ -111,8 +111,8 @@ architecture rtl of mips_top is
|
|||||||
cpu_dmem_err : out STD_LOGIC;
|
cpu_dmem_err : out STD_LOGIC;
|
||||||
cpu_dmem_rdy : out STD_LOGIC;
|
cpu_dmem_rdy : out STD_LOGIC;
|
||||||
cpu_dmem_en : in STD_LOGIC;
|
cpu_dmem_en : in STD_LOGIC;
|
||||||
cpu_dmem_we : in STD_LOGIC;
|
cpu_dmem_re : in STD_LOGIC;
|
||||||
cpu_dmem_be : in unsigned(3 downto 0);
|
cpu_dmem_we : in unsigned(3 downto 0);
|
||||||
cpu_dmem_dout : in word_t;
|
cpu_dmem_dout : in word_t;
|
||||||
cpu_dmem_din : out word_t;
|
cpu_dmem_din : out word_t;
|
||||||
cpu_dmem_addr : in word_t
|
cpu_dmem_addr : in word_t
|
||||||
@@ -140,8 +140,8 @@ inst_pipeline: pipeline
|
|||||||
dmem_err => dmem_err,
|
dmem_err => dmem_err,
|
||||||
dmem_rdy => dmem_rdy,
|
dmem_rdy => dmem_rdy,
|
||||||
dmem_en => dmem_en,
|
dmem_en => dmem_en,
|
||||||
|
dmem_re => dmem_re,
|
||||||
dmem_we => dmem_we,
|
dmem_we => dmem_we,
|
||||||
dmem_be => dmem_be,
|
|
||||||
dmem_addr => dmem_addr,
|
dmem_addr => dmem_addr,
|
||||||
dmem_din => dmem_din,
|
dmem_din => dmem_din,
|
||||||
dmem_dout => dmem_dout
|
dmem_dout => dmem_dout
|
||||||
@@ -170,8 +170,8 @@ inst_bui: bui
|
|||||||
cpu_dmem_err => dmem_err,
|
cpu_dmem_err => dmem_err,
|
||||||
cpu_dmem_rdy => dmem_rdy,
|
cpu_dmem_rdy => dmem_rdy,
|
||||||
cpu_dmem_en => dmem_en,
|
cpu_dmem_en => dmem_en,
|
||||||
|
cpu_dmem_re => dmem_re,
|
||||||
cpu_dmem_we => dmem_we,
|
cpu_dmem_we => dmem_we,
|
||||||
cpu_dmem_be => dmem_be,
|
|
||||||
cpu_dmem_addr => dmem_addr,
|
cpu_dmem_addr => dmem_addr,
|
||||||
cpu_dmem_din => dmem_din,
|
cpu_dmem_din => dmem_din,
|
||||||
cpu_dmem_dout => dmem_dout
|
cpu_dmem_dout => dmem_dout
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
vhdl work "../../../misc/utils_pkg.vhd"
|
||||||
|
vhdl work "../src/sdram_config.vhd"
|
||||||
|
vhdl work "../../../FIFO/src/fifo_ctrl_pkg.vhd"
|
||||||
|
vhdl work "../src/sdram_types.vhd"
|
||||||
|
vhdl work "../../../FIFO/src/sync_fifo_ctrl.vhd"
|
||||||
|
vhdl work "../../../FIFO/src/dpram.vhd"
|
||||||
|
vhdl work "../src/sdram_ctrl.vhd"
|
||||||
|
vhdl work "../src/sdram_cmd.vhd"
|
||||||
|
vhdl work "../src/reset_virtex4.vhd"
|
||||||
|
vhdl work "../src/fifo_sync.vhd"
|
||||||
|
vhdl work "../src/ddr_phy_virtex4.vhd"
|
||||||
|
vhdl work "../src/clockgen_virtex4.vhd"
|
||||||
|
vhdl work "../src/sdram_ctrl_top.vhd"
|
||||||
Binary file not shown.
@@ -0,0 +1,6 @@
|
|||||||
|
vlib simprim
|
||||||
|
|
||||||
|
vcom -93 -work simprim F:/Xilinx9/vhdl/src/simprims/simprim_Vcomponents_mti.vhd
|
||||||
|
vcom -93 -work simprim F:/Xilinx9/vhdl/src/simprims/simprim_Vpackage_mti.vhd
|
||||||
|
vcom -93 -work simprim F:/Xilinx9/vhdl/src/simprims/simprim_SMODEL_mti.vhd
|
||||||
|
vcom -93 -work simprim F:/Xilinx9/vhdl/src/simprims/simprim_VITAL_mti.vhd
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
vlib unisim
|
||||||
|
|
||||||
|
vcom -93 -work unisim F:/Xilinx9/vhdl/src/unisims/unisim_vpkg.vhd
|
||||||
|
vcom -93 -work unisim F:/Xilinx9/vhdl/src/unisims/unisim_vcomp.vhd
|
||||||
|
vcom -93 -work unisim F:/Xilinx9/vhdl/src/unisims/unisim_smodel.vhd
|
||||||
|
vcom -93 -work unisim F:/Xilinx9/vhdl/src/unisims/unisim_vital.vhd
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
## NOTE: Do not edit this file.
|
||||||
|
##
|
||||||
|
|
||||||
|
vlib work
|
||||||
|
vcom -explicit -93 "../../../FIFO/src/fifo_ctrl_pkg.vhd"
|
||||||
|
vcom -explicit -93 "../../../misc/dpram_1w1r_dist.vhd"
|
||||||
|
vcom -explicit -93 "../../../FIFO/src/sync_fifo_ctrl.vhd"
|
||||||
|
vcom -explicit -93 "../../../misc/utils_pkg.vhd"
|
||||||
|
vcom -explicit -93 "../../../misc/clockgen_virtex4.vhd"
|
||||||
|
vcom -explicit -93 "../src/fifo_sync.vhd"
|
||||||
|
vcom -explicit -93 "../src/sdram_config.vhd"
|
||||||
|
vcom -explicit -93 "../src/sdram_types.vhd"
|
||||||
|
vcom -explicit -93 "../src/reset_virtex4.vhd"
|
||||||
|
vcom -explicit -93 "../src/sdram_cmd.vhd"
|
||||||
|
vcom -explicit -93 "../src/sdram_ctrl.vhd"
|
||||||
|
vcom -explicit -93 "../src/ddr_phy_virtex4.vhd"
|
||||||
|
vcom -explicit -93 "../src/sdram_ctrl_top.vhd"
|
||||||
|
vcom -explicit -93 "../src/sdram_ctrl_frontend_wb.vhd"
|
||||||
|
vcom -explicit -93 "../src/mt46v16m16.vhd"
|
||||||
|
vcom -explicit -93 "../src/tb_sdram_ctrl_frontend_wb.vhd"
|
||||||
|
|
||||||
|
#restart -force
|
||||||
|
vsim -t 1ps -lib work tb_sdram_ctrl_frontend_wb
|
||||||
|
do {tb_sdram_ctrl_frontend_wb.wdo}
|
||||||
|
view wave
|
||||||
|
view structure
|
||||||
|
view signals
|
||||||
|
run 10us
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
onerror {resume}
|
||||||
|
quietly WaveActivateNextPane {} 0
|
||||||
|
add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/clk_o
|
||||||
|
add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/rst_o
|
||||||
|
add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/cyc_o
|
||||||
|
add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/stb_o
|
||||||
|
add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/we_o
|
||||||
|
add wave -noupdate -format Literal /tb_sdram_ctrl_frontend_wb/sel_o
|
||||||
|
add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/ack_i
|
||||||
|
add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/mrdy_o
|
||||||
|
add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/srdy_i
|
||||||
|
add wave -noupdate -format Literal -radix hexadecimal /tb_sdram_ctrl_frontend_wb/addr_o
|
||||||
|
add wave -noupdate -format Literal -radix hexadecimal /tb_sdram_ctrl_frontend_wb/dat_i
|
||||||
|
add wave -noupdate -format Literal -radix hexadecimal /tb_sdram_ctrl_frontend_wb/dat_o
|
||||||
|
add wave -noupdate -format Literal -radix hexadecimal /tb_sdram_ctrl_frontend_wb/dout_reg
|
||||||
|
add wave -noupdate -format Literal /tb_sdram_ctrl_frontend_wb/dout_cnt
|
||||||
|
add wave -noupdate -divider Part
|
||||||
|
add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/part_cs_n
|
||||||
|
add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/part_we_n
|
||||||
|
add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/part_ras_n
|
||||||
|
add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/part_cas_n
|
||||||
|
add wave -noupdate -format Literal /tb_sdram_ctrl_frontend_wb/part_ba
|
||||||
|
add wave -noupdate -format Literal /tb_sdram_ctrl_frontend_wb/part_dm
|
||||||
|
add wave -noupdate -format Literal /tb_sdram_ctrl_frontend_wb/part_dqs
|
||||||
|
add wave -noupdate -format Literal -radix hexadecimal /tb_sdram_ctrl_frontend_wb/part_addr
|
||||||
|
add wave -noupdate -format Literal -radix hexadecimal /tb_sdram_ctrl_frontend_wb/part_data
|
||||||
|
TreeUpdate [SetDefaultTree]
|
||||||
|
WaveRestoreCursors {{Cursor 1} {8165533 ps} 0}
|
||||||
|
configure wave -namecolwidth 150
|
||||||
|
configure wave -valuecolwidth 100
|
||||||
|
configure wave -justifyvalue left
|
||||||
|
configure wave -signalnamewidth 1
|
||||||
|
configure wave -snapdistance 10
|
||||||
|
configure wave -datasetprefix 0
|
||||||
|
configure wave -rowmargin 4
|
||||||
|
configure wave -childrowmargin 2
|
||||||
|
configure wave -gridoffset 0
|
||||||
|
configure wave -gridperiod 1
|
||||||
|
configure wave -griddelta 40
|
||||||
|
configure wave -timeline 0
|
||||||
|
update
|
||||||
|
WaveRestoreZoom {7279048 ps} {8233593 ps}
|
||||||
@@ -0,0 +1,389 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: SDRAM controller
|
||||||
|
-- This file: DDR physical layer (Virtex-4 specific)
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This program is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published by
|
||||||
|
-- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This program 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 General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.numeric_std.ALL;
|
||||||
|
|
||||||
|
use work.sdram_config.all;
|
||||||
|
use work.sdram_types.all;
|
||||||
|
|
||||||
|
Library UNISIM;
|
||||||
|
use UNISIM.vcomponents.all;
|
||||||
|
|
||||||
|
entity ddr_phy is
|
||||||
|
Port (
|
||||||
|
sys_rst : in STD_LOGIC;
|
||||||
|
sys_clk0 : in STD_LOGIC;
|
||||||
|
sys_clk270 : in STD_LOGIC;
|
||||||
|
u_tag_in : in user_tag_t;
|
||||||
|
u_tag_rd : out user_tag_t;
|
||||||
|
u_tag_wr : out user_tag_t;
|
||||||
|
read_clk : in STD_LOGIC;
|
||||||
|
phy_ctrl : in phy_ctrl_t;
|
||||||
|
part_ctrl : in part_ctrl_t;
|
||||||
|
sdr_data_w : in unsigned(SDR_DATA_WIDTH-1 downto 0);
|
||||||
|
sdr_dm_wr_in : in unsigned(SDR_DM_WIDTH-1 downto 0);
|
||||||
|
sdr_dm_rd_in : in unsigned(SDR_DM_WIDTH-1 downto 0);
|
||||||
|
sdr_dm_rd_out : out unsigned(SDR_DM_WIDTH-1 downto 0);
|
||||||
|
sdr_data_r : out unsigned(SDR_DATA_WIDTH-1 downto 0);
|
||||||
|
sdr_data_vld : out STD_LOGIC;
|
||||||
|
sdr_data_req_w : out STD_LOGIC;
|
||||||
|
sdr_data_req_r : out STD_LOGIC;
|
||||||
|
part_clk_p : out STD_LOGIC;
|
||||||
|
part_clk_n : out STD_LOGIC;
|
||||||
|
part_dm : out unsigned(DDR_DM_WIDTH-1 downto 0);
|
||||||
|
part_dqs : inout unsigned(DDR_DQS_WIDTH-1 downto 0);
|
||||||
|
part_data : inout unsigned(DDR_DATA_WIDTH-1 downto 0);
|
||||||
|
part_ba : out unsigned(DDR_BANK_WIDTH-1 downto 0);
|
||||||
|
part_addr : out unsigned(DDR_ADDR_WIDTH-1 downto 0);
|
||||||
|
part_cs_n : out STD_LOGIC;
|
||||||
|
part_we_n : out STD_LOGIC;
|
||||||
|
part_cas_n : out STD_LOGIC;
|
||||||
|
part_ras_n : out STD_LOGIC;
|
||||||
|
part_cke : out STD_LOGIC
|
||||||
|
);
|
||||||
|
end ddr_phy;
|
||||||
|
|
||||||
|
architecture tech of ddr_phy is
|
||||||
|
|
||||||
|
signal dqs_drive : std_logic;
|
||||||
|
signal drive : std_logic;
|
||||||
|
signal dqs : unsigned(DDR_DQS_WIDTH-1 downto 0);
|
||||||
|
signal dqs_zen : unsigned(DDR_DQS_WIDTH-1 downto 0);
|
||||||
|
signal dqs_rst : std_logic;
|
||||||
|
signal ddr_data_w : unsigned(DDR_DATA_WIDTH-1 downto 0);
|
||||||
|
signal data_r : unsigned(SDR_DATA_WIDTH-1 downto 0);
|
||||||
|
signal data_reg_r : unsigned(SDR_DATA_WIDTH-1 downto 0);
|
||||||
|
signal drive270 : unsigned(DDR_DATA_WIDTH-1 downto 0);
|
||||||
|
signal part_ctrl_reg : part_ctrl_t;
|
||||||
|
signal we_reg : std_logic;
|
||||||
|
signal read_en : std_logic;
|
||||||
|
|
||||||
|
type u_tag_array_t is array (natural range 0 to 4) of user_tag_t;
|
||||||
|
signal u_tag_pipe : u_tag_array_t;
|
||||||
|
|
||||||
|
type dm_out_array_t is array (natural range 0 to 4) of unsigned(SDR_DM_WIDTH-1 downto 0);
|
||||||
|
signal dm_out_pipe : dm_out_array_t;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
utag_pipe:
|
||||||
|
process(sys_rst, sys_clk0)
|
||||||
|
begin
|
||||||
|
if rising_edge(sys_clk0) then
|
||||||
|
for i in u_tag_pipe'length-1 downto 1 loop
|
||||||
|
u_tag_pipe(i) <= u_tag_pipe(i-1);
|
||||||
|
end loop;
|
||||||
|
if phy_ctrl.utag_we = '1' then
|
||||||
|
u_tag_pipe(0) <= u_tag_in;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
dmout_pipe:
|
||||||
|
process(sys_rst, sys_clk0)
|
||||||
|
begin
|
||||||
|
if rising_edge(sys_clk0) then
|
||||||
|
for i in dm_out_pipe'length-1 downto 1 loop
|
||||||
|
dm_out_pipe(i) <= dm_out_pipe(i-1);
|
||||||
|
end loop;
|
||||||
|
if phy_ctrl.utag_we = '1' then
|
||||||
|
dm_out_pipe(0) <= sdr_dm_rd_in;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
WE_REGISTER:
|
||||||
|
process(sys_rst, sys_clk0)
|
||||||
|
begin
|
||||||
|
if sys_rst = '1' then
|
||||||
|
we_reg <= '0';
|
||||||
|
elsif rising_edge(sys_clk0) then
|
||||||
|
we_reg <= phy_ctrl.we;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
DATA_DRIVE_GEN:
|
||||||
|
process(sys_clk0)
|
||||||
|
begin
|
||||||
|
if falling_edge(sys_clk0) then
|
||||||
|
dqs_rst <= not we_reg;
|
||||||
|
drive <= we_reg;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
DQS_DRIVE_GEN:
|
||||||
|
process(sys_clk0)
|
||||||
|
variable p : unsigned(1 downto 0);
|
||||||
|
begin
|
||||||
|
if rising_edge(sys_clk0) then
|
||||||
|
if phy_ctrl.drive_en = '1' then
|
||||||
|
p := (others => '1');
|
||||||
|
else
|
||||||
|
p := p(p'left-1 downto 0) & '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
dqs_drive <= p(p'left);
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- SDRAM Clock
|
||||||
|
ODDR_clk_p : ODDR
|
||||||
|
generic map
|
||||||
|
(
|
||||||
|
DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE"
|
||||||
|
INIT => '0', -- Initial value for Q port ('1' or '0')
|
||||||
|
SRTYPE => "SYNC" -- Reset Type ("ASYNC" or "SYNC")
|
||||||
|
)
|
||||||
|
port map (
|
||||||
|
Q => part_clk_p, -- 1-bit DDR output
|
||||||
|
C => sys_clk0, -- 1-bit clock input
|
||||||
|
CE => '1', -- 1-bit clock enable input
|
||||||
|
D1 => '1', -- 1-bit data input (positive edge)
|
||||||
|
D2 => '0', -- 1-bit data input (negative edge)
|
||||||
|
R => '0', -- 1-bit reset input
|
||||||
|
S => '0' -- 1-bit set input
|
||||||
|
);
|
||||||
|
|
||||||
|
ODDR_clk_n : ODDR
|
||||||
|
generic map
|
||||||
|
(
|
||||||
|
DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE"
|
||||||
|
INIT => '0', -- Initial value for Q port ('1' or '0')
|
||||||
|
SRTYPE => "SYNC" -- Reset Type ("ASYNC" or "SYNC")
|
||||||
|
)
|
||||||
|
port map (
|
||||||
|
Q => part_clk_n, -- 1-bit DDR output
|
||||||
|
C => sys_clk0, -- 1-bit clock input
|
||||||
|
CE => '1', -- 1-bit clock enable input
|
||||||
|
D1 => '0', -- 1-bit data input (positive edge)
|
||||||
|
D2 => '1', -- 1-bit data input (negative edge)
|
||||||
|
R => '0', -- 1-bit reset input
|
||||||
|
S => '0' -- 1-bit set input
|
||||||
|
);
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Data OUT DDR-FFs
|
||||||
|
gen_ddr_data_out:
|
||||||
|
for n in 0 to DDR_DATA_WIDTH-1 generate
|
||||||
|
begin
|
||||||
|
ODDR_data : ODDR
|
||||||
|
generic map
|
||||||
|
(
|
||||||
|
DDR_CLK_EDGE => "SAME_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE"
|
||||||
|
INIT => '0', -- Initial value for Q port ('1' or '0')
|
||||||
|
SRTYPE => "SYNC" -- Reset Type ("ASYNC" or "SYNC")
|
||||||
|
)
|
||||||
|
port map (
|
||||||
|
Q => ddr_data_w(n), -- 1-bit DDR output
|
||||||
|
C => sys_clk270, -- 1-bit clock input
|
||||||
|
CE => '1', -- 1-bit clock enable input
|
||||||
|
D1 => sdr_data_w(n + DDR_DATA_WIDTH), -- 1-bit data input (positive edge)
|
||||||
|
D2 => sdr_data_w(n), -- 1-bit data input (negative edge)
|
||||||
|
R => '0', -- 1-bit reset input
|
||||||
|
S => '0' -- 1-bit set input
|
||||||
|
);
|
||||||
|
end generate gen_ddr_data_out;
|
||||||
|
|
||||||
|
-- Sample tristate on clock90
|
||||||
|
process (sys_clk270)
|
||||||
|
begin
|
||||||
|
if rising_edge(sys_clk270) then
|
||||||
|
for n in 0 to DDR_DATA_WIDTH-1 loop
|
||||||
|
drive270(n) <= drive;
|
||||||
|
end loop;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Output mux
|
||||||
|
out_mux_data:
|
||||||
|
for n in 0 to DDR_DATA_WIDTH-1 generate
|
||||||
|
part_data(n) <= ddr_data_w(n) when drive270(n) = '1' else 'Z';
|
||||||
|
end generate;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Data-mask OUT DDR-FFs
|
||||||
|
gen_ddr_dm_out:
|
||||||
|
for n in 0 to DDR_DM_WIDTH-1 generate
|
||||||
|
begin
|
||||||
|
ODDR_dm : ODDR
|
||||||
|
generic map
|
||||||
|
(
|
||||||
|
DDR_CLK_EDGE => "SAME_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE"
|
||||||
|
INIT => '0', -- Initial value for Q port ('1' or '0')
|
||||||
|
SRTYPE => "SYNC" -- Reset Type ("ASYNC" or "SYNC")
|
||||||
|
)
|
||||||
|
port map (
|
||||||
|
Q => part_dm(n), -- 1-bit DDR output
|
||||||
|
C => sys_clk270, -- 1-bit clock input
|
||||||
|
CE => '1', -- 1-bit clock enable input
|
||||||
|
D1 => sdr_dm_wr_in(n + DDR_DM_WIDTH), -- 1-bit data input (positive edge)
|
||||||
|
D2 => sdr_dm_wr_in(n), -- 1-bit data input (negative edge)
|
||||||
|
R => '0', -- 1-bit reset input
|
||||||
|
S => '0' -- 1-bit set input
|
||||||
|
);
|
||||||
|
end generate gen_ddr_dm_out;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- DQS OUT DDR-FFs
|
||||||
|
gen_dqs_out:
|
||||||
|
for n in 0 to DDR_DQS_WIDTH-1 generate
|
||||||
|
begin
|
||||||
|
ODDR_dqs : ODDR
|
||||||
|
generic map
|
||||||
|
(
|
||||||
|
DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE"
|
||||||
|
INIT => '0', -- Initial value for Q port ('1' or '0')
|
||||||
|
SRTYPE => "SYNC" -- Reset Type ("ASYNC" or "SYNC")
|
||||||
|
)
|
||||||
|
port map (
|
||||||
|
Q => dqs(n), -- 1-bit DDR output
|
||||||
|
C => sys_clk0, -- 1-bit clock input
|
||||||
|
CE => '1', -- 1-bit clock enable input
|
||||||
|
D2 => '0', -- 1-bit data input (positive edge)
|
||||||
|
D1 => '1', -- 1-bit data input (negative edge)
|
||||||
|
R => dqs_rst, -- 1-bit reset input
|
||||||
|
S => '0' -- 1-bit set input
|
||||||
|
);
|
||||||
|
end generate gen_dqs_out;
|
||||||
|
|
||||||
|
-- Tristate-Control fuer dqs
|
||||||
|
process (sys_clk0) is
|
||||||
|
variable zctrl : boolean;
|
||||||
|
begin
|
||||||
|
if rising_edge(sys_clk0) then
|
||||||
|
if dqs_drive = '1' then
|
||||||
|
zctrl := false;
|
||||||
|
else
|
||||||
|
zctrl := true;
|
||||||
|
end if;
|
||||||
|
if zctrl then
|
||||||
|
dqs_zen <= (others => '1');
|
||||||
|
else
|
||||||
|
dqs_zen <= (others => '0');
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Tristate-Buffer fuer dqs
|
||||||
|
gen_out_mux_dqs:
|
||||||
|
for n in 0 to DDR_DQS_WIDTH-1 generate
|
||||||
|
part_dqs(n) <= 'Z' when dqs_zen(n)='1' else dqs(n);
|
||||||
|
end generate gen_out_mux_dqs;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
process (sys_rst, sys_clk0) is
|
||||||
|
begin
|
||||||
|
if sys_rst = '1' then
|
||||||
|
part_ctrl_reg.cmd <= COMMAND(SD_DESELECT);
|
||||||
|
part_ctrl_reg.ba <= (others=>'0');
|
||||||
|
part_ctrl_reg.addr <= (others=>'0');
|
||||||
|
part_ctrl_reg.cke <= '0';
|
||||||
|
elsif rising_edge(sys_clk0) then
|
||||||
|
part_ctrl_reg <= part_ctrl;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
process (sys_clk0) is
|
||||||
|
begin
|
||||||
|
if falling_edge(sys_clk0) then
|
||||||
|
part_ras_n <= part_ctrl_reg.cmd.ras_n;
|
||||||
|
part_cas_n <= part_ctrl_reg.cmd.cas_n;
|
||||||
|
part_we_n <= part_ctrl_reg.cmd.we_n;
|
||||||
|
part_cs_n <= part_ctrl_reg.cmd.cs_n;
|
||||||
|
part_ba <= part_ctrl_reg.ba;
|
||||||
|
part_addr <= part_ctrl_reg.addr;
|
||||||
|
part_cke <= part_ctrl_reg.cke;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
-- READ DATA Processing
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
gen_ddr_data_in:
|
||||||
|
for n in 0 to DDR_DATA_WIDTH-1 generate
|
||||||
|
begin
|
||||||
|
IDDR_data : IDDR
|
||||||
|
generic map
|
||||||
|
(
|
||||||
|
DDR_CLK_EDGE => "SAME_EDGE", -- "OPPOSITE_EDGE", "SAME_EDGE" or "SAME_EDGE_PIPELINED"
|
||||||
|
INIT_Q1 => '0', -- Initial value of Q1: '0' or '1'
|
||||||
|
INIT_Q2 => '0', -- Initial value of Q2: '0' or '1'
|
||||||
|
SRTYPE => "SYNC" -- Set/Reset type: "SYNC" or "ASYNC"
|
||||||
|
)
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
Q1 => data_r(n), -- 1-bit output for positive edge of clock
|
||||||
|
Q2 => data_r(n + DDR_DATA_WIDTH), -- 1-bit output for negative edge of clock
|
||||||
|
C => read_clk, -- 1-bit clock input
|
||||||
|
CE => read_en, -- 1-bit clock enable input
|
||||||
|
D => part_data(n), -- 1-bit DDR data input
|
||||||
|
R => '0', -- 1-bit reset
|
||||||
|
S => '0' -- 1-bit set
|
||||||
|
);
|
||||||
|
end generate;
|
||||||
|
|
||||||
|
|
||||||
|
data_sample_stage:
|
||||||
|
process (sys_clk0)
|
||||||
|
begin
|
||||||
|
if falling_edge(sys_clk0) then
|
||||||
|
data_reg_r <= data_r;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
misc_flags_and_data_out:
|
||||||
|
process (sys_rst, sys_clk0)
|
||||||
|
variable p : unsigned(3 downto 0);
|
||||||
|
begin
|
||||||
|
if sys_rst = '1' then
|
||||||
|
p := (others => '0');
|
||||||
|
read_en <= '0';
|
||||||
|
sdr_data_vld <= '0';
|
||||||
|
sdr_data_req_w <= '0';
|
||||||
|
sdr_data_req_r <= '0';
|
||||||
|
elsif rising_edge(sys_clk0) then
|
||||||
|
sdr_data_r <= data_reg_r;
|
||||||
|
if p(3) = '1' then
|
||||||
|
u_tag_rd <= u_tag_pipe(4);
|
||||||
|
sdr_dm_rd_out <= dm_out_pipe(4);
|
||||||
|
end if;
|
||||||
|
if phy_ctrl.we = '1' then
|
||||||
|
u_tag_wr <= u_tag_pipe(0);
|
||||||
|
end if;
|
||||||
|
sdr_data_req_w <= phy_ctrl.we;
|
||||||
|
sdr_data_req_r <= phy_ctrl.re;
|
||||||
|
sdr_data_vld <= p(3);
|
||||||
|
read_en <= p(1);
|
||||||
|
if phy_ctrl.re = '1' then
|
||||||
|
p := p(p'left-1 downto 0) & '1';
|
||||||
|
else
|
||||||
|
p := p(p'left-1 downto 0) & '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
end tech;
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||||
|
-- This file: Dual-ported register file with asynchrous read
|
||||||
|
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
|
||||||
|
-- This library 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 library 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 library; if not, write to the Free Software
|
||||||
|
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
LIBRARY IEEE;
|
||||||
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
|
|
||||||
|
use work.fifo_ctrl_pkg.all;
|
||||||
|
|
||||||
|
entity fifo_sync is
|
||||||
|
Generic (
|
||||||
|
addr_width : natural := 4;
|
||||||
|
data_width : natural := 8;
|
||||||
|
almost_full_thresh : integer := 12;
|
||||||
|
almost_empty_thresh : integer := 4
|
||||||
|
);
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
rst : in STD_LOGIC;
|
||||||
|
clk : in STD_LOGIC;
|
||||||
|
we : in STD_LOGIC;
|
||||||
|
re : in STD_LOGIC;
|
||||||
|
fifo_full : out STD_LOGIC;
|
||||||
|
fifo_empty : out STD_LOGIC;
|
||||||
|
fifo_afull : out STD_LOGIC;
|
||||||
|
fifo_aempty : out STD_LOGIC;
|
||||||
|
data_w : in unsigned (data_width-1 downto 0);
|
||||||
|
data_r : out unsigned (data_width-1 downto 0)
|
||||||
|
);
|
||||||
|
end fifo_sync;
|
||||||
|
|
||||||
|
architecture Behavioral of fifo_sync is
|
||||||
|
|
||||||
|
signal mem_wr_en : STD_LOGIC;
|
||||||
|
signal mem_rd_en : STD_LOGIC;
|
||||||
|
signal ptr_w : unsigned (addr_width-1 downto 0);
|
||||||
|
signal ptr_r : unsigned (addr_width-1 downto 0);
|
||||||
|
signal full : STD_LOGIC;
|
||||||
|
signal empty : STD_LOGIC;
|
||||||
|
signal almost_full : STD_LOGIC;
|
||||||
|
signal almost_empty : STD_LOGIC;
|
||||||
|
signal pre_full : STD_LOGIC;
|
||||||
|
signal pre_empty : STD_LOGIC;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
mem_wr_en <= not full;
|
||||||
|
mem_rd_en <= not pre_empty;
|
||||||
|
fifo_full <= full;
|
||||||
|
fifo_empty <= empty;
|
||||||
|
fifo_afull <= almost_full;
|
||||||
|
fifo_aempty <= almost_empty;
|
||||||
|
|
||||||
|
inst_sync_fifo_ctrl: entity work.sync_fifo_ctrl
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
addr_width => addr_width,
|
||||||
|
almost_full_thresh => almost_full_thresh,
|
||||||
|
almost_empty_thresh => almost_empty_thresh
|
||||||
|
)
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
rst => rst,
|
||||||
|
clk => clk,
|
||||||
|
we => we,
|
||||||
|
re => re,
|
||||||
|
ptr_w => ptr_w,
|
||||||
|
ptr_r => ptr_r,
|
||||||
|
fifo_full => full,
|
||||||
|
fifo_empty => empty,
|
||||||
|
fifo_pre_full => pre_full,
|
||||||
|
fifo_pre_empty => pre_empty,
|
||||||
|
fifo_afull => almost_full,
|
||||||
|
fifo_aempty => almost_empty
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
inst_dpram_1w1r: entity work.dpram_1w1r_dist
|
||||||
|
GENERIC MAP (
|
||||||
|
addr_width => addr_width,
|
||||||
|
data_width => data_width
|
||||||
|
)
|
||||||
|
PORT MAP(
|
||||||
|
clka => clk,
|
||||||
|
clkb => clk,
|
||||||
|
en_a => mem_wr_en,
|
||||||
|
en_b => mem_rd_en,
|
||||||
|
we_a => we,
|
||||||
|
addr_a => ptr_w,
|
||||||
|
addr_b => ptr_r,
|
||||||
|
din_a => data_w,
|
||||||
|
dout_b => data_r
|
||||||
|
);
|
||||||
|
|
||||||
|
end Behavioral;
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,111 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: SDRAM controller
|
||||||
|
-- This file: Reset generator (Virtex-4 specific)
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This program is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published by
|
||||||
|
-- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This program 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 General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
|
||||||
|
Library UNISIM;
|
||||||
|
use UNISIM.vcomponents.all;
|
||||||
|
|
||||||
|
entity reset is
|
||||||
|
port
|
||||||
|
(
|
||||||
|
clk : in std_logic;
|
||||||
|
rst_in : in std_logic;
|
||||||
|
rst_out : out std_logic
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
|
||||||
|
architecture tech of reset is
|
||||||
|
|
||||||
|
signal rst : std_logic;
|
||||||
|
signal shift_pipe : std_logic_vector(3 downto 0);
|
||||||
|
attribute KEEP : string;
|
||||||
|
attribute KEEP of shift_pipe : signal is "TRUE";
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
rst <= shift_pipe(0);
|
||||||
|
|
||||||
|
bufg_reset: bufg
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
o => rst_out,
|
||||||
|
i => rst
|
||||||
|
);
|
||||||
|
|
||||||
|
fdp0: fdp
|
||||||
|
generic map
|
||||||
|
(
|
||||||
|
init => '1'
|
||||||
|
)
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
d => rst_in,
|
||||||
|
c => clk,
|
||||||
|
pre => '0',
|
||||||
|
q => shift_pipe(3)
|
||||||
|
);
|
||||||
|
|
||||||
|
fdp1: fdp
|
||||||
|
generic map
|
||||||
|
(
|
||||||
|
init => '1'
|
||||||
|
)
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
|
||||||
|
d => shift_pipe(3),
|
||||||
|
c => clk,
|
||||||
|
pre => '0',
|
||||||
|
q => shift_pipe(2)
|
||||||
|
);
|
||||||
|
|
||||||
|
fdp2: fdp
|
||||||
|
generic map
|
||||||
|
(
|
||||||
|
init => '1'
|
||||||
|
)
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
d => shift_pipe(2),
|
||||||
|
c => clk,
|
||||||
|
pre => '0',
|
||||||
|
q => shift_pipe(1)
|
||||||
|
);
|
||||||
|
|
||||||
|
fdp3: fdp
|
||||||
|
generic map
|
||||||
|
(
|
||||||
|
init => '1'
|
||||||
|
)
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
|
||||||
|
d => shift_pipe(1),
|
||||||
|
c => clk,
|
||||||
|
pre => '0',
|
||||||
|
q => shift_pipe(0)
|
||||||
|
);
|
||||||
|
|
||||||
|
end tech;
|
||||||
@@ -0,0 +1,269 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: SDRAM controller
|
||||||
|
-- This file: SDRAM command controller
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This program is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published by
|
||||||
|
-- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This program 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 General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.numeric_std.ALL;
|
||||||
|
|
||||||
|
use work.sdram_config.all;
|
||||||
|
use work.sdram_types.all;
|
||||||
|
|
||||||
|
entity sdram_cmd is
|
||||||
|
Generic (BL : natural := 2);
|
||||||
|
Port (
|
||||||
|
rst : in STD_LOGIC;
|
||||||
|
clk : in STD_LOGIC;
|
||||||
|
enable : in STD_LOGIC;
|
||||||
|
u_tag_in : in user_tag_t;
|
||||||
|
u_tag_out : out user_tag_t;
|
||||||
|
phy_ctrl : out phy_ctrl_t;
|
||||||
|
cmd : in sdr_cmd_t;
|
||||||
|
cmd_we : in STD_LOGIC;
|
||||||
|
cmd_ack : out STD_LOGIC;
|
||||||
|
col_addr : in col_addr_t;
|
||||||
|
mode_word : in mode_word_t;
|
||||||
|
sdr_cmd_ctrl : out sdr_cmd_lines_t;
|
||||||
|
sdr_addr : out sdr_addr_t;
|
||||||
|
sdr_ba : out sdr_ba_t
|
||||||
|
);
|
||||||
|
end sdram_cmd;
|
||||||
|
|
||||||
|
architecture behaviour of sdram_cmd is
|
||||||
|
|
||||||
|
signal st_sdr, st_sdr_next : sdr_state_t;
|
||||||
|
|
||||||
|
signal cc_preset : natural range 0 to 10;
|
||||||
|
signal cc_load_en : std_logic;
|
||||||
|
signal cycle_finished : std_logic;
|
||||||
|
|
||||||
|
signal burst_preset : natural range 0 to 3;
|
||||||
|
signal burst_load_en : std_logic;
|
||||||
|
signal burst_finished : std_logic;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
u_tag_out <= u_tag_in;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fsm_sdr_state:
|
||||||
|
process (st_sdr, cmd, cmd_we, cycle_finished, burst_finished, mode_word, enable, col_addr)
|
||||||
|
begin
|
||||||
|
st_sdr_next <= st_sdr;
|
||||||
|
sdr_cmd_ctrl <= COMMAND(SD_NOP);
|
||||||
|
|
||||||
|
cc_load_en <= '0';
|
||||||
|
cc_preset <= TIMING(cmd);
|
||||||
|
burst_load_en <= '0';
|
||||||
|
cmd_ack <= '0';
|
||||||
|
burst_preset <= BL/2-1;
|
||||||
|
phy_ctrl.re <= '0';
|
||||||
|
phy_ctrl.drive_en <= '0';
|
||||||
|
phy_ctrl.we <= '0';
|
||||||
|
phy_ctrl.utag_we <= '0';
|
||||||
|
sdr_addr <= mode_word(sdr_addr_t'left downto sdr_addr_t'right);
|
||||||
|
sdr_ba <= mode_word(mode_word_t'left downto mode_word_t'left-1);
|
||||||
|
|
||||||
|
case st_sdr is
|
||||||
|
when PWR_DOWN =>
|
||||||
|
sdr_cmd_ctrl <= COMMAND(SD_DESELECT);
|
||||||
|
if enable = '1' then
|
||||||
|
st_sdr_next <= IDLE;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when PRECHARGE =>
|
||||||
|
if cycle_finished = '1' then
|
||||||
|
st_sdr_next <= IDLE;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when MODE =>
|
||||||
|
if cycle_finished = '1' then
|
||||||
|
st_sdr_next <= IDLE;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when IDLE =>
|
||||||
|
if cmd_we = '1' then
|
||||||
|
cmd_ack <= '1';
|
||||||
|
cc_load_en <= '1';
|
||||||
|
cc_preset <= TIMING(cmd);
|
||||||
|
sdr_cmd_ctrl <= COMMAND(cmd);
|
||||||
|
case cmd is
|
||||||
|
when SD_PRE =>
|
||||||
|
st_sdr_next <= PRECHARGE;
|
||||||
|
sdr_addr(BIT_PRE_ALL) <= mode_word(BIT_PRE_ALL);
|
||||||
|
when SD_LMR =>
|
||||||
|
st_sdr_next <= MODE;
|
||||||
|
when SD_ACT =>
|
||||||
|
st_sdr_next <= ROW_ACT;
|
||||||
|
when SD_AR =>
|
||||||
|
st_sdr_next <= AUTO_REF;
|
||||||
|
when others => null;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when ROW_ACT =>
|
||||||
|
if cycle_finished = '1' then
|
||||||
|
if cmd_we = '1' then
|
||||||
|
cmd_ack <= '1';
|
||||||
|
burst_load_en <= '1';
|
||||||
|
cc_load_en <= '1';
|
||||||
|
cc_preset <= TIMING(cmd);
|
||||||
|
sdr_cmd_ctrl <= COMMAND(cmd);
|
||||||
|
case cmd is
|
||||||
|
when SD_PRE =>
|
||||||
|
st_sdr_next <= PRECHARGE;
|
||||||
|
when SD_READ =>
|
||||||
|
phy_ctrl.utag_we <= '1';
|
||||||
|
st_sdr_next <= READ;
|
||||||
|
sdr_addr(col_addr_t'range) <= col_addr;
|
||||||
|
when SD_WRITE =>
|
||||||
|
phy_ctrl.utag_we <= '1';
|
||||||
|
phy_ctrl.drive_en <= '1';
|
||||||
|
st_sdr_next <= WRITE;
|
||||||
|
sdr_addr(col_addr_t'range) <= col_addr;
|
||||||
|
when others => null;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when WRITE =>
|
||||||
|
phy_ctrl.drive_en <= '1';
|
||||||
|
phy_ctrl.we <= '1';
|
||||||
|
if burst_finished = '1' then
|
||||||
|
if cmd_we = '1' and cmd = SD_WRITE then
|
||||||
|
sdr_addr(col_addr_t'range) <= col_addr;
|
||||||
|
cmd_ack <= '1';
|
||||||
|
burst_load_en <= '1';
|
||||||
|
sdr_cmd_ctrl <= COMMAND(cmd);
|
||||||
|
phy_ctrl.utag_we <= '1';
|
||||||
|
else
|
||||||
|
phy_ctrl.drive_en <= '0';
|
||||||
|
cc_load_en <= '1';
|
||||||
|
cc_preset <= TIMING(SD_WRITE)+1;
|
||||||
|
st_sdr_next <= ROW_ACT;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when READ =>
|
||||||
|
phy_ctrl.re <= '1';
|
||||||
|
if burst_finished = '1' then
|
||||||
|
if cmd_we = '1' and cmd = SD_READ then
|
||||||
|
sdr_addr(col_addr_t'range) <= col_addr;
|
||||||
|
cmd_ack <= '1';
|
||||||
|
burst_load_en <= '1';
|
||||||
|
sdr_cmd_ctrl <= COMMAND(cmd);
|
||||||
|
phy_ctrl.utag_we <= '1';
|
||||||
|
else
|
||||||
|
cc_load_en <= '1';
|
||||||
|
cc_preset <= TIMING(SD_READ);
|
||||||
|
st_sdr_next <= ROW_ACT;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when WRITE_A => -- not implemented yet
|
||||||
|
cmd_ack <= '1';
|
||||||
|
st_sdr_next <= IDLE;
|
||||||
|
|
||||||
|
when READ_A => -- not implemented yet
|
||||||
|
cmd_ack <= '1';
|
||||||
|
st_sdr_next <= IDLE;
|
||||||
|
|
||||||
|
when BURST_STOP => -- not implemented yet
|
||||||
|
cmd_ack <= '1';
|
||||||
|
st_sdr_next <= IDLE;
|
||||||
|
|
||||||
|
when SELF_REF => -- not implemented yet
|
||||||
|
cmd_ack <= '1';
|
||||||
|
st_sdr_next <= IDLE;
|
||||||
|
|
||||||
|
when PRE_PWR_DOWN => -- not implemented yet
|
||||||
|
cmd_ack <= '1';
|
||||||
|
st_sdr_next <= IDLE;
|
||||||
|
|
||||||
|
when ACT_PWR_DOWN => -- not implemented yet
|
||||||
|
cmd_ack <= '1';
|
||||||
|
st_sdr_next <= IDLE;
|
||||||
|
|
||||||
|
when AUTO_REF =>
|
||||||
|
if cycle_finished = '1' then
|
||||||
|
st_sdr_next <= IDLE;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when others =>
|
||||||
|
st_sdr_next <= IDLE;
|
||||||
|
end case;
|
||||||
|
|
||||||
|
end process;
|
||||||
|
|
||||||
|
fsm_sdr_state_next:
|
||||||
|
process (rst, clk)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
st_sdr <= PWR_DOWN;
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
st_sdr <= st_sdr_next;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
cycle_counter:
|
||||||
|
process (rst, clk)
|
||||||
|
variable cycle_cnt : natural range 0 to 10;
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
cycle_cnt := 0;
|
||||||
|
cycle_finished <= '0';
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
cycle_finished <= '0';
|
||||||
|
if cc_load_en = '1' then
|
||||||
|
cycle_cnt := cc_preset;
|
||||||
|
elsif cycle_cnt /= 0 then
|
||||||
|
cycle_cnt := cycle_cnt - 1;
|
||||||
|
else
|
||||||
|
cycle_finished <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
burst_counter:
|
||||||
|
process (rst, clk)
|
||||||
|
variable burst_cnt : natural range 0 to 3;
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
burst_cnt := 0;
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
burst_finished <= '0';
|
||||||
|
if burst_load_en = '1' then
|
||||||
|
burst_cnt := burst_preset;
|
||||||
|
elsif burst_cnt /= 0 then
|
||||||
|
burst_cnt := burst_cnt - 1;
|
||||||
|
end if;
|
||||||
|
if burst_cnt = 0 then
|
||||||
|
burst_finished <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
end behaviour;
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: SDRAM controller
|
||||||
|
-- This file: User SDRAM component adjustments
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This program is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published by
|
||||||
|
-- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This program 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 General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
library IEEE;
|
||||||
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
|
|
||||||
|
package sdram_config is
|
||||||
|
|
||||||
|
constant DDR_DATA_WIDTH : positive := 16; -- External DDR-SDRAM Module data bus width
|
||||||
|
constant DDR_ADDR_WIDTH : positive := 13; -- number of address lines to DDR-SDRAM Device/Module
|
||||||
|
constant DDR_BANK_WIDTH : positive := 2; -- Number of BANK address lines of external DDR-SDRAM
|
||||||
|
constant DDR_ROW_ADDR_WIDTH : positive := 13; --
|
||||||
|
constant DDR_COL_ADDR_WIDTH : positive := 9; --
|
||||||
|
|
||||||
|
constant LMR_REG_BASE : natural := 0;
|
||||||
|
constant LMR_REG_EXTENDED : natural := 1;
|
||||||
|
constant LMR_OP_NORMAL : natural := 0;
|
||||||
|
constant LMR_OP_RES_DLL : natural := 2;
|
||||||
|
constant LMR_BT_SEQ : natural := 0;
|
||||||
|
constant LMR_BT_ILVD : natural := 1;
|
||||||
|
constant LMR_BL2 : natural := 1;
|
||||||
|
constant LMR_BL4 : natural := 2;
|
||||||
|
constant LMR_BL8 : natural := 3;
|
||||||
|
constant LMR_CL2 : natural := 2;
|
||||||
|
constant LMR_CL3 : natural := 3;
|
||||||
|
constant LMR_CL2_5 : natural := 6;
|
||||||
|
|
||||||
|
-- DDR SDRAM Hardware defined constants
|
||||||
|
constant BIT_AUTO_PRE : positive := 10; -- bit-position in column address for auto precharge (see Data Sheet)
|
||||||
|
constant BIT_PRE_ALL : positive := 10; -- bit-position in column address for precharge all (see Data Sheet)
|
||||||
|
constant ENABLE_PRE_ALL : std_logic := '1';
|
||||||
|
constant ENABLE_AUTO_PRE : std_logic := '0';
|
||||||
|
|
||||||
|
-- DDR-SDR TIMING constants ------------------------------------------------------------------
|
||||||
|
-- After REFRESH_CLOCKS a refresh cycle is necessary, 64ms / 8192 = max every 7.8125 us refesh
|
||||||
|
constant REFRESH_INTERVAL : real := 7.8125; -- us
|
||||||
|
|
||||||
|
-- These values are for your SDRAM part (see datasheet)
|
||||||
|
constant TCAS : positive := 2; -- CAS latency [clocks]
|
||||||
|
constant TRP : positive := 2; -- precharge command period
|
||||||
|
constant TRAS : positive := 4; -- active to precharge delay
|
||||||
|
constant TRFC : positive := 8; -- auto refresh command period
|
||||||
|
constant TMRD : positive := 2; -- load mode register command cylce time
|
||||||
|
constant TRCD : positive := 2; -- active to read or write delay !
|
||||||
|
constant TWR : positive := 2; -- write recovery time
|
||||||
|
|
||||||
|
constant PWR_UP_WAIT : natural := 1; -- µs
|
||||||
|
|
||||||
|
subtype user_tag_t is unsigned(3 downto 0);
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
end sdram_config;
|
||||||
@@ -0,0 +1,487 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: SDRAM controller
|
||||||
|
-- This file: SDRAM main controller and user I/F
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This program is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published by
|
||||||
|
-- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This program 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 General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.numeric_std.ALL;
|
||||||
|
|
||||||
|
use work.sdram_config.all;
|
||||||
|
use work.sdram_types.all;
|
||||||
|
use work.utils_pkg.all;
|
||||||
|
|
||||||
|
entity sdram_ctrl is
|
||||||
|
Generic
|
||||||
|
(
|
||||||
|
f_sysclk : natural := 100E6;
|
||||||
|
BL : natural := 2
|
||||||
|
);
|
||||||
|
Port (
|
||||||
|
rst : in STD_LOGIC;
|
||||||
|
clk : in STD_LOGIC;
|
||||||
|
u_busy : out STD_LOGIC;
|
||||||
|
u_tag_in : in user_tag_t;
|
||||||
|
u_tag_out : out user_tag_t;
|
||||||
|
u_addr : in user_addr_t;
|
||||||
|
u_cmd : in user_cmd_t;
|
||||||
|
u_cmd_we : in STD_LOGIC;
|
||||||
|
col_addr : out col_addr_t;
|
||||||
|
sdr_cmd_busy : in STD_LOGIC;
|
||||||
|
sdr_cmd : out sdr_cmd_t;
|
||||||
|
sdr_cmd_we : out STD_LOGIC;
|
||||||
|
sdr_mode : out mode_word_t;
|
||||||
|
sdr_cke : out STD_LOGIC
|
||||||
|
);
|
||||||
|
end sdram_ctrl;
|
||||||
|
|
||||||
|
architecture behaviour of sdram_ctrl is
|
||||||
|
|
||||||
|
constant LMR_BURST_LEN : natural := NextExpBaseTwo(BL);
|
||||||
|
|
||||||
|
type ctrl_state_t is (RESET, POWER_WAIT, INIT, INIT_WAIT, USER_READY, USER_WRITE_PRE, USER_WRITE_ACT, USER_WRITE, USER_READ_PRE, USER_READ_ACT, USER_READ, REFRESH);
|
||||||
|
signal st_ctrl, st_ctrl_next : ctrl_state_t;
|
||||||
|
|
||||||
|
constant PWR_UP_CLOCK_INTERVAL : natural := PWR_UP_WAIT*(f_sysclk/1E6);
|
||||||
|
signal pwr_up_cnt : natural range 0 to PWR_UP_CLOCK_INTERVAL-1;
|
||||||
|
signal pwr_up_cnt_rst : std_logic;
|
||||||
|
signal pwr_up_finished : std_logic;
|
||||||
|
|
||||||
|
signal cycle_cnt : natural range 0 to 255;
|
||||||
|
signal cc_preset : natural range 0 to 255;
|
||||||
|
signal cc_load_en : std_logic;
|
||||||
|
signal cycle_finished : std_logic;
|
||||||
|
|
||||||
|
signal seq_cnt : natural range 0 to 31;
|
||||||
|
signal seq_rst_en : std_logic;
|
||||||
|
signal seq_cnt_en : std_logic;
|
||||||
|
|
||||||
|
constant REFRESH_CLOCK_INTERVAL : natural := natural(REFRESH_INTERVAL*real(f_sysclk)/1.0E6);
|
||||||
|
signal refresh_cnt : natural range 0 to REFRESH_CLOCK_INTERVAL-1;
|
||||||
|
signal refresh_request : std_logic;
|
||||||
|
signal refresh_cnt_rst : std_logic;
|
||||||
|
|
||||||
|
signal addr_reg_load_en : std_logic;
|
||||||
|
|
||||||
|
signal u_tag_reg : user_tag_t;
|
||||||
|
signal bank_addr_reg : bank_addr_t;
|
||||||
|
signal row_addr_reg : row_addr_t;
|
||||||
|
signal col_addr_reg : col_addr_t;
|
||||||
|
|
||||||
|
signal u_bank_addr : bank_addr_t;
|
||||||
|
signal u_row_addr : row_addr_t;
|
||||||
|
signal u_col_addr : col_addr_t;
|
||||||
|
|
||||||
|
signal act_request : std_logic;
|
||||||
|
signal act_request_set : std_logic;
|
||||||
|
signal act_request_clr : std_logic;
|
||||||
|
|
||||||
|
type init_seq_rom_t is array (0 to 14) of init_seq_t;
|
||||||
|
|
||||||
|
constant init_seq_rom : init_seq_rom_t :=
|
||||||
|
(
|
||||||
|
(
|
||||||
|
cmd => SD_NOP,
|
||||||
|
mode_word => (others => '0'),
|
||||||
|
wait_cycle => 0
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cmd => SD_PRE,
|
||||||
|
mode_word => "000010000000000",
|
||||||
|
wait_cycle => 0
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cmd => SD_NOP,
|
||||||
|
mode_word => (others => '0'),
|
||||||
|
wait_cycle => 0
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cmd => SD_LMR,
|
||||||
|
mode_word => to_unsigned(LMR_REG_EXTENDED, 2) & "0000000000010",
|
||||||
|
wait_cycle => 0
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cmd => SD_NOP,
|
||||||
|
mode_word => (others => '0'),
|
||||||
|
wait_cycle => 0
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cmd => SD_LMR,
|
||||||
|
mode_word => to_unsigned(LMR_REG_BASE, 2) & to_unsigned(LMR_OP_RES_DLL, 6) & to_unsigned(LMR_CL2, 3) & '0' & to_unsigned(LMR_BURST_LEN, 3),
|
||||||
|
wait_cycle => 200
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cmd => SD_NOP,
|
||||||
|
mode_word => (others => '0'),
|
||||||
|
wait_cycle => 0
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cmd => SD_PRE,
|
||||||
|
mode_word => "000010000000000",
|
||||||
|
wait_cycle => 0
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cmd => SD_NOP,
|
||||||
|
mode_word => (others => '0'),
|
||||||
|
wait_cycle => 0
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cmd => SD_AR,
|
||||||
|
mode_word => (others => '0'),
|
||||||
|
wait_cycle => 0
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cmd => SD_NOP,
|
||||||
|
mode_word => (others => '0'),
|
||||||
|
wait_cycle => 0
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cmd => SD_AR,
|
||||||
|
mode_word => (others => '0'),
|
||||||
|
wait_cycle => 0
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cmd => SD_NOP,
|
||||||
|
mode_word => (others => '0'),
|
||||||
|
wait_cycle => 0
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cmd => SD_LMR,
|
||||||
|
mode_word => to_unsigned(LMR_REG_BASE, 2) & to_unsigned(LMR_OP_NORMAL, 6) & to_unsigned(LMR_CL2, 3) & '0' & to_unsigned(LMR_BURST_LEN, 3),
|
||||||
|
wait_cycle => 200
|
||||||
|
),
|
||||||
|
(
|
||||||
|
cmd => SD_NOP,
|
||||||
|
mode_word => (others => '0'),
|
||||||
|
wait_cycle => 0
|
||||||
|
)
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
u_row_addr <= u_addr(user_addr_t'left downto user_addr_t'left-row_addr_t'length+1);
|
||||||
|
u_bank_addr <= u_addr(user_addr_t'left-row_addr_t'length downto user_addr_t'left-row_addr_t'length-bank_addr_t'length+1);
|
||||||
|
u_col_addr <= u_addr(user_addr_t'left-row_addr_t'length-bank_addr_t'length downto 0);
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
fsm_ctrl_state:
|
||||||
|
process (st_ctrl, u_tag_in, u_tag_reg, u_cmd, u_cmd_we, sdr_cmd_busy, pwr_up_finished, seq_cnt, cycle_finished, u_bank_addr, u_row_addr, bank_addr_reg, row_addr_reg, u_col_addr, col_addr_reg, refresh_request, act_request)
|
||||||
|
begin
|
||||||
|
|
||||||
|
u_busy <= '1';
|
||||||
|
pwr_up_cnt_rst <= '0';
|
||||||
|
cc_preset <= init_seq_rom(seq_cnt).wait_cycle;
|
||||||
|
cc_load_en <= '0';
|
||||||
|
sdr_cmd <= init_seq_rom(seq_cnt).cmd;
|
||||||
|
sdr_cmd_we <= '0';
|
||||||
|
sdr_mode <= bank_addr_reg & row_addr_reg;
|
||||||
|
col_addr <= col_addr_reg;
|
||||||
|
sdr_cke <= '1';
|
||||||
|
seq_cnt_en <= '0';
|
||||||
|
seq_rst_en <= '0';
|
||||||
|
addr_reg_load_en <= '0';
|
||||||
|
refresh_cnt_rst <= '0';
|
||||||
|
act_request_set <= '0';
|
||||||
|
act_request_clr <= '0';
|
||||||
|
u_tag_out <= u_tag_reg;
|
||||||
|
|
||||||
|
st_ctrl_next <= st_ctrl;
|
||||||
|
case st_ctrl is
|
||||||
|
when RESET =>
|
||||||
|
sdr_cke <= '0';
|
||||||
|
pwr_up_cnt_rst <= '1';
|
||||||
|
st_ctrl_next <= POWER_WAIT;
|
||||||
|
|
||||||
|
when POWER_WAIT =>
|
||||||
|
sdr_cke <= '0';
|
||||||
|
if pwr_up_finished = '1' then
|
||||||
|
seq_rst_en <= '1';
|
||||||
|
st_ctrl_next <= INIT;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when INIT =>
|
||||||
|
sdr_mode <= init_seq_rom(seq_cnt).mode_word;
|
||||||
|
sdr_cmd <= init_seq_rom(seq_cnt).cmd;
|
||||||
|
cc_preset <= init_seq_rom(seq_cnt).wait_cycle;
|
||||||
|
if seq_cnt = init_seq_rom_t'high then
|
||||||
|
act_request_set <= '1';
|
||||||
|
refresh_cnt_rst <= '1';
|
||||||
|
st_ctrl_next <= USER_READY;
|
||||||
|
elsif sdr_cmd_busy = '0' then
|
||||||
|
cc_load_en <= '1';
|
||||||
|
sdr_cmd_we <= '1';
|
||||||
|
st_ctrl_next <= INIT_WAIT;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when INIT_WAIT =>
|
||||||
|
if sdr_cmd_busy = '0' and cycle_finished = '1' then
|
||||||
|
seq_cnt_en <= '1';
|
||||||
|
st_ctrl_next <= INIT;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when USER_READY =>
|
||||||
|
if sdr_cmd_busy = '0' then
|
||||||
|
if refresh_request = '1' then
|
||||||
|
sdr_mode(BIT_PRE_ALL) <= '1';
|
||||||
|
sdr_cmd_we <= '1';
|
||||||
|
sdr_cmd <= SD_PRE;
|
||||||
|
st_ctrl_next <= REFRESH;
|
||||||
|
else
|
||||||
|
u_busy <= '0';
|
||||||
|
if u_cmd_we = '1' then
|
||||||
|
case u_cmd is
|
||||||
|
when UCMD_NOP =>
|
||||||
|
sdr_cmd <= SD_NOP;
|
||||||
|
when UCMD_LMR =>
|
||||||
|
sdr_cmd <= SD_NOP;
|
||||||
|
when UCMD_WRITE =>
|
||||||
|
col_addr <= u_col_addr;
|
||||||
|
u_tag_out <= u_tag_in;
|
||||||
|
sdr_mode(BIT_AUTO_PRE) <= ENABLE_AUTO_PRE;
|
||||||
|
addr_reg_load_en <= '1';
|
||||||
|
act_request_clr <= '1';
|
||||||
|
sdr_cmd <= SD_WRITE;
|
||||||
|
if (u_row_addr /= row_addr_reg) or act_request = '1' then
|
||||||
|
st_ctrl_next <= USER_WRITE_PRE;
|
||||||
|
elsif (u_bank_addr /= bank_addr_reg) then
|
||||||
|
if ENABLE_PRE_ALL = '1' then
|
||||||
|
st_ctrl_next <= USER_WRITE_ACT;
|
||||||
|
else
|
||||||
|
st_ctrl_next <= USER_WRITE_PRE;
|
||||||
|
end if;
|
||||||
|
elsif sdr_cmd_busy = '0' then
|
||||||
|
sdr_cmd_we <= '1';
|
||||||
|
else
|
||||||
|
st_ctrl_next <= USER_WRITE;
|
||||||
|
end if;
|
||||||
|
when UCMD_READ =>
|
||||||
|
col_addr <= u_col_addr;
|
||||||
|
u_tag_out <= u_tag_in;
|
||||||
|
sdr_mode(BIT_AUTO_PRE) <= ENABLE_AUTO_PRE;
|
||||||
|
addr_reg_load_en <= '1';
|
||||||
|
act_request_clr <= '1';
|
||||||
|
sdr_cmd <= SD_READ;
|
||||||
|
if (u_row_addr /= row_addr_reg) or act_request = '1' then
|
||||||
|
st_ctrl_next <= USER_READ_PRE;
|
||||||
|
elsif (u_bank_addr /= bank_addr_reg) then
|
||||||
|
if ENABLE_PRE_ALL = '1' then
|
||||||
|
st_ctrl_next <= USER_READ_ACT;
|
||||||
|
else
|
||||||
|
st_ctrl_next <= USER_READ_PRE;
|
||||||
|
end if;
|
||||||
|
elsif sdr_cmd_busy = '0' then
|
||||||
|
sdr_cmd_we <= '1';
|
||||||
|
else
|
||||||
|
st_ctrl_next <= USER_READ;
|
||||||
|
end if;
|
||||||
|
when others => null;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when USER_WRITE_PRE =>
|
||||||
|
sdr_cmd <= SD_PRE;
|
||||||
|
sdr_mode(BIT_PRE_ALL) <= ENABLE_PRE_ALL;
|
||||||
|
if sdr_cmd_busy = '0' then
|
||||||
|
sdr_cmd_we <= '1';
|
||||||
|
st_ctrl_next <= USER_WRITE_ACT;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when USER_WRITE_ACT =>
|
||||||
|
sdr_cmd <= SD_ACT;
|
||||||
|
if sdr_cmd_busy = '0' then
|
||||||
|
sdr_cmd_we <= '1';
|
||||||
|
st_ctrl_next <= USER_WRITE;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when USER_WRITE =>
|
||||||
|
sdr_cmd <= SD_WRITE;
|
||||||
|
sdr_mode(BIT_AUTO_PRE) <= ENABLE_AUTO_PRE;
|
||||||
|
if sdr_cmd_busy = '0' then
|
||||||
|
sdr_cmd_we <= '1';
|
||||||
|
st_ctrl_next <= USER_READY;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when USER_READ_PRE =>
|
||||||
|
sdr_cmd <= SD_PRE;
|
||||||
|
sdr_mode(BIT_PRE_ALL) <= ENABLE_PRE_ALL;
|
||||||
|
if sdr_cmd_busy = '0' then
|
||||||
|
sdr_cmd_we <= '1';
|
||||||
|
st_ctrl_next <= USER_READ_ACT;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when USER_READ_ACT =>
|
||||||
|
sdr_cmd <= SD_ACT;
|
||||||
|
if sdr_cmd_busy = '0' then
|
||||||
|
sdr_cmd_we <= '1';
|
||||||
|
st_ctrl_next <= USER_READ;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when USER_READ =>
|
||||||
|
sdr_cmd <= SD_READ;
|
||||||
|
sdr_mode(BIT_AUTO_PRE) <= ENABLE_AUTO_PRE;
|
||||||
|
if sdr_cmd_busy = '0' then
|
||||||
|
sdr_cmd_we <= '1';
|
||||||
|
st_ctrl_next <= USER_READY;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when REFRESH =>
|
||||||
|
sdr_cmd <= SD_AR;
|
||||||
|
if sdr_cmd_busy = '0' then
|
||||||
|
sdr_cmd_we <= '1';
|
||||||
|
st_ctrl_next <= USER_READY;
|
||||||
|
refresh_cnt_rst <= '1';
|
||||||
|
act_request_set <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when others =>
|
||||||
|
st_ctrl_next <= RESET;
|
||||||
|
end case;
|
||||||
|
|
||||||
|
end process;
|
||||||
|
|
||||||
|
fsm_ctrl_state_next:
|
||||||
|
process (rst, clk)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
st_ctrl <= RESET;
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
st_ctrl <= st_ctrl_next;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
act_request_register:
|
||||||
|
process (rst, clk)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
act_request <= '1';
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
if act_request_set = '1' then
|
||||||
|
act_request <= '1';
|
||||||
|
elsif act_request_clr = '1' then
|
||||||
|
act_request <= '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
user_addr_register:
|
||||||
|
process (rst, clk)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
bank_addr_reg <= (others => '0');
|
||||||
|
row_addr_reg <= (others => '0');
|
||||||
|
col_addr_reg <= (others => '0');
|
||||||
|
u_tag_reg <= (others => '0');
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
if addr_reg_load_en = '1' then
|
||||||
|
bank_addr_reg <= u_bank_addr;
|
||||||
|
row_addr_reg <= u_row_addr;
|
||||||
|
col_addr_reg <= u_col_addr;
|
||||||
|
u_tag_reg <= u_tag_in;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
power_up_counter:
|
||||||
|
process (rst, clk)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
pwr_up_cnt <= 0;
|
||||||
|
pwr_up_finished <= '0';
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
pwr_up_finished <= '0';
|
||||||
|
if pwr_up_cnt_rst = '1' then
|
||||||
|
pwr_up_cnt <= PWR_UP_CLOCK_INTERVAL-1;
|
||||||
|
else
|
||||||
|
if pwr_up_cnt /= 0 then
|
||||||
|
pwr_up_cnt <= pwr_up_cnt - 1;
|
||||||
|
else
|
||||||
|
pwr_up_finished <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
refresh_counter:
|
||||||
|
process (rst, clk)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
refresh_cnt <= 0;
|
||||||
|
refresh_request <= '0';
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
refresh_request <= '0';
|
||||||
|
if refresh_cnt_rst = '1' then
|
||||||
|
refresh_cnt <= REFRESH_CLOCK_INTERVAL-1;
|
||||||
|
else
|
||||||
|
if refresh_cnt /= 0 then
|
||||||
|
refresh_cnt <= refresh_cnt - 1;
|
||||||
|
else
|
||||||
|
refresh_request <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
cycle_counter:
|
||||||
|
process (rst, clk)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
cycle_cnt <= 0;
|
||||||
|
cycle_finished <= '0';
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
cycle_finished <= '0';
|
||||||
|
if cc_load_en = '1' then
|
||||||
|
cycle_cnt <= cc_preset;
|
||||||
|
elsif cycle_cnt /= 0 then
|
||||||
|
cycle_cnt <= cycle_cnt - 1;
|
||||||
|
else
|
||||||
|
cycle_finished <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
seq_counter:
|
||||||
|
process (rst, clk)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
seq_cnt <= 0;
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
if seq_rst_en = '1' then
|
||||||
|
seq_cnt <= 0;
|
||||||
|
elsif seq_cnt_en = '1' then
|
||||||
|
if seq_cnt /= init_seq_rom_t'high then
|
||||||
|
seq_cnt <= seq_cnt + 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
end behaviour;
|
||||||
@@ -0,0 +1,283 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||||
|
-- This file: cpu_embedded using cpu_core and rom
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This program is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published by
|
||||||
|
-- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This program 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 General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.numeric_std.ALL;
|
||||||
|
|
||||||
|
use work.fifo_ctrl_pkg.all;
|
||||||
|
use work.sdram_config.all;
|
||||||
|
use work.sdram_types.all;
|
||||||
|
|
||||||
|
entity sdram_ctrl_frontend_wb is
|
||||||
|
Generic
|
||||||
|
(
|
||||||
|
BL : natural := 2;
|
||||||
|
f_sysclk : natural := 100E6;
|
||||||
|
fifo_depth : integer := 4
|
||||||
|
);
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
RST_I : in STD_LOGIC;
|
||||||
|
CLK_I : in STD_LOGIC;
|
||||||
|
CLK270_I : in STD_LOGIC;
|
||||||
|
CLK270VAR_I : in STD_LOGIC;
|
||||||
|
|
||||||
|
CYC_I : in STD_LOGIC;
|
||||||
|
STB_I : in STD_LOGIC;
|
||||||
|
SEL_I : in unsigned(3 downto 0);
|
||||||
|
WE_I : in STD_LOGIC;
|
||||||
|
ACK_O : out STD_LOGIC;
|
||||||
|
MRDY_I : in STD_LOGIC;
|
||||||
|
SRDY_O : out STD_LOGIC;
|
||||||
|
ADDR_I : in unsigned(31 downto 0);
|
||||||
|
DAT_I : in unsigned(31 downto 0);
|
||||||
|
DAT_O : out unsigned(31 downto 0);
|
||||||
|
|
||||||
|
-- SDRAM signals
|
||||||
|
sd_clk_p : out STD_LOGIC;
|
||||||
|
sd_clk_n : out STD_LOGIC;
|
||||||
|
sd_cke : out STD_LOGIC;
|
||||||
|
sd_cs_n : out STD_LOGIC;
|
||||||
|
sd_cas_n : out STD_LOGIC;
|
||||||
|
sd_ras_n : out STD_LOGIC;
|
||||||
|
sd_we_n : out STD_LOGIC;
|
||||||
|
sd_addr : out sdr_addr_t;
|
||||||
|
sd_ba : out sdr_ba_t;
|
||||||
|
sd_dm : out unsigned(DDR_DM_WIDTH-1 downto 0);
|
||||||
|
sd_dqs : inout unsigned(DDR_DQS_WIDTH-1 downto 0);
|
||||||
|
sd_data : inout unsigned(DDR_DATA_WIDTH-1 downto 0)
|
||||||
|
|
||||||
|
);
|
||||||
|
end sdram_ctrl_frontend_wb;
|
||||||
|
|
||||||
|
architecture struct of sdram_ctrl_frontend_wb is
|
||||||
|
|
||||||
|
-- Number of user data words for simulation
|
||||||
|
signal u_addr : user_addr_t;
|
||||||
|
signal u_tag_in : user_tag_t;
|
||||||
|
signal u_tag_rd : user_tag_t;
|
||||||
|
signal u_tag_wr : user_tag_t;
|
||||||
|
signal u_cmd : user_cmd_t;
|
||||||
|
signal u_cmd_we : std_logic;
|
||||||
|
signal u_busy : std_logic;
|
||||||
|
signal u_data_w : unsigned(SDR_DATA_WIDTH-1 downto 0);
|
||||||
|
signal u_dm_wr_in : unsigned(SDR_DM_WIDTH-1 downto 0);
|
||||||
|
signal u_dm_rd_in : unsigned(SDR_DM_WIDTH-1 downto 0);
|
||||||
|
signal u_dm_rd_out : unsigned(SDR_DM_WIDTH-1 downto 0);
|
||||||
|
signal u_data_r : unsigned(SDR_DATA_WIDTH-1 downto 0);
|
||||||
|
signal u_data_vld : std_logic;
|
||||||
|
signal u_req_wr : std_logic;
|
||||||
|
signal rdy : std_logic;
|
||||||
|
|
||||||
|
constant CAT_FIFO_WIDTH : integer := user_cmd_t'length + user_tag_t'length + DDR_ROW_ADDR_WIDTH + DDR_BANK_WIDTH + DDR_COL_ADDR_WIDTH + 4;
|
||||||
|
signal cat_fifo_din : unsigned(CAT_FIFO_WIDTH-1 downto 0);
|
||||||
|
signal cat_fifo_dout : unsigned(CAT_FIFO_WIDTH-1 downto 0);
|
||||||
|
signal cat_fifo_re : std_logic;
|
||||||
|
signal cat_fifo_we : std_logic;
|
||||||
|
signal cat_fifo_full : std_logic;
|
||||||
|
signal cat_fifo_empty : std_logic;
|
||||||
|
-- signal cat_fifo_almost_full : std_logic;
|
||||||
|
-- signal cat_fifo_almost_empty : std_logic;
|
||||||
|
|
||||||
|
signal write_fifo_din : unsigned(35 downto 0);
|
||||||
|
signal write_fifo_dout : unsigned(35 downto 0);
|
||||||
|
signal write_fifo_re : std_logic;
|
||||||
|
signal write_fifo_we : std_logic;
|
||||||
|
signal write_fifo_full : std_logic;
|
||||||
|
signal write_fifo_empty : std_logic;
|
||||||
|
-- signal write_fifo_almost_full : std_logic;
|
||||||
|
-- signal write_fifo_almost_empty : std_logic;
|
||||||
|
|
||||||
|
signal read_fifo_din : unsigned(35 downto 0);
|
||||||
|
signal read_fifo_dout : unsigned(35 downto 0);
|
||||||
|
signal read_fifo_re : std_logic;
|
||||||
|
signal read_fifo_we : std_logic;
|
||||||
|
signal read_fifo_full : std_logic;
|
||||||
|
signal read_fifo_empty : std_logic;
|
||||||
|
-- signal read_fifo_almost_full : std_logic;
|
||||||
|
-- signal read_fifo_almost_empty : std_logic;
|
||||||
|
|
||||||
|
alias cmd_fifo_in is cat_fifo_din(CAT_FIFO_WIDTH-1 downto CAT_FIFO_WIDTH-user_cmd_t'length);
|
||||||
|
alias tag_fifo_in is cat_fifo_din(CAT_FIFO_WIDTH-user_cmd_t'length-1 downto CAT_FIFO_WIDTH-user_cmd_t'length-user_tag_t'length);
|
||||||
|
alias addr_fifo_in is cat_fifo_din(CAT_FIFO_WIDTH-user_cmd_t'length-user_tag_t'length-1 downto 4);
|
||||||
|
alias dm_rd_fifo_in is cat_fifo_din(4-1 downto 0);
|
||||||
|
alias cmd_fifo_out is cat_fifo_dout(CAT_FIFO_WIDTH-1 downto CAT_FIFO_WIDTH-user_cmd_t'length);
|
||||||
|
alias tag_fifo_out is cat_fifo_dout(CAT_FIFO_WIDTH-user_cmd_t'length-1 downto CAT_FIFO_WIDTH-user_cmd_t'length-user_tag_t'length);
|
||||||
|
alias addr_fifo_out is cat_fifo_dout(CAT_FIFO_WIDTH-user_cmd_t'length-user_tag_t'length-1 downto 4);
|
||||||
|
alias dm_rd_fifo_out is cat_fifo_dout(4-1 downto 0);
|
||||||
|
|
||||||
|
alias write_fifo_dm_in is write_fifo_din(write_fifo_din'length-1 downto write_fifo_din'length-4);
|
||||||
|
alias write_fifo_data_in is write_fifo_din(write_fifo_din'length-4-1 downto 0);
|
||||||
|
alias write_fifo_dm_out is write_fifo_dout(write_fifo_dout'length-1 downto write_fifo_dout'length-4);
|
||||||
|
alias write_fifo_data_out is write_fifo_dout(write_fifo_dout'length-4-1 downto 0);
|
||||||
|
|
||||||
|
alias read_fifo_dm_in is read_fifo_din(read_fifo_din'length-1 downto read_fifo_din'length-4);
|
||||||
|
alias read_fifo_data_in is read_fifo_din(read_fifo_din'length-4-1 downto 0);
|
||||||
|
alias read_fifo_dm_out is read_fifo_dout(read_fifo_dout'length-1 downto read_fifo_dout'length-4);
|
||||||
|
alias read_fifo_data_out is read_fifo_dout(read_fifo_dout'length-4-1 downto 0);
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
-- Instantiate synchronous FIFO
|
||||||
|
inst_cat_fifo: entity work.fifo_sync
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
addr_width => fifo_depth,
|
||||||
|
data_width => CAT_FIFO_WIDTH
|
||||||
|
)
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
rst => RST_I,
|
||||||
|
clk => CLK_I,
|
||||||
|
we => cat_fifo_we,
|
||||||
|
re => cat_fifo_re,
|
||||||
|
fifo_full => cat_fifo_full,
|
||||||
|
fifo_empty => cat_fifo_empty,
|
||||||
|
fifo_afull => open,
|
||||||
|
fifo_aempty => open,
|
||||||
|
data_w => cat_fifo_din,
|
||||||
|
data_r => cat_fifo_dout
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Instantiate synchronous FIFO
|
||||||
|
inst_write_fifo: entity work.fifo_sync
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
addr_width => fifo_depth,
|
||||||
|
data_width => 36
|
||||||
|
)
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
rst => RST_I,
|
||||||
|
clk => CLK_I,
|
||||||
|
we => write_fifo_we,
|
||||||
|
re => write_fifo_re,
|
||||||
|
fifo_full => write_fifo_full,
|
||||||
|
fifo_empty => write_fifo_empty,
|
||||||
|
fifo_afull => open,
|
||||||
|
fifo_aempty => open,
|
||||||
|
data_w => write_fifo_din,
|
||||||
|
data_r => write_fifo_dout
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Instantiate synchronous FIFO
|
||||||
|
inst_read_fifo: entity work.fifo_sync
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
addr_width => fifo_depth,
|
||||||
|
data_width => 36
|
||||||
|
)
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
rst => RST_I,
|
||||||
|
clk => CLK_I,
|
||||||
|
we => read_fifo_we,
|
||||||
|
re => read_fifo_re,
|
||||||
|
fifo_full => read_fifo_full,
|
||||||
|
fifo_empty => read_fifo_empty,
|
||||||
|
fifo_afull => open,
|
||||||
|
fifo_aempty => open,
|
||||||
|
data_w => read_fifo_din,
|
||||||
|
data_r => read_fifo_dout
|
||||||
|
);
|
||||||
|
|
||||||
|
-- DDR SDRAM Controller Core
|
||||||
|
inst_sdram_ctrl : entity work.sdram_ctrl_top
|
||||||
|
Generic map
|
||||||
|
(
|
||||||
|
BL => BL,
|
||||||
|
f_sysclk => f_sysclk
|
||||||
|
)
|
||||||
|
Port map
|
||||||
|
(
|
||||||
|
|
||||||
|
sys_rst_in => RST_I,
|
||||||
|
sys_clk0_in => CLK_I,
|
||||||
|
|
||||||
|
sys_clk270_in => CLK270_I,
|
||||||
|
capture_clk270_in => CLK270VAR_I,
|
||||||
|
|
||||||
|
-- User interface
|
||||||
|
u_data_vld => u_data_vld,
|
||||||
|
u_data_req_w => u_req_wr,
|
||||||
|
u_data_req_r => open,
|
||||||
|
u_tag_in => u_tag_in,
|
||||||
|
u_tag_rd => u_tag_rd,
|
||||||
|
u_tag_wr => u_tag_wr,
|
||||||
|
u_busy => u_busy,
|
||||||
|
u_addr => u_addr,
|
||||||
|
u_cmd => u_cmd,
|
||||||
|
u_cmd_we => u_cmd_we,
|
||||||
|
u_data_wr => u_data_w,
|
||||||
|
u_data_rd => u_data_r,
|
||||||
|
u_dm_wr_in => u_dm_wr_in,
|
||||||
|
u_dm_rd_in => u_dm_rd_in,
|
||||||
|
u_dm_rd_out => u_dm_rd_out,
|
||||||
|
|
||||||
|
-- SDRAM signals
|
||||||
|
sd_clk_p => sd_clk_p,
|
||||||
|
sd_clk_n => sd_clk_n,
|
||||||
|
sd_cke => sd_cke,
|
||||||
|
sd_cs_n => sd_cs_n,
|
||||||
|
sd_cas_n => sd_cas_n,
|
||||||
|
sd_ras_n => sd_ras_n,
|
||||||
|
sd_we_n => sd_we_n,
|
||||||
|
sd_addr => sd_addr,
|
||||||
|
sd_ba => sd_ba,
|
||||||
|
sd_dm => sd_dm,
|
||||||
|
sd_dqs => sd_dqs,
|
||||||
|
sd_data => sd_data
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
SRDY_O <= rdy;
|
||||||
|
ACK_O <= not (read_fifo_empty);
|
||||||
|
DAT_O <= read_fifo_data_out;
|
||||||
|
rdy <= not (cat_fifo_full or write_fifo_full or read_fifo_full) and CYC_I;
|
||||||
|
write_fifo_we <= STB_I and WE_I and rdy;
|
||||||
|
write_fifo_data_in <= DAT_I;
|
||||||
|
write_fifo_dm_in <= not SEL_I;
|
||||||
|
cat_fifo_we <= STB_I and rdy;
|
||||||
|
cmd_fifo_in <= UCMD_WRITE when WE_I = '1' else UCMD_READ;
|
||||||
|
addr_fifo_in <= ADDR_I(24 downto 2) & "0";
|
||||||
|
dm_rd_fifo_in <= not SEL_I;
|
||||||
|
tag_fifo_in <= (others=>'0');
|
||||||
|
|
||||||
|
u_cmd_we <= (not cat_fifo_empty) and (not u_busy);
|
||||||
|
u_cmd <= cmd_fifo_out;
|
||||||
|
u_addr <= addr_fifo_out;
|
||||||
|
u_dm_rd_in <= dm_rd_fifo_out & dm_rd_fifo_out;
|
||||||
|
u_dm_wr_in <= write_fifo_dm_out & write_fifo_dm_out;
|
||||||
|
u_tag_in <= tag_fifo_out;
|
||||||
|
|
||||||
|
write_fifo_re <= u_req_wr and (not write_fifo_empty);
|
||||||
|
cat_fifo_re <= u_cmd_we;
|
||||||
|
u_data_w <= write_fifo_data_out & write_fifo_data_out;
|
||||||
|
read_fifo_re <= (not read_fifo_empty) and MRDY_I;
|
||||||
|
read_fifo_we <= u_data_vld;
|
||||||
|
read_fifo_data_in <= u_data_r(31 downto 0);
|
||||||
|
read_fifo_dm_in <= u_dm_rd_out(3 downto 0);
|
||||||
|
|
||||||
|
end architecture struct;
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: SDRAM controller
|
||||||
|
-- This file: Top-level put all together
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This program is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published by
|
||||||
|
-- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This program 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 General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.numeric_std.ALL;
|
||||||
|
|
||||||
|
use work.sdram_config.all;
|
||||||
|
use work.sdram_types.all;
|
||||||
|
|
||||||
|
entity sdram_ctrl_top is
|
||||||
|
Generic
|
||||||
|
(
|
||||||
|
BL : natural := 2;
|
||||||
|
f_sysclk : natural := 100E6
|
||||||
|
);
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
sys_rst_in : in STD_LOGIC;
|
||||||
|
sys_clk0_in : in STD_LOGIC;
|
||||||
|
sys_clk270_in : in STD_LOGIC;
|
||||||
|
capture_clk270_in : in STD_LOGIC;
|
||||||
|
|
||||||
|
-- User interface
|
||||||
|
u_data_vld : out STD_LOGIC;
|
||||||
|
u_data_req_w : out STD_LOGIC;
|
||||||
|
u_data_req_r : out STD_LOGIC;
|
||||||
|
u_busy : out STD_LOGIC;
|
||||||
|
u_tag_in : in user_tag_t;
|
||||||
|
u_tag_rd : out user_tag_t;
|
||||||
|
u_tag_wr : out user_tag_t;
|
||||||
|
u_addr : in user_addr_t;
|
||||||
|
u_cmd : in user_cmd_t;
|
||||||
|
u_cmd_we : in STD_LOGIC;
|
||||||
|
u_data_wr : in unsigned(SDR_DATA_WIDTH-1 downto 0);
|
||||||
|
u_dm_wr_in : in unsigned(SDR_DM_WIDTH-1 downto 0);
|
||||||
|
u_dm_rd_in : in unsigned(SDR_DM_WIDTH-1 downto 0);
|
||||||
|
u_dm_rd_out : out unsigned(SDR_DM_WIDTH-1 downto 0);
|
||||||
|
u_data_rd : out unsigned(SDR_DATA_WIDTH-1 downto 0);
|
||||||
|
|
||||||
|
-- SDRAM signals
|
||||||
|
sd_clk_p : out STD_LOGIC;
|
||||||
|
sd_clk_n : out STD_LOGIC;
|
||||||
|
sd_cke : out STD_LOGIC;
|
||||||
|
sd_cs_n : out STD_LOGIC;
|
||||||
|
sd_cas_n : out STD_LOGIC;
|
||||||
|
sd_ras_n : out STD_LOGIC;
|
||||||
|
sd_we_n : out STD_LOGIC;
|
||||||
|
sd_addr : out sdr_addr_t;
|
||||||
|
sd_ba : out sdr_ba_t;
|
||||||
|
sd_dm : out unsigned(DDR_DM_WIDTH-1 downto 0);
|
||||||
|
sd_dqs : inout unsigned(DDR_DQS_WIDTH-1 downto 0);
|
||||||
|
sd_data : inout unsigned(DDR_DATA_WIDTH-1 downto 0)
|
||||||
|
|
||||||
|
);
|
||||||
|
end sdram_ctrl_top;
|
||||||
|
|
||||||
|
architecture rtl of sdram_ctrl_top is
|
||||||
|
|
||||||
|
|
||||||
|
signal phy_ctrl : phy_ctrl_t;
|
||||||
|
|
||||||
|
signal u_tag : user_tag_t;
|
||||||
|
signal sd_cmd_in : sdr_cmd_t;
|
||||||
|
signal sd_cmd : sdr_cmd_t;
|
||||||
|
signal sd_cmd_we : std_logic;
|
||||||
|
signal cmd_ctrl : sdr_cmd_lines_t;
|
||||||
|
signal cke : std_logic;
|
||||||
|
signal ba : unsigned(DDR_BANK_WIDTH-1 downto 0);
|
||||||
|
signal addr : unsigned(DDR_ADDR_WIDTH-1 downto 0);
|
||||||
|
|
||||||
|
-- Clock generator
|
||||||
|
|
||||||
|
signal ctrl_rst : std_logic;
|
||||||
|
signal part_ctrl : part_ctrl_t;
|
||||||
|
|
||||||
|
-- SD command FIFO
|
||||||
|
|
||||||
|
constant CMD_FIFO_ADDR_WIDTH : positive := 2;
|
||||||
|
constant CMD_FIFO_DATA_WIDTH : positive := user_tag_t'length + 4 + mode_word_t'length + col_addr_t'length;
|
||||||
|
signal cmd_fifo_din : unsigned(CMD_FIFO_DATA_WIDTH-1 downto 0);
|
||||||
|
signal cmd_fifo_dout : unsigned(CMD_FIFO_DATA_WIDTH-1 downto 0);
|
||||||
|
signal cmd_fifo_re : std_logic;
|
||||||
|
signal cmd_fifo_we : std_logic;
|
||||||
|
signal cmd_fifo_full : std_logic;
|
||||||
|
signal cmd_fifo_empty : std_logic;
|
||||||
|
|
||||||
|
alias tag_fifo_in is cmd_fifo_din(CMD_FIFO_DATA_WIDTH-1 downto CMD_FIFO_DATA_WIDTH-user_tag_t'length);
|
||||||
|
alias cmd_fifo_in is cmd_fifo_din(CMD_FIFO_DATA_WIDTH-user_tag_t'length-1 downto CMD_FIFO_DATA_WIDTH-user_tag_t'length-4);
|
||||||
|
alias mode_fifo_in is cmd_fifo_din(CMD_FIFO_DATA_WIDTH-user_tag_t'length-4-1 downto CMD_FIFO_DATA_WIDTH-user_tag_t'length-4-mode_word_t'length);
|
||||||
|
alias col_fifo_in is cmd_fifo_din(CMD_FIFO_DATA_WIDTH-user_tag_t'length-4-mode_word_t'length-1 downto 0);
|
||||||
|
|
||||||
|
alias tag_fifo_out is cmd_fifo_dout(CMD_FIFO_DATA_WIDTH-1 downto CMD_FIFO_DATA_WIDTH-user_tag_t'length);
|
||||||
|
alias cmd_fifo_out is cmd_fifo_dout(CMD_FIFO_DATA_WIDTH-user_tag_t'length-1 downto CMD_FIFO_DATA_WIDTH-user_tag_t'length-4);
|
||||||
|
alias mode_fifo_out is cmd_fifo_dout(CMD_FIFO_DATA_WIDTH-user_tag_t'length-4-1 downto CMD_FIFO_DATA_WIDTH-user_tag_t'length-4-mode_word_t'length);
|
||||||
|
alias col_fifo_out is cmd_fifo_dout(CMD_FIFO_DATA_WIDTH-user_tag_t'length-4-mode_word_t'length-1 downto 0);
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
---------------------------------
|
||||||
|
part_ctrl.cmd <= cmd_ctrl;
|
||||||
|
part_ctrl.ba <= ba;
|
||||||
|
part_ctrl.addr <= addr;
|
||||||
|
part_ctrl.cke <= cke;
|
||||||
|
|
||||||
|
---------------------------------
|
||||||
|
sd_cmd_we <= not cmd_fifo_empty;
|
||||||
|
cmd_fifo_in <= to_unsigned(sd_cmd_in, 4);
|
||||||
|
sd_cmd <= sdr_cmd_t(to_integer(cmd_fifo_out));
|
||||||
|
|
||||||
|
---------------------------------
|
||||||
|
inst_reset: entity work.reset
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
clk => sys_clk0_in,
|
||||||
|
rst_in => sys_rst_in,
|
||||||
|
rst_out => ctrl_rst
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Main controller
|
||||||
|
inst_sdram_ctrl : entity work.sdram_ctrl
|
||||||
|
Generic map
|
||||||
|
(
|
||||||
|
f_sysclk => 100E6,
|
||||||
|
BL => BL
|
||||||
|
)
|
||||||
|
Port map
|
||||||
|
(
|
||||||
|
rst => ctrl_rst,
|
||||||
|
clk => sys_clk0_in,
|
||||||
|
u_busy => u_busy,
|
||||||
|
u_tag_in => u_tag_in,
|
||||||
|
u_tag_out => tag_fifo_in,
|
||||||
|
u_cmd => u_cmd,
|
||||||
|
u_cmd_we => u_cmd_we,
|
||||||
|
u_addr => u_addr,
|
||||||
|
sdr_cmd_busy => cmd_fifo_full,
|
||||||
|
sdr_cmd => sd_cmd_in,
|
||||||
|
sdr_cmd_we => cmd_fifo_we,
|
||||||
|
col_addr => col_fifo_in,
|
||||||
|
sdr_mode => mode_fifo_in,
|
||||||
|
sdr_cke => cke
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Instantiate synchronous FIFO
|
||||||
|
inst_sd_cmd_fifo: entity work.fifo_sync
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
addr_width => CMD_FIFO_ADDR_WIDTH,
|
||||||
|
data_width => CMD_FIFO_DATA_WIDTH,
|
||||||
|
almost_full_thresh => 2**(CMD_FIFO_ADDR_WIDTH-1),
|
||||||
|
almost_empty_thresh => 2**(CMD_FIFO_ADDR_WIDTH-1)
|
||||||
|
)
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
rst => ctrl_rst,
|
||||||
|
clk => sys_clk0_in,
|
||||||
|
we => cmd_fifo_we,
|
||||||
|
re => cmd_fifo_re,
|
||||||
|
fifo_full => cmd_fifo_full,
|
||||||
|
fifo_empty => cmd_fifo_empty,
|
||||||
|
fifo_afull => open,
|
||||||
|
fifo_aempty => open,
|
||||||
|
data_w => cmd_fifo_din,
|
||||||
|
data_r => cmd_fifo_dout
|
||||||
|
);
|
||||||
|
|
||||||
|
-- DDR SDRAM command fsm
|
||||||
|
inst_sdram_cmd : entity work.sdram_cmd
|
||||||
|
Generic map
|
||||||
|
(
|
||||||
|
BL => BL
|
||||||
|
)
|
||||||
|
Port map
|
||||||
|
(
|
||||||
|
rst => ctrl_rst,
|
||||||
|
clk => sys_clk0_in,
|
||||||
|
u_tag_in => tag_fifo_out,
|
||||||
|
u_tag_out => u_tag,
|
||||||
|
phy_ctrl => phy_ctrl,
|
||||||
|
enable => cke,
|
||||||
|
cmd => sd_cmd,
|
||||||
|
cmd_we => sd_cmd_we,
|
||||||
|
cmd_ack => cmd_fifo_re,
|
||||||
|
sdr_cmd_ctrl => cmd_ctrl,
|
||||||
|
col_addr => col_fifo_out,
|
||||||
|
mode_word => mode_fifo_out,
|
||||||
|
sdr_ba => ba,
|
||||||
|
sdr_addr => addr
|
||||||
|
);
|
||||||
|
|
||||||
|
-- DDR phy
|
||||||
|
inst_ddr_phy : entity work.ddr_phy
|
||||||
|
Port map
|
||||||
|
(
|
||||||
|
sys_rst => ctrl_rst,
|
||||||
|
sys_clk0 => sys_clk0_in,
|
||||||
|
sys_clk270 => sys_clk270_in,
|
||||||
|
u_tag_in => u_tag,
|
||||||
|
u_tag_rd => u_tag_rd,
|
||||||
|
u_tag_wr => u_tag_wr,
|
||||||
|
read_clk => capture_clk270_in,
|
||||||
|
phy_ctrl => phy_ctrl,
|
||||||
|
part_ctrl => part_ctrl,
|
||||||
|
sdr_data_req_w => u_data_req_w,
|
||||||
|
sdr_data_req_r => u_data_req_r,
|
||||||
|
sdr_data_w => u_data_wr,
|
||||||
|
sdr_dm_wr_in => u_dm_wr_in,
|
||||||
|
sdr_dm_rd_in => u_dm_rd_in,
|
||||||
|
sdr_dm_rd_out => u_dm_rd_out,
|
||||||
|
sdr_data_r => u_data_rd,
|
||||||
|
sdr_data_vld => u_data_vld,
|
||||||
|
part_clk_p => sd_clk_p,
|
||||||
|
part_clk_n => sd_clk_n,
|
||||||
|
part_addr => sd_addr,
|
||||||
|
part_ba => sd_ba,
|
||||||
|
part_dm => sd_dm,
|
||||||
|
part_dqs => sd_dqs,
|
||||||
|
part_data => sd_data,
|
||||||
|
part_cs_n => sd_cs_n,
|
||||||
|
part_we_n => sd_we_n,
|
||||||
|
part_cas_n => sd_cas_n,
|
||||||
|
part_ras_n => sd_ras_n,
|
||||||
|
part_cke => sd_cke
|
||||||
|
);
|
||||||
|
|
||||||
|
end architecture rtl;
|
||||||
|
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: SDRAM controller
|
||||||
|
-- This file: Type definitions
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This program is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published by
|
||||||
|
-- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This program 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 General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
library IEEE;
|
||||||
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
|
|
||||||
|
use work.sdram_config.all;
|
||||||
|
|
||||||
|
package sdram_types is
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------
|
||||||
|
-- Table of Timing Parameters as a function of operation
|
||||||
|
|
||||||
|
-- Derived constants from sdram_config
|
||||||
|
|
||||||
|
constant DDR_DQS_WIDTH : positive := DDR_DATA_WIDTH / 8; -- Number of data strobe lines
|
||||||
|
constant DDR_DM_WIDTH : positive := DDR_DATA_WIDTH / 8; -- Number of Data Mask Lines
|
||||||
|
constant SDR_DATA_WIDTH : positive := 2*DDR_DATA_WIDTH; --
|
||||||
|
constant SDR_DM_WIDTH : positive := 2*DDR_DM_WIDTH; --
|
||||||
|
|
||||||
|
subtype user_cmd_t is unsigned(1 downto 0);
|
||||||
|
constant UCMD_NOP : user_cmd_t := "00";
|
||||||
|
constant UCMD_READ : user_cmd_t := "01";
|
||||||
|
constant UCMD_WRITE : user_cmd_t := "10";
|
||||||
|
constant UCMD_LMR : user_cmd_t := "11";
|
||||||
|
|
||||||
|
subtype sdr_cmd_t is natural range 0 to 9;
|
||||||
|
constant SD_DESELECT : sdr_cmd_t := 0;
|
||||||
|
constant SD_NOP : sdr_cmd_t := 1;
|
||||||
|
constant SD_LMR : sdr_cmd_t := 2;
|
||||||
|
constant SD_ACT : sdr_cmd_t := 3;
|
||||||
|
constant SD_READ : sdr_cmd_t := 4;
|
||||||
|
constant SD_WRITE : sdr_cmd_t := 5;
|
||||||
|
constant SD_PRE : sdr_cmd_t := 6;
|
||||||
|
constant SD_BST : sdr_cmd_t := 7;
|
||||||
|
constant SD_AR : sdr_cmd_t := 8;
|
||||||
|
constant SD_SR : sdr_cmd_t := 9;
|
||||||
|
|
||||||
|
type sdr_state_t is (PWR_DOWN, PRECHARGE, MODE, IDLE, ROW_ACT, WRITE, WRITE_A, READ, READ_A, BURST_STOP, SELF_REF, AUTO_REF, PRE_PWR_DOWN, ACT_PWR_DOWN);
|
||||||
|
subtype user_addr_t is unsigned(DDR_BANK_WIDTH+DDR_ROW_ADDR_WIDTH+DDR_COL_ADDR_WIDTH-1 downto 0);
|
||||||
|
subtype sdr_addr_t is unsigned(DDR_ADDR_WIDTH-1 downto 0);
|
||||||
|
subtype sdr_ba_t is unsigned(DDR_BANK_WIDTH-1 downto 0);
|
||||||
|
subtype mode_word_t is unsigned(DDR_ADDR_WIDTH+DDR_BANK_WIDTH-1 downto 0);
|
||||||
|
|
||||||
|
subtype bank_addr_t is unsigned(DDR_BANK_WIDTH-1 downto 0);
|
||||||
|
subtype row_addr_t is unsigned(DDR_ADDR_WIDTH-1 downto 0);
|
||||||
|
subtype col_addr_t is unsigned(8 downto 0);
|
||||||
|
|
||||||
|
subtype cycle_cnt_t is natural range 0 to 10;
|
||||||
|
|
||||||
|
type phy_ctrl_t is
|
||||||
|
record
|
||||||
|
drive_en : std_logic;
|
||||||
|
re : std_logic;
|
||||||
|
we : std_logic;
|
||||||
|
utag_we : std_logic;
|
||||||
|
end record phy_ctrl_t;
|
||||||
|
|
||||||
|
type sdr_cmd_lines_t is
|
||||||
|
record
|
||||||
|
cs_n : std_logic;
|
||||||
|
ras_n : std_logic;
|
||||||
|
cas_n : std_logic;
|
||||||
|
we_n : std_logic;
|
||||||
|
end record sdr_cmd_lines_t;
|
||||||
|
|
||||||
|
type part_ctrl_t is
|
||||||
|
record
|
||||||
|
cmd : sdr_cmd_lines_t;
|
||||||
|
ba : unsigned(DDR_BANK_WIDTH-1 downto 0);
|
||||||
|
addr : unsigned(DDR_ADDR_WIDTH-1 downto 0);
|
||||||
|
cke : std_logic;
|
||||||
|
end record part_ctrl_t;
|
||||||
|
|
||||||
|
type part_cmd_array_t is array (sdr_cmd_t) of sdr_cmd_lines_t;
|
||||||
|
constant COMMAND : part_cmd_array_t :=
|
||||||
|
-- command cs_n ras_qn cas_qn we_qn
|
||||||
|
( SD_DESELECT => ( '1', '1', '1', '1'),
|
||||||
|
SD_NOP => ( '0', '1', '1', '1'),
|
||||||
|
SD_LMR => ( '0', '0', '0', '0'),
|
||||||
|
SD_ACT => ( '0', '0', '1', '1'),
|
||||||
|
SD_READ => ( '0', '1', '0', '1'),
|
||||||
|
SD_WRITE => ( '0', '1', '0', '0'),
|
||||||
|
SD_PRE => ( '0', '0', '1', '0'),
|
||||||
|
SD_BST => ( '0', '1', '1', '0'),
|
||||||
|
SD_AR => ( '0', '0', '0', '1'),
|
||||||
|
SD_SR => ( '0', '0', '0', '1')
|
||||||
|
);
|
||||||
|
|
||||||
|
type part_timing_array_t is array (sdr_cmd_t) of cycle_cnt_t;
|
||||||
|
constant TIMING : part_timing_array_t :=
|
||||||
|
-- command cycle_cnt
|
||||||
|
( SD_DESELECT => ( 0 ),
|
||||||
|
SD_NOP => ( 0 ),
|
||||||
|
SD_LMR => ( TMRD-1 ),
|
||||||
|
SD_ACT => ( TRCD-1 ),
|
||||||
|
SD_READ => ( TCAS-1 ),
|
||||||
|
SD_WRITE => ( TWR-1 ),
|
||||||
|
SD_PRE => ( TRP-1 ),
|
||||||
|
SD_BST => ( 0 ),
|
||||||
|
SD_AR => ( TRFC-1 ),
|
||||||
|
SD_SR => ( TRFC-1 )
|
||||||
|
);
|
||||||
|
|
||||||
|
type init_seq_t is
|
||||||
|
record
|
||||||
|
cmd : sdr_cmd_t;
|
||||||
|
mode_word : mode_word_t;
|
||||||
|
wait_cycle : natural;
|
||||||
|
end record init_seq_t;
|
||||||
|
|
||||||
|
end sdram_types;
|
||||||
@@ -0,0 +1,505 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||||
|
-- This file: cpu_embedded using cpu_core and rom
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This program is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published by
|
||||||
|
-- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This program 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 General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.numeric_std.ALL;
|
||||||
|
|
||||||
|
use work.fifo_ctrl_pkg.all;
|
||||||
|
use work.sdram_config.all;
|
||||||
|
use work.sdram_types.all;
|
||||||
|
|
||||||
|
entity tb_sdram_ctrl_frontend_wb is
|
||||||
|
end;
|
||||||
|
|
||||||
|
architecture struct of tb_sdram_ctrl_frontend_wb is
|
||||||
|
|
||||||
|
-- Number of user data words for simulation
|
||||||
|
constant CLK_PERIOD : time := 10 ns;
|
||||||
|
constant BURST_LEN : natural := 2;
|
||||||
|
|
||||||
|
signal rst : std_logic := '1';
|
||||||
|
signal clk : std_logic := '1';
|
||||||
|
signal locked : std_logic;
|
||||||
|
signal error : std_logic;
|
||||||
|
signal clk_out : std_logic;
|
||||||
|
signal clk_fb : std_logic;
|
||||||
|
signal part_clk_p : std_logic;
|
||||||
|
signal part_clk_n : std_logic;
|
||||||
|
signal part_cke : std_logic;
|
||||||
|
signal part_cs_n : std_logic;
|
||||||
|
signal part_we_n : std_logic;
|
||||||
|
signal part_ras_n : std_logic;
|
||||||
|
signal part_cas_n : std_logic;
|
||||||
|
signal part_ba : unsigned(DDR_BANK_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
signal part_dm : unsigned(DDR_DM_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
signal part_dqs : unsigned(DDR_DQS_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
signal part_addr : unsigned(DDR_ADDR_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
signal part_data : unsigned(DDR_DATA_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
|
||||||
|
signal CLK_O : std_logic;
|
||||||
|
signal CLK270_O : std_logic;
|
||||||
|
signal CLK270VAR_O : std_logic;
|
||||||
|
signal RST_O : std_logic;
|
||||||
|
signal CYC_O : std_logic := '0';
|
||||||
|
signal STB_O : std_logic := '0';
|
||||||
|
signal WE_O : std_logic := '0';
|
||||||
|
signal SEL_O : unsigned(3 downto 0) := (others => '1');
|
||||||
|
signal ACK_I : std_logic;
|
||||||
|
signal MRDY_O : std_logic := '1';
|
||||||
|
signal SRDY_I : std_logic;
|
||||||
|
signal ADDR_O : unsigned(31 downto 0) := (others => '-');
|
||||||
|
signal DAT_I : unsigned(31 downto 0);
|
||||||
|
signal DAT_O : unsigned(31 downto 0) := (others => '-');
|
||||||
|
|
||||||
|
signal dout_rst : std_logic := '0';
|
||||||
|
signal dout_reg : unsigned(31 downto 0);
|
||||||
|
signal dout_cnt : natural range 0 to 255;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
inst_clockgen : entity work.clockgen
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
sys1_phaseshift => 0,
|
||||||
|
frequency_hz => 100E6
|
||||||
|
)
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
-- Clocks and Reset
|
||||||
|
rst => rst, -- external async reset, low active
|
||||||
|
clk_in => clk, -- system clock (e.g. 100MHz), from board
|
||||||
|
clk_fb_in => clk_fb, -- feedback clock
|
||||||
|
sys1_clk0_out => open, -- System clock #1 (e.g. clock for DDR-SDRAM data capture), dcm#1 output 0°
|
||||||
|
sys1_clk270_out => CLK270VAR_O, -- System clock #1 (e.g. clock for DDR-SDRAM data capture), dcm#1 output 270°
|
||||||
|
sys0_clk0_out => CLK_O, -- System clock #0, dcm#0 output 0°
|
||||||
|
sys0_clk270_out => CLK270_O, -- System clock #0, dcm#0 output 270°
|
||||||
|
locked_out => locked, -- DCM locked status
|
||||||
|
error_out => error
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
clk_fb <= part_clk_p after 1 ns;
|
||||||
|
RST_O <= not locked;
|
||||||
|
|
||||||
|
-- DDR SDRAM Controller Core
|
||||||
|
sdram_ctrl_frontend_wb : entity work.sdram_ctrl_frontend_wb
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
BL => BURST_LEN,
|
||||||
|
f_sysclk => 100E6,
|
||||||
|
fifo_depth => 3
|
||||||
|
)
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
RST_I => RST_O,
|
||||||
|
CLK_I => CLK_O,
|
||||||
|
CLK270_I => CLK270_O,
|
||||||
|
CLK270VAR_I => CLK270VAR_O,
|
||||||
|
|
||||||
|
CYC_I => CYC_O,
|
||||||
|
STB_I => STB_O,
|
||||||
|
SEL_I => SEL_O,
|
||||||
|
WE_I => WE_O,
|
||||||
|
ACK_O => ACK_I,
|
||||||
|
SRDY_O => SRDY_I,
|
||||||
|
MRDY_I => MRDY_O,
|
||||||
|
ADDR_I => ADDR_O,
|
||||||
|
DAT_I => DAT_O,
|
||||||
|
DAT_O => DAT_I,
|
||||||
|
|
||||||
|
-- SDRAM signals
|
||||||
|
sd_clk_p => part_clk_p,
|
||||||
|
sd_clk_n => part_clk_n,
|
||||||
|
sd_cke => part_cke,
|
||||||
|
sd_cs_n => part_cs_n,
|
||||||
|
sd_cas_n => part_cas_n,
|
||||||
|
sd_ras_n => part_ras_n,
|
||||||
|
sd_we_n => part_we_n,
|
||||||
|
sd_addr => part_addr,
|
||||||
|
sd_ba => part_ba,
|
||||||
|
sd_dm => part_dm,
|
||||||
|
sd_dqs => part_dqs,
|
||||||
|
sd_data => part_data
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
-- MICRON DDR SDRAM Simulation Model
|
||||||
|
i_mt46v16m16_0 : entity work.mt46v16m16
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
dq => std_logic_vector(part_data),
|
||||||
|
dqs => std_logic_vector(part_dqs),
|
||||||
|
addr => std_logic_vector(part_addr),
|
||||||
|
ba => std_logic_vector(part_ba),
|
||||||
|
clk => part_clk_p,
|
||||||
|
clk_n => part_clk_n,
|
||||||
|
cke => part_cke,
|
||||||
|
cs_n => part_cs_n,
|
||||||
|
ras_n => part_ras_n,
|
||||||
|
cas_n => part_cas_n,
|
||||||
|
we_n => part_we_n,
|
||||||
|
dm => std_logic_vector(part_dm)
|
||||||
|
);
|
||||||
|
|
||||||
|
CLK_GEN: process
|
||||||
|
begin
|
||||||
|
wait for CLK_PERIOD/2;
|
||||||
|
clk <= not clk;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
read_register:
|
||||||
|
process(CLK_O)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_O) then
|
||||||
|
if dout_rst = '1' then
|
||||||
|
dout_cnt <= 0;
|
||||||
|
elsif ACK_I = '1' and WE_O = '0' then
|
||||||
|
dout_reg <= DAT_I;
|
||||||
|
dout_cnt <= dout_cnt + 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
STIMULUS: process
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
wait for 3*CLK_PERIOD;
|
||||||
|
rst <= '0';
|
||||||
|
|
||||||
|
wait until RST_O = '0';
|
||||||
|
-- 8 single cycles
|
||||||
|
CYC_O <= '1';
|
||||||
|
STB_O <= '1';
|
||||||
|
WE_O <= '1';
|
||||||
|
DAT_O <= X"1234_0000";
|
||||||
|
ADDR_O <= X"0000_0000";
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
DAT_O <= DAT_O + 1;
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
STB_O <= '0';
|
||||||
|
wait until rising_edge(CLK_O) and ACK_I = '1';
|
||||||
|
CYC_O <= '0';
|
||||||
|
|
||||||
|
|
||||||
|
-- 8-word burst cycle
|
||||||
|
wait for 3*CLK_PERIOD;
|
||||||
|
dout_rst <= '1';
|
||||||
|
wait until rising_edge(CLK_O);
|
||||||
|
dout_rst <= '0';
|
||||||
|
CYC_O <= '1';
|
||||||
|
STB_O <= '1';
|
||||||
|
WE_O <= '0';
|
||||||
|
ADDR_O <= X"0000_0000";
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
STB_O <= '0';
|
||||||
|
|
||||||
|
wait until rising_edge(CLK_O) and dout_cnt = 7;
|
||||||
|
CYC_O <= '0';
|
||||||
|
|
||||||
|
wait for 3*CLK_PERIOD;
|
||||||
|
wait until rising_edge(CLK_O);
|
||||||
|
-- 1-word burst cycle
|
||||||
|
CYC_O <= '1';
|
||||||
|
STB_O <= '1';
|
||||||
|
WE_O <= '1';
|
||||||
|
SEL_O <= "0011";
|
||||||
|
ADDR_O <= X"0000_0080";
|
||||||
|
DAT_O <= X"DEADBEEF";
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
STB_O <= '0';
|
||||||
|
wait until rising_edge(CLK_O) and ACK_I = '1';
|
||||||
|
CYC_O <= '0';
|
||||||
|
|
||||||
|
wait for 3*CLK_PERIOD;
|
||||||
|
wait until rising_edge(CLK_O);
|
||||||
|
-- 1-word burst cycle
|
||||||
|
CYC_O <= '1';
|
||||||
|
STB_O <= '1';
|
||||||
|
WE_O <= '0';
|
||||||
|
ADDR_O <= X"0000_0080";
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
STB_O <= '0';
|
||||||
|
wait until rising_edge(CLK_O) and ACK_I = '1';
|
||||||
|
CYC_O <= '0';
|
||||||
|
|
||||||
|
-- 8-word burst cycle
|
||||||
|
wait for 3*CLK_PERIOD;
|
||||||
|
dout_rst <= '1';
|
||||||
|
wait until rising_edge(CLK_O);
|
||||||
|
dout_rst <= '0';
|
||||||
|
CYC_O <= '1';
|
||||||
|
STB_O <= '1';
|
||||||
|
WE_O <= '0';
|
||||||
|
ADDR_O <= X"0000_0000";
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
STB_O <= '0';
|
||||||
|
MRDY_O <= '0';
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
STB_O <= '1';
|
||||||
|
MRDY_O <= '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
ADDR_O <= ADDR_O + 4;
|
||||||
|
wait until rising_edge(CLK_O) and SRDY_I = '1';
|
||||||
|
STB_O <= '0';
|
||||||
|
|
||||||
|
wait until rising_edge(CLK_O) and dout_cnt = 54;
|
||||||
|
CYC_O <= '0';
|
||||||
|
|
||||||
|
wait;
|
||||||
|
|
||||||
|
end process;
|
||||||
|
|
||||||
|
end architecture struct;
|
||||||
Reference in New Issue
Block a user