From 56930a80c3f58081b2413ff54d6c40df5fbecdb5 Mon Sep 17 00:00:00 2001 From: Matthias Blankertz Date: Thu, 28 Feb 2013 15:54:48 +0100 Subject: [PATCH] - Seperated control and data path in wb_ddr_ctrl_wb_dc - Debugging wb_ddr_ctrl --- Default.wcfg | 419 ++++++++++++++++++++++++++++++++++ Makefile | 4 +- src/wb_ddr_ctrl_wb_dc.vhd | 267 ++++++++-------------- src/wb_ddr_ctrl_wb_dc_fsm.vhd | 269 ++++++++++++++++++++++ src/wb_ddr_ctrl_wb_sc.vhd | 57 +++-- tb/wb_ddr_ctrl_tb.vhd | 44 +++- 6 files changed, 854 insertions(+), 206 deletions(-) create mode 100755 Default.wcfg create mode 100755 src/wb_ddr_ctrl_wb_dc_fsm.vhd diff --git a/Default.wcfg b/Default.wcfg new file mode 100755 index 0000000..4c550f7 --- /dev/null +++ b/Default.wcfg @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + toplevel + label + + ddr2_clock + ddr2_clock + + + ddr2_reset + ddr2_reset + + + ddr2_dq[15:0] + ddr2_dq[15:0] + HEXRADIX + + + ddr2_a[12:0] + ddr2_a[12:0] + + + ddr2_ba[1:0] + ddr2_ba[1:0] + + + ddr2_cke + ddr2_cke + + + ddr2_cs_n + ddr2_cs_n + + + ddr2_ras_n + ddr2_ras_n + + + ddr2_cas_n + ddr2_cas_n + + + ddr2_we_n + ddr2_we_n + + + ddr2_odt + ddr2_odt + + + ddr2_dm[1:0] + ddr2_dm[1:0] + + + rst_dqs_div_in + rst_dqs_div_in + + + rst_dqs_div_out + rst_dqs_div_out + + + ddr2_dqs[1:0] + ddr2_dqs[1:0] + + + ddr2_dqs_n[1:0] + ddr2_dqs_n[1:0] + + + ddr2_ck[0:0] + ddr2_ck[0:0] + + + ddr2_ck_n[0:0] + ddr2_ck_n[0:0] + + + clk_i + clk_i + + + rst_i + rst_i + + + dat_i[31:0] + dat_i[31:0] + + + dat_o[31:0] + dat_o[31:0] + + + ack_o + ack_o + + + adr_i[25:2] + adr_i[25:2] + + + cyc_i + cyc_i + + + sel_i[3:0] + sel_i[3:0] + + + stb_i + stb_i + + + we_i + we_i + + + cti_i[2:0] + cti_i[2:0] + + + bte_i[1:0] + bte_i[1:0] + + + + ddr_cd_inst + label + + ddr2_clk0 + ddr2_clk0 + + + ddr2_clk180 + ddr2_clk180 + + + ddr2_clk90 + ddr2_clk90 + + + ddr2_reset + ddr2_reset + + + ctrl_input_data[31:0] + ctrl_input_data[31:0] + HEXRADIX + + + ctrl_data_mask[3:0] + ctrl_data_mask[3:0] + + + ctrl_output_data[31:0] + ctrl_output_data[31:0] + HEXRADIX + + + ctrl_data_valid + ctrl_data_valid + + + ctrl_input_address[24:0] + ctrl_input_address[24:0] + HEXRADIX + + + ctrl_command_register[2:0] + ctrl_command_register[2:0] + + + ctrl_burst_done + ctrl_burst_done + + + ctrl_auto_ref_req + ctrl_auto_ref_req + + + ctrl_cmd_ack + ctrl_cmd_ack + + + ctrl_init_done + ctrl_init_done + + + ctrl_ar_done + ctrl_ar_done + + + din[31:0] + din[31:0] + HEXRADIX + + + dout[31:0] + dout[31:0] + HEXRADIX + + + adr[23:0] + adr[23:0] + HEXRADIX + + + we + we + + + be[3:0] + be[3:0] + + + fifo_to_sys_write + fifo_to_sys_write + + + fifo_from_sys_read + fifo_from_sys_read + + + fifo_to_sys_full + fifo_to_sys_full + + + fifo_from_sys_empty + fifo_from_sys_empty + + + ddr_address[23:0] + ddr_address[23:0] + HEXRADIX + + + ddr_address_en + ddr_address_en + + + ddr_dout[31:0] + ddr_dout[31:0] + HEXRADIX + + + ddr_dout_en + ddr_dout_en + + + ddr_dmask[3:0] + ddr_dmask[3:0] + + + ddr_dmask_rst + ddr_dmask_rst + + + ddr_dmask_en + ddr_dmask_en + + + ctrl_command_register_d[2:0] + ctrl_command_register_d[2:0] + + + ctrl_burst_done_d + ctrl_burst_done_d + + + ctrl_state + ctrl_state + + + burst_start_adr[12:0] + burst_start_adr[12:0] + + + fifo_pending + fifo_pending + + + fifo_from_sys_read_int + fifo_from_sys_read_int + + + fifo_from_sys_valid + fifo_from_sys_valid + + + + system_cd_inst + label + + clk_i + clk_i + + + rst_i + rst_i + + + dat_i[31:0] + dat_i[31:0] + HEXRADIX + + + dat_o[31:0] + dat_o[31:0] + HEXRADIX + + + ack_o + ack_o + + + adr_i[25:2] + adr_i[25:2] + HEXRADIX + + + cyc_i + cyc_i + + + sel_i[3:0] + sel_i[3:0] + + + stb_i + stb_i + + + we_i + we_i + + + cti_i[2:0] + cti_i[2:0] + + + bte_i[1:0] + bte_i[1:0] + + + ddr_din[31:0] + ddr_din[31:0] + HEXRADIX + + + ddr_dout[31:0] + ddr_dout[31:0] + HEXRADIX + + + ddr_adr[23:0] + ddr_adr[23:0] + HEXRADIX + + + ddr_we + ddr_we + + + ddr_be[3:0] + ddr_be[3:0] + + + fifo_to_ddr_write + fifo_to_ddr_write + + + fifo_from_ddr_read + fifo_from_ddr_read + + + fifo_to_ddr_full + fifo_to_ddr_full + + + fifo_from_ddr_empty + fifo_from_ddr_empty + + + state + state + + + fifo_from_ddr_read_int + fifo_from_ddr_read_int + + + fifo_from_ddr_valid + fifo_from_ddr_valid + + + diff --git a/Makefile b/Makefile index dee2541..52d10a9 100755 --- a/Makefile +++ b/Makefile @@ -26,8 +26,8 @@ ddr2_sdram/vhdl_bl4/example_design/rtl/vhdl_bl4_s3_dm_iob.vhd \ ddr2_sdram/vhdl_bl4/example_design/rtl/vhdl_bl4_s3_dqs_iob.vhd \ ddr2_sdram/vhdl_bl4/example_design/rtl/vhdl_bl4_s3_dq_iob.vhd \ src/toplevel.vhd src/clk_reset.vhd src/wb_ddr_ctrl.vhd src/wb_ddr_ctrl_ddrwrap.vhd \ -src/wb_ddr_ctrl_wb.vhd src/wb_ddr_ctrl_wb_dc.vhd src/wb_ddr_ctrl_wb_sc.vhd \ - +src/wb_ddr_ctrl_wb.vhd src/wb_ddr_ctrl_wb_dc_fsm.vhd src/wb_ddr_ctrl_wb_dc.vhd \ +src/wb_ddr_ctrl_wb_sc.vhd SYN_INFILES= PSMFILES= CORES=wb_ddr_ctrl_wb_from_ddr wb_ddr_ctrl_wb_to_ddr diff --git a/src/wb_ddr_ctrl_wb_dc.vhd b/src/wb_ddr_ctrl_wb_dc.vhd index 7afdb14..e24670f 100755 --- a/src/wb_ddr_ctrl_wb_dc.vhd +++ b/src/wb_ddr_ctrl_wb_dc.vhd @@ -68,54 +68,99 @@ end wb_ddr_ctrl_wb_dc; architecture Behavioral of wb_ddr_ctrl_wb_dc is --- DDR2 Controller commands -constant ctrl_command_nop : std_logic_vector(2 downto 0) := "000"; -constant ctrl_command_initialize : std_logic_vector(2 downto 0) := "010"; -constant ctrl_command_write : std_logic_vector(2 downto 0) := "100"; -constant ctrl_command_read : std_logic_vector(2 downto 0) := "110"; + component wb_ddr_ctrl_wb_dc_fsm + port ( + ddr2_clk0 : in std_ulogic; + ddr2_clk180 : in std_ulogic; + ddr2_reset : in std_ulogic; + ctrl_data_valid : in std_logic; + ctrl_auto_ref_req : in std_logic; + ctrl_cmd_ack : in std_logic; + ctrl_init_done : in std_logic; + ctrl_ar_done : in std_logic; + fifo_from_sys_empty : in std_ulogic; + we : in std_ulogic; + row_addr : in std_ulogic_vector(12 downto 0); + ddr_address_en : out std_ulogic; + ddr_dout_en : out std_ulogic; + ddr_dmask_rst : out std_ulogic; + ddr_dmask_en : out std_ulogic; + ctrl_command_register_d : out std_logic_vector(2 downto 0); + ctrl_burst_done_d : out std_ulogic; + fifo_from_sys_read : out std_ulogic); + end component; + +signal ddr_address : std_ulogic_vector(23 downto 0) := (others => '-'); +signal ddr_address_en : std_ulogic := '0'; --- DDR-side FSM -type ctrl_states is (S_RESET, S_INITIALIZE, S_WAITINITDONE, S_IDLE, S_REFRESH, S_REQUEST_INIT, S_WRITE1, - S_WRITE2, S_WRITE3, S_WRITE4, S_WRITE_END1, S_WRITE_END2, S_READ1, S_READ2, - S_READ3, S_READ4, S_READ5, S_READ_END1, S_READ_END2); -signal ctrl_state : ctrl_states := S_RESET; -signal burst_start_adr : std_ulogic_vector(12 downto 0); +signal ddr_dout : std_ulogic_vector(31 downto 0) := (others => '-'); +signal ddr_dout_en : std_ulogic := '0'; --- fifo_pending is '1' when a valid, unprocessed request is on the fifo outputs --- the idle state does not cause a fifo read if fifo_pending is '1' -signal fifo_from_sys_read_int, fifo_from_sys_valid, fifo_pending : std_ulogic; +signal ddr_dmask : std_ulogic_vector(3 downto 0) := (others => '0'); +signal ddr_dmask_rst, ddr_dmask_en : std_ulogic := '0'; -signal ddr_address : std_ulogic_vector(23 downto 0); -signal ddr_dout : std_ulogic_vector(31 downto 0); -signal ddr_dmask : std_ulogic_vector(3 downto 0); +signal ctrl_command_register_d : std_logic_vector(2 downto 0) := "000"; +signal ctrl_burst_done_d : std_ulogic := '0'; begin +wb_ddr_ctrl_wb_dc_fsm_inst: wb_ddr_ctrl_wb_dc_fsm + port map ( + ddr2_clk0 => ddr2_clk0, + ddr2_clk180 => ddr2_clk180, + ddr2_reset => ddr2_reset, + ctrl_data_valid => ctrl_data_valid, + ctrl_auto_ref_req => ctrl_auto_ref_req, + ctrl_cmd_ack => ctrl_cmd_ack, + ctrl_init_done => ctrl_init_done, + ctrl_ar_done => ctrl_ar_done, + fifo_from_sys_empty => fifo_from_sys_empty, + we => we, + row_addr => adr(21 downto 9), + ddr_address_en => ddr_address_en, + ddr_dout_en => ddr_dout_en, + ddr_dmask_rst => ddr_dmask_rst, + ddr_dmask_en => ddr_dmask_en, + ctrl_command_register_d => ctrl_command_register_d, + ctrl_burst_done_d => ctrl_burst_done_d, + fifo_from_sys_read => fifo_from_sys_read + ); + +-- ddr_address register +ddr_address_reg : process(ddr2_clk180) + begin + if rising_edge(ddr2_clk180) then + if ddr_address_en = '1' then + ddr_address <= adr; + end if; + end if; + end process ddr_address_reg; + -- remap address for ddr controller (so column is lowest) ctrl_input_address <= std_logic_vector(ddr_address(21 downto 9) & ddr_address(8 downto 0) & '0' & ddr_address(23 downto 22)); --- input FIFO control -fifo_from_sys_read_int <= '1' when ((ctrl_state = S_IDLE and ctrl_auto_ref_req = '0' and fifo_pending = '0') or - (ctrl_state = S_REQUEST_INIT and we = '1') or - (ctrl_state = S_WRITE1 and ctrl_cmd_ack = '1') or - (ctrl_state = S_WRITE2 and not (fifo_from_sys_valid = '0' or adr(21 downto 9) /= burst_start_adr or - we = '0' or ctrl_auto_ref_req = '1')) or - (ctrl_state = S_WRITE4) or - (ctrl_state = S_READ2 or ctrl_state = S_READ3) or - (ctrl_state = S_READ4 and not (fifo_from_sys_valid = '0' or adr(21 downto 9) /= burst_start_adr or - we = '1' or ctrl_auto_ref_req = '1')) or - (ctrl_state = S_READ5) - ) and fifo_from_sys_empty = '0' else - '0'; -is_fifo_from_sys_valid : process(ddr2_clk0) - begin - if rising_edge(ddr2_clk0) then - fifo_from_sys_valid <= fifo_from_sys_read_int; - end if; - end process is_fifo_from_sys_valid; - -fifo_from_sys_read <= fifo_from_sys_read_int; +-- ddr_dout register +ddr_dout_reg : process(ddr2_clk180) + begin + if rising_edge(ddr2_clk180) then + if ddr_dout_en = '1' then + ddr_dout <= din; + end if; + end if; + end process ddr_dout_reg; +-- ddr_dmask register +ddr_dmask_reg : process(ddr2_clk180) + begin + if rising_edge(ddr2_clk180) then + if ddr_dmask_rst = '1' or ddr2_reset = '1' then + ddr_dmask <= (others => '0'); + elsif ddr_dmask_en = '1' then + ddr_dmask <= be; + end if; + end if; + end process ddr_dmask_reg; + -- resync data to ddr to ddr2_clk90 ddr_dout_resync : process(ddr2_clk90) begin @@ -125,134 +170,24 @@ ddr_dout_resync : process(ddr2_clk90) end if; end process ddr_dout_resync; +-- ctrl_command_register register +ctrl_command_register_reg : process(ddr2_clk180) + begin + if rising_edge(ddr2_clk180) then + ctrl_command_register <= ctrl_command_register_d; + end if; + end process ctrl_command_register_reg; + +-- ctrl_burst_done register +ctrl_burst_done_reg : process(ddr2_clk180) + begin + if rising_edge(ddr2_clk180) then + ctrl_burst_done <= ctrl_burst_done_d; + end if; + end process ctrl_burst_done_reg; + -- move data from ddr to fifo dout <= std_ulogic_vector(ctrl_output_data); -fifo_to_sys_write <= ctrl_data_valid and not ddr2_reset; - -ctrl_fsm : process(ddr2_clk180) - begin - if rising_edge(ddr2_clk180) then - if ddr2_reset = '1' then - ctrl_state <= S_RESET; - ddr_dout <= (others => '-'); - ddr_dmask <= (others => '0'); - ddr_address <= (others => '-'); - ctrl_burst_done <= '0'; - ctrl_command_register <= ctrl_command_nop; - - fifo_pending <= '0'; - else - ctrl_command_register <= ctrl_command_nop; - ctrl_burst_done <= '0'; - - case ctrl_state is - when S_RESET => - ctrl_state <= S_INITIALIZE; - when S_INITIALIZE => - ctrl_command_register <= ctrl_command_initialize; - ctrl_state <= S_WAITINITDONE; - when S_WAITINITDONE => - if ctrl_init_done = '1' then - ctrl_state <= S_IDLE; - end if; - when S_IDLE => - if ctrl_auto_ref_req = '1' then -- DDR controller requests refresh - ctrl_state <= S_REFRESH; - elsif fifo_from_sys_valid = '1' then -- A request from the system is pending - ctrl_state <= S_REQUEST_INIT; - end if; -- else do nothing - when S_REFRESH => - if ctrl_ar_done = '1' then - ctrl_state <= S_IDLE; - end if; - when S_REQUEST_INIT => - if we = '1' then - ctrl_command_register <= ctrl_command_write; - ctrl_state <= S_WRITE1; - ddr_dout <= din; - ddr_dmask <= be; - else - ctrl_command_register <= ctrl_command_read; - ctrl_state <= S_READ1; - end if; - burst_start_adr <= adr(21 downto 9); - ddr_address <= adr; - - when S_WRITE1 => - ctrl_command_register <= ctrl_command_write; - if ctrl_cmd_ack = '1' then - ddr_dout <= din; - ddr_dmask <= be; - ctrl_state <= S_WRITE2; - end if; - when S_WRITE2 => - ctrl_command_register <= ctrl_command_write; - if fifo_from_sys_valid = '0' or adr(21 downto 9) /= burst_start_adr or - we = '0' or ctrl_auto_ref_req = '1' then - -- next request incompatible with burst type, or auto refresh requested - ctrl_burst_done <= '1'; - fifo_pending <= fifo_from_sys_valid; - ctrl_state <= S_WRITE_END1; - else - ddr_dout <= din; - ddr_dmask <= be; - ctrl_state <= S_WRITE3; - end if; - when S_WRITE3 => - ctrl_command_register <= ctrl_command_write; - ddr_dout <= din; - ddr_dmask <= be; - ddr_address <= adr; - ctrl_state <= S_WRITE4; - when S_WRITE4 => - ctrl_command_register <= ctrl_command_write; - ctrl_state <= S_WRITE2; - - when S_WRITE_END1 => - ctrl_burst_done <= '1'; - ctrl_state <= S_WRITE_END2; - when S_WRITE_END2 => - if ctrl_cmd_ack = '0' then - ctrl_state <= S_IDLE; - end if; - - when S_READ1 => - ctrl_command_register <= ctrl_command_read; - if ctrl_cmd_ack = '1' then - ctrl_state <= S_READ2; - end if; - when S_READ2 => - ctrl_command_register <= ctrl_command_read; - ctrl_state <= S_READ3; - when S_READ3 => - ctrl_command_register <= ctrl_command_read; - ctrl_state <= S_READ4; - when S_READ4 => - ctrl_command_register <= ctrl_command_read; - if fifo_from_sys_valid = '0' or adr(21 downto 9) /= burst_start_adr or - we = '1' or ctrl_auto_ref_req = '1' then - -- next request incompatible with burst type, or auto refresh requested - fifo_pending <= fifo_from_sys_valid; - ctrl_burst_done <= '1'; - ctrl_state <= S_READ_END1; - else - ddr_address <= adr; - ctrl_state <= S_READ5; - end if; - when S_READ5 => - ctrl_command_register <= ctrl_command_read; - ctrl_state <= S_READ4; - - when S_READ_END1 => - ctrl_burst_done <= '1'; - ctrl_state <= S_READ_END2; - when S_READ_END2 => - if ctrl_cmd_ack = '0' then - ctrl_state <= S_IDLE; - end if; - end case; - end if; - end if; - end process ctrl_fsm; - +fifo_to_sys_write <= ctrl_data_valid; + end Behavioral; diff --git a/src/wb_ddr_ctrl_wb_dc_fsm.vhd b/src/wb_ddr_ctrl_wb_dc_fsm.vhd new file mode 100755 index 0000000..45158aa --- /dev/null +++ b/src/wb_ddr_ctrl_wb_dc_fsm.vhd @@ -0,0 +1,269 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 11/06/2012 03:04:35 PM +-- Design Name: +-- Module Name: wb_ddr_ctrl_wb_dc_fsm - Behavioral +-- Project Name: +-- Target Devices: +-- Tool Versions: +-- Description: +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- + + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; + +-- Uncomment the following library declaration if using +-- arithmetic functions with Signed or Unsigned values +--use IEEE.NUMERIC_STD.ALL; + +-- Uncomment the following library declaration if instantiating +-- any Xilinx primitives in this code. +--library UNISIM; +--use UNISIM.VComponents.all; + +entity wb_ddr_ctrl_wb_dc_fsm is + port ( + -- Control signals + ddr2_clk0 : in std_ulogic; + ddr2_clk180 : in std_ulogic; + ddr2_reset : in std_ulogic; + + -- Inputs + ctrl_data_valid : in std_logic; + ctrl_auto_ref_req : in std_logic; + ctrl_cmd_ack : in std_logic; + ctrl_init_done : in std_logic; + ctrl_ar_done : in std_logic; + fifo_from_sys_empty : in std_ulogic; + we : in std_ulogic; + row_addr : in std_ulogic_vector(12 downto 0); + + -- Outputs + ddr_address_en : out std_ulogic; + ddr_dout_en : out std_ulogic; + ddr_dmask_rst : out std_ulogic; + ddr_dmask_en : out std_ulogic; + ctrl_command_register_d : out std_logic_vector(2 downto 0); + ctrl_burst_done_d : out std_ulogic; + fifo_from_sys_read : out std_ulogic + ); +end wb_ddr_ctrl_wb_dc_fsm; + +architecture Behavioral of wb_ddr_ctrl_wb_dc_fsm is +-- DDR2 Controller commands +constant ctrl_command_nop : std_logic_vector(2 downto 0) := "000"; +constant ctrl_command_initialize : std_logic_vector(2 downto 0) := "010"; +constant ctrl_command_write : std_logic_vector(2 downto 0) := "100"; +constant ctrl_command_read : std_logic_vector(2 downto 0) := "110"; + +-- DDR-side FSM +type ctrl_states is (S_RESET, S_INITIALIZE, S_WAITINITDONE, S_IDLE, S_REFRESH, S_REQUEST_INIT, S_WRITE1, + S_WRITE2, S_WRITE3, S_WRITE4, S_WRITE_END1, S_WRITE_END2, S_READ1, S_READ2, + S_READ3, S_READ4, S_READ5, S_READ_END1, S_READ_END2); +signal ctrl_state : ctrl_states := S_RESET; +signal burst_start_adr : std_ulogic_vector(12 downto 0) := (others => '-'); + +signal fifo_pending : std_ulogic := '0'; +-- fifo_pending is '1' when a valid, unprocessed request is on the fifo outputs +-- the idle state does not cause a fifo read if fifo_pending is '1' +signal fifo_from_sys_read_int, fifo_from_sys_valid : std_ulogic := '0'; + +begin + +-- input FIFO control +fifo_from_sys_read_int <= '1' when ((ctrl_state = S_IDLE and ctrl_auto_ref_req = '0' and fifo_pending = '0') or + (ctrl_state = S_REQUEST_INIT and we = '1') or + (ctrl_state = S_WRITE1 and ctrl_cmd_ack = '1') or + (ctrl_state = S_WRITE2 and not (fifo_from_sys_valid = '0' or row_addr /= burst_start_adr or + we = '0' or ctrl_auto_ref_req = '1')) or + (ctrl_state = S_WRITE4) or + (ctrl_state = S_READ3 or ctrl_state = S_READ5) or + (ctrl_state = S_READ4 and not (fifo_from_sys_valid = '0' or row_addr /= burst_start_adr or + we = '1' or ctrl_auto_ref_req = '1')) or + (ctrl_state = S_READ2) + ) and fifo_from_sys_empty = '0' else + '0'; + +is_fifo_from_sys_valid : process(ddr2_clk0) + begin + if rising_edge(ddr2_clk0) then + fifo_from_sys_valid <= fifo_from_sys_read_int; + end if; + end process is_fifo_from_sys_valid; + +fifo_from_sys_read <= fifo_from_sys_read_int; + +ctrl_fsm_state : process(ddr2_clk180) + begin + if rising_edge(ddr2_clk180) then + if ddr2_reset = '1' then + ctrl_state <= S_RESET; + fifo_pending <= '0'; + else + case ctrl_state is + when S_RESET => + ctrl_state <= S_INITIALIZE; + when S_INITIALIZE => + ctrl_state <= S_WAITINITDONE; + when S_WAITINITDONE => + if ctrl_init_done = '1' then + ctrl_state <= S_IDLE; + end if; + when S_IDLE => + if ctrl_auto_ref_req = '1' then -- DDR controller requests refresh + ctrl_state <= S_REFRESH; + elsif fifo_from_sys_valid = '1' then -- A request from the system is pending + ctrl_state <= S_REQUEST_INIT; + end if; -- else do nothing + when S_REFRESH => + if ctrl_ar_done = '1' then + ctrl_state <= S_IDLE; + end if; + when S_REQUEST_INIT => + if we = '1' then + ctrl_state <= S_WRITE1; + else + ctrl_state <= S_READ1; + end if; + burst_start_adr <= row_addr; + + when S_WRITE1 => + if ctrl_cmd_ack = '1' then + ctrl_state <= S_WRITE2; + end if; + when S_WRITE2 => + if fifo_from_sys_valid = '0' or row_addr /= burst_start_adr or + we = '0' or ctrl_auto_ref_req = '1' then + -- next request incompatible with burst type, or auto refresh requested + fifo_pending <= fifo_from_sys_valid; + ctrl_state <= S_WRITE_END1; + else + ctrl_state <= S_WRITE3; + end if; + when S_WRITE3 => + ctrl_state <= S_WRITE4; + when S_WRITE4 => + ctrl_state <= S_WRITE2; + + when S_WRITE_END1 => + ctrl_state <= S_WRITE_END2; + when S_WRITE_END2 => + if ctrl_cmd_ack = '0' then + ctrl_state <= S_IDLE; + end if; + + when S_READ1 => + if ctrl_cmd_ack = '1' then + ctrl_state <= S_READ2; + end if; + when S_READ2 => + ctrl_state <= S_READ3; + when S_READ3 => + ctrl_state <= S_READ4; + when S_READ4 => + if fifo_from_sys_valid = '0' or row_addr /= burst_start_adr or + we = '1' or ctrl_auto_ref_req = '1' then + -- next request incompatible with burst type, or auto refresh requested + fifo_pending <= fifo_from_sys_valid; + ctrl_state <= S_READ_END1; + else + ctrl_state <= S_READ5; + end if; + when S_READ5 => + ctrl_state <= S_READ4; + + when S_READ_END1 => + ctrl_state <= S_READ_END2; + when S_READ_END2 => + if ctrl_cmd_ack = '0' then + ctrl_state <= S_IDLE; + end if; + end case; + end if; + end if; + end process ctrl_fsm_state; + +ctrl_fsm_out : process(ctrl_state, ddr2_reset, we, ctrl_cmd_ack, fifo_from_sys_valid, + row_addr, burst_start_adr, ctrl_auto_ref_req) + begin + ddr_dmask_rst <= '0'; + ddr_dmask_en <= '0'; + ddr_dout_en <= '0'; + ddr_address_en <= '0'; + ctrl_burst_done_d <= '0'; + ctrl_command_register_d <= ctrl_command_nop; + + case ctrl_state is + when S_INITIALIZE => + ctrl_command_register_d <= ctrl_command_initialize; + when S_REQUEST_INIT => + if we = '1' then + ddr_dmask_en <= '1'; + ddr_dout_en <= '1'; + ctrl_command_register_d <= ctrl_command_write; + else + ctrl_command_register_d <= ctrl_command_read; + end if; + ddr_address_en <= '1'; + + when S_WRITE1 => + if ctrl_cmd_ack = '1' then + ddr_dmask_en <= '1'; + ddr_dout_en <= '1'; + end if; + ctrl_command_register_d <= ctrl_command_write; + when S_WRITE2 => + if fifo_from_sys_valid = '0' or row_addr /= burst_start_adr or + we = '0' or ctrl_auto_ref_req = '1' then + -- next request incompatible with burst type, or auto refresh requested + ctrl_burst_done_d <= '1'; + else + ddr_dmask_en <= '1'; + ddr_dout_en <= '1'; + end if; + ctrl_command_register_d <= ctrl_command_write; + when S_WRITE3 => + ddr_dmask_en <= '1'; + ddr_dout_en <= '1'; + ddr_address_en <= '1'; + ctrl_command_register_d <= ctrl_command_write; + when S_WRITE4 => + ctrl_command_register_d <= ctrl_command_write; + when S_WRITE_END1 => + ctrl_burst_done_d <= '1'; + + when S_READ1 => + ctrl_command_register_d <= ctrl_command_read; + when S_READ2 => + ctrl_command_register_d <= ctrl_command_read; + when S_READ3 => + ctrl_command_register_d <= ctrl_command_read; + when S_READ4 => + if fifo_from_sys_valid = '0' or row_addr /= burst_start_adr or + we = '1' or ctrl_auto_ref_req = '1' then + -- next request incompatible with burst type, or auto refresh requested + ctrl_burst_done_d <= '1'; + else + ddr_address_en <= '1'; + end if; + when S_READ5 => + ctrl_command_register_d <= ctrl_command_read; + when S_READ_END1 => + ctrl_burst_done_d <= '1'; + + when others => + null; + end case; + end process ctrl_fsm_out; + +end Behavioral; diff --git a/src/wb_ddr_ctrl_wb_sc.vhd b/src/wb_ddr_ctrl_wb_sc.vhd index 1d82c8f..444300a 100755 --- a/src/wb_ddr_ctrl_wb_sc.vhd +++ b/src/wb_ddr_ctrl_wb_sc.vhd @@ -24,7 +24,7 @@ use IEEE.STD_LOGIC_1164.ALL; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values ---use IEEE.NUMERIC_STD.ALL; +use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. @@ -62,15 +62,14 @@ entity wb_ddr_ctrl_wb_sc is end wb_ddr_ctrl_wb_sc; architecture Behavioral of wb_ddr_ctrl_wb_sc is -type states is (S_IDLE, S_WRITE_CLASSIC1, S_READ_CLASSIC1, S_READ_CLASSIC2, S_READ_CLASSIC3); +type states is (S_IDLE, S_WRITE_CLASSIC1, S_READ_CLASSIC1, S_READ_CLASSIC2); signal state : states := S_IDLE; signal fifo_from_ddr_read_int, fifo_from_ddr_valid : std_ulogic; begin fifo_from_ddr_read_int <= '1' when (((state = S_READ_CLASSIC1 and fifo_to_ddr_full = '0') or - (state = S_READ_CLASSIC2) or - (state = S_READ_CLASSIC3 and fifo_from_ddr_valid = '0') + (state = S_READ_CLASSIC2) ) and fifo_from_ddr_empty = '0') or rst_i = '1' else '0'; @@ -92,6 +91,7 @@ wb_slave : process(clk_i) ddr_we <= '-'; ddr_be <= (others => '-'); fifo_to_ddr_write <= '0'; + ack_o <= '0'; state <= S_IDLE; else ddr_din <= (others => '-'); @@ -99,6 +99,7 @@ wb_slave : process(clk_i) ddr_we <= '-'; ddr_be <= (others => '-'); fifo_to_ddr_write <= '0'; + ack_o <= '0'; case state is when S_IDLE => if stb_i = '1' then @@ -110,7 +111,7 @@ wb_slave : process(clk_i) ddr_din <= dat_i; ddr_adr <= adr_i; ddr_we <= '1'; - ddr_be <= sel_i; + ddr_be <= not sel_i; fifo_to_ddr_write <= '1'; state <= S_WRITE_CLASSIC1; end if; @@ -128,35 +129,31 @@ wb_slave : process(clk_i) end if; end if; end if; + when S_WRITE_CLASSIC1 => - if fifo_to_ddr_full = '0' then - ddr_din <= (others => '-'); - ddr_adr <= adr_i; - ddr_we <= '1'; - ddr_be <= (others => '0'); - fifo_to_ddr_write <= '1'; - - ack_o <= '1'; - state <= S_IDLE; - end if; + if fifo_to_ddr_full = '0' then + ddr_din <= (others => '-'); + ddr_adr <= std_ulogic_vector(unsigned(adr_i) + 1); + ddr_we <= '1'; + ddr_be <= (others => '1'); + fifo_to_ddr_write <= '1'; + ack_o <= '1'; + state <= S_IDLE; + end if; when S_READ_CLASSIC1 => - if fifo_to_ddr_full = '0' then - ddr_adr <= adr_i; - ddr_we <= '0'; - fifo_to_ddr_write <= '1'; - state <= S_READ_CLASSIC2; - end if; + if fifo_to_ddr_full = '0' then + ddr_adr <= std_ulogic_vector(unsigned(adr_i) + 1); + ddr_we <= '0'; + fifo_to_ddr_write <= '1'; + state <= S_READ_CLASSIC2; + end if; when S_READ_CLASSIC2 => - if fifo_from_ddr_valid = '1' then - dat_o <= ddr_dout; - state <= S_READ_CLASSIC3; - end if; - when S_READ_CLASSIC3 => - if fifo_from_ddr_valid = '1' then - ack_o <= '1'; - state <= S_IDLE; - end if; + if fifo_from_ddr_valid = '1' then + dat_o <= ddr_dout; + ack_o <= '1'; + state <= S_IDLE; + end if; end case; end if; end if; diff --git a/tb/wb_ddr_ctrl_tb.vhd b/tb/wb_ddr_ctrl_tb.vhd index 6df4136..2944df2 100755 --- a/tb/wb_ddr_ctrl_tb.vhd +++ b/tb/wb_ddr_ctrl_tb.vhd @@ -108,16 +108,16 @@ architecture testbench of wb_ddr_ctrl_tb is signal ddr2_ck_n : std_logic_vector(0 downto 0); signal clk_i : std_ulogic := '0'; signal rst_i : std_ulogic; - signal dat_i : std_ulogic_vector(31 downto 0); + signal dat_i : std_ulogic_vector(31 downto 0) := (others => '-'); signal dat_o : std_ulogic_vector(31 downto 0); signal ack_o : std_ulogic; - signal adr_i : std_ulogic_vector(25 downto 2); - signal cyc_i : std_ulogic; - signal sel_i : std_ulogic_vector(3 downto 0); - signal stb_i : std_ulogic; - signal we_i : std_ulogic; - signal cti_i : std_ulogic_vector(2 downto 0); - signal bte_i : std_ulogic_vector(1 downto 0); + signal adr_i : std_ulogic_vector(25 downto 2) := (others => '-'); + signal cyc_i : std_ulogic := '0'; + signal sel_i : std_ulogic_vector(3 downto 0) := (others => '0'); + signal stb_i : std_ulogic := '0'; + signal we_i : std_ulogic := '0'; + signal cti_i : std_ulogic_vector(2 downto 0) := (others => '0'); + signal bte_i : std_ulogic_vector(1 downto 0) := (others => '0'); begin -- testbench @@ -191,6 +191,34 @@ begin -- testbench wait until rising_edge(clk_i); rst_i <= '0' after 2 ns; + -- simple write cycle + wait until rising_edge(clk_i); + stb_i <= '1' after 2 ns; + we_i <= '1' after 2 ns; + sel_i <= "1111" after 2 ns; + adr_i <= x"000010" after 2 ns; + dat_i <= x"deadbeef" after 2 ns; + + wait until rising_edge(clk_i); + while ack_o = '0' loop + wait until rising_edge(clk_i); + end loop; + stb_i <= '0' after 2 ns; + wait until rising_edge(clk_i); + + -- simple read cycle + wait until rising_edge(clk_i); + stb_i <= '1' after 2 ns; + we_i <= '0' after 2 ns; + adr_i <= x"000010" after 2 ns; + wait until rising_edge(clk_i); + while ack_o = '0' loop + wait until rising_edge(clk_i); + end loop; + stb_i <= '0' after 2 ns; + assert dat_o = x"deadbeef" report "Read failed: unexpected data" severity failure; + wait until rising_edge(clk_i); + wait; end process WaveGen_Proc;