From e4a407ddd154d1ef0fa3dcb8ce17f26bd9a363e2 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Sun, 15 Feb 2015 19:08:40 +0100 Subject: [PATCH] Correct FPGA bus design for external CPU read cycle. The original design required to keep peripheral chip/clock enable signal for two clock cycles during read to ensure correct output data routing. Signed-off-by: Pavel Pisa --- hw/bus_tumbl.vhd | 59 +++++++++++++++++++++---------- hw/lx_rocon_top.vhd | 84 ++++++++++++++++++++++++--------------------- 2 files changed, 84 insertions(+), 59 deletions(-) diff --git a/hw/bus_tumbl.vhd b/hw/bus_tumbl.vhd index 2496570..9e09ef9 100644 --- a/hw/bus_tumbl.vhd +++ b/hw/bus_tumbl.vhd @@ -53,7 +53,9 @@ architecture Behavioral of bus_tumbl is -- Internal memory signals signal imem_en_s : std_logic; + signal imem_en_r : std_logic; signal dmem_en_s : std_logic; + signal dmem_en_r : std_logic; signal imem_we_s : std_logic_vector(3 downto 0); signal dmem_we_s : std_logic_vector(3 downto 0); @@ -61,6 +63,11 @@ architecture Behavioral of bus_tumbl is signal imem_data_o_s : std_logic_vector(31 downto 0); signal dmem_data_o_s : std_logic_vector(31 downto 0); + -- Control registers read access + signal tumbl_reg_en_control_r : std_logic; + signal tumbl_reg_en_pc_r : std_logic; + signal tumbl_reg_en_halt_code_r : std_logic; + -- Internal bus structure -- 12 address bits: 2 bits for selection, 10 bits for address -- @@ -157,7 +164,9 @@ enabling: process(ce_i, address_i) -- Wiring wiring: process(ce_i, bls_i, address_i, imem_en_s, imem_data_o_s, dmem_en_s, - dmem_data_o_s, tumbl_reset_s, tumbl_input_s, tumbl_state_s) + dmem_data_o_s, tumbl_reset_s, tumbl_input_s, tumbl_state_s, + imem_en_r, dmem_en_r, tumbl_reg_en_control_r, tumbl_reg_en_pc_r, + tumbl_reg_en_halt_code_r) begin if imem_en_s = '1' then @@ -172,26 +181,22 @@ wiring: dmem_we_s <= "0000"; end if; - if imem_en_s = '1' then + if imem_en_r = '1' then data_o <= imem_data_o_s; - elsif dmem_en_s = '1' then + elsif dmem_en_r = '1' then data_o <= dmem_data_o_s; - elsif ce_i = '1' and address_i(11 downto 10) = "11" then - if address_i(9 downto 0) = "0000000000" then - data_o(0) <= tumbl_reset_s; - data_o(1) <= tumbl_input_s.int; - data_o(2) <= tumbl_input_s.halt; - data_o(3) <= tumbl_input_s.trace; - data_o(4) <= tumbl_state_s.halted; - data_o(31 downto 5) <= (others => '0'); - elsif address_i(9 downto 0) = "0000000010" then - data_o <= tumbl_state_s.pc; - elsif address_i(9 downto 0) = "0000000011" then - data_o(4 downto 0) <= tumbl_state_s.halt_code; - data_o(31 downto 5) <= (others => '0'); - else - data_o <= (others => 'X'); - end if; + elsif tumbl_reg_en_control_r = '1' then + data_o(0) <= tumbl_reset_s; + data_o(1) <= tumbl_input_s.int; + data_o(2) <= tumbl_input_s.halt; + data_o(3) <= tumbl_input_s.trace; + data_o(4) <= tumbl_state_s.halted; + data_o(31 downto 5) <= (others => '0'); + elsif tumbl_reg_en_pc_r = '1' then + data_o <= tumbl_state_s.pc; + elsif tumbl_reg_en_halt_code_r = '1' then + data_o(4 downto 0) <= tumbl_state_s.halt_code; + data_o(31 downto 5) <= (others => '0'); else data_o <= (others => 'X'); end if; @@ -206,6 +211,13 @@ update: -- Update wait until clk_i'event and clk_i = '1'; + imem_en_r <= imem_en_s; + dmem_en_r <= dmem_en_s; + + tumbl_reg_en_control_r <= '0'; + tumbl_reg_en_pc_r <= '0'; + tumbl_reg_en_halt_code_r <= '0'; + tumbl_input_s.trace_kick <= '0'; if reset_i = '1' then @@ -229,6 +241,15 @@ update: end if; end if; end if; + + + if address_i(9 downto 0) = "0000000000" then + tumbl_reg_en_control_r <= '1'; + elsif address_i(9 downto 0) = "0000000010" then + tumbl_reg_en_pc_r <= '1'; + elsif address_i(9 downto 0) = "0000000011" then + tumbl_reg_en_halt_code_r <= '1'; + end if; end if; end if; diff --git a/hw/lx_rocon_top.vhd b/hw/lx_rocon_top.vhd index 439d275..10ecdca 100644 --- a/hw/lx_rocon_top.vhd +++ b/hw/lx_rocon_top.vhd @@ -100,25 +100,28 @@ architecture Behavioral of lx_rocon_top is -- Master to Tumbl DMEM / IMEM (Master) signal tumbl_out_s : std_logic_vector(31 downto 0); signal tumbl_ce_s : std_logic; + signal tumbl_ce_r : std_logic; -- Measurement (Master) signal meas_out_s : std_logic_vector(31 downto 0); signal meas_ce_s : std_logic; + signal meas_ce_r : std_logic; -- Master to Tumbl XMEM signal master_tumbl_xmem_out_s : std_logic_vector(31 downto 0); signal master_tumbl_xmem_ce_s : std_logic; + signal master_tumbl_xmem_ce_r : std_logic; signal master_tumbl_xmem_lock_s : std_logic; -- IRC (Tumbl) - signal irc_proc_out_s : std_logic_vector(31 downto 0); - signal irc_proc_ce_s : std_logic; - signal irc_proc_next_ce_s : std_logic; + signal irc_proc_out_s : std_logic_vector(31 downto 0); + signal irc_proc_ce_s : std_logic; + signal irc_proc_ce_r : std_logic; -- LX Master (Tumbl) signal lxmaster_out_s : std_logic_vector(15 downto 0); signal lxmaster_ce_s : std_logic; - signal lxmaster_next_ce_s : std_logic; + signal lxmaster_ce_r : std_logic; -- LX function approximation signal lxfncapprox_out_s : std_logic_vector(31 downto 0); signal lxfncapprox_ce_s : std_logic; - signal lxfncapprox_next_ce_s : std_logic; + signal lxfncapprox_ce_r : std_logic; -- Signals for external bus transmission signal data_i_s : std_logic_vector(31 downto 0); signal data_o_s : std_logic_vector(31 downto 0); @@ -142,11 +145,8 @@ architecture Behavioral of lx_rocon_top is signal cs0_xc_f_s : std_logic; signal rd_f_s : std_logic; -- Filtered RD signal i_rd_s : std_logic; -- Internal bus RD (active 1) - -- signal next_i_rd_s : std_logic; - signal last_i_rd_s : std_logic; -- Delayed RD bus, used for latching signal next_last_i_rd_s : std_logic; - signal i_rd_cycle2_s : std_logic; -- Some internal subsystems provide - signal next_i_rd_cycle2_s : std_logic; -- data only after 2 cycles + signal last_i_rd_s : std_logic; -- Delayed RD bus, used for latching -- signal address_f_s : std_logic_vector(15 downto 0); -- Filtered address -- @@ -232,7 +232,7 @@ memory_bus_irc: bus_irc -- clk_i => clk_50m, address_i => tumbl_address_s(4 downto 0), - next_ce_i => irc_proc_next_ce_s, + next_ce_i => irc_proc_ce_s, data_i => tumbl_data_i_s, data_o => irc_proc_out_s, bls_i => tumbl_bls_s, @@ -286,7 +286,7 @@ memory_bus_lxmaster: bus_lxmaster -- clk_i => clk_50m, address_i => tumbl_address_s(10 downto 0), - next_ce_i => lxmaster_next_ce_s, + next_ce_i => lxmaster_ce_s, data_i => tumbl_data_i_s(15 downto 0), data_o => lxmaster_out_s, bls_i => tumbl_bls_s(1 downto 0), @@ -322,7 +322,7 @@ function_approx: component lx_fncapprox clk_i => clk_50m, -- Data bus address_i => tumbl_address_s(4 downto 0), - next_ce_i => lxfncapprox_next_ce_s, + next_ce_i => lxfncapprox_ce_s, data_i => tumbl_data_i_s, data_o => lxfncapprox_out_s, bls_i => tumbl_bls_s @@ -363,12 +363,11 @@ dff_reset: dff2 -- Bus update memory_bus_logic: - process(cs0_xc_f_s, rd_f_s, last_rd_s, i_rd_cycle2_s, last_i_rd_s, + process(cs0_xc_f_s, rd_f_s, last_rd_s, last_i_rd_s, bls_f_s, last_bls_s, data_f_s, data_write_s, data_o_s, data_read_s, last_address_s, address_f_s) begin -- Defaults - next_i_rd_cycle2_s <= '0'; next_address_hold_s <= '0'; -- Check if we have chip select @@ -379,10 +378,6 @@ memory_bus_logic: -- Internal read if last_rd_s = '0' or (last_address_s /= address_f_s) then i_rd_s <= '1'; - next_i_rd_cycle2_s <= '1'; - next_last_i_rd_s <= '1'; - elsif i_rd_cycle2_s = '1' then -- FIXME it seems that some internal - i_rd_s <= '1'; -- peripherals demands 2 cycles to read next_last_i_rd_s <= '1'; else i_rd_s <= '0'; @@ -471,36 +466,40 @@ memory_bus_update: last_bls_s <= next_last_bls_s; last_rd_s <= next_last_rd_s; i_bls_s <= next_i_bls_s; - -- i_rd_s <= next_i_rd_s; - i_rd_cycle2_s <= next_i_rd_cycle2_s; last_i_rd_s <= next_last_i_rd_s; data_write_s <= next_data_write_s; last_address_s <= next_last_address_s; data_read_s <= next_data_read_s; + + -- Internal bus chipselects + tumbl_ce_r <= tumbl_ce_s; + meas_ce_r <= meas_ce_s; + master_tumbl_xmem_ce_r <= master_tumbl_xmem_ce_s; -- -- ====================================================== -- TUMBL BUS -- ====================================================== -- Just copy these to their desired next state - irc_proc_ce_s <= irc_proc_next_ce_s; - lxmaster_ce_s <= lxmaster_next_ce_s; - lxfncapprox_ce_s <= lxfncapprox_next_ce_s; + irc_proc_ce_r <= irc_proc_ce_s; + lxmaster_ce_r <= lxmaster_ce_s; + lxfncapprox_ce_r <= lxfncapprox_ce_s; end process; -- Do the actual wiring here memory_bus_wiring: - process(cs0_xc_f_s, i_bls_s, address_f_s, tumbl_out_s, meas_out_s, master_tumbl_xmem_out_s) + process(i_rd_s, i_bls_s, address_f_s, tumbl_out_s, meas_out_s, master_tumbl_xmem_out_s, + tumbl_ce_r, meas_ce_r, master_tumbl_xmem_ce_r, last_i_rd_s) begin -- Inactive by default tumbl_ce_s <= '0'; meas_ce_s <= '0'; master_tumbl_xmem_ce_s <= '0'; - data_o_s <= (others => '0'); + data_o_s <= (others => 'X'); - if cs0_xc_f_s = '1' or i_bls_s /= "0000" then + if i_rd_s = '1' or i_bls_s /= "0000" then -- Memory Map (16-bit address @ 32-bit each) @@ -511,17 +510,22 @@ memory_bus_wiring: if address_f_s < "0001000000000000" then -- Tumbl tumbl_ce_s <= '1'; - data_o_s <= tumbl_out_s; elsif address_f_s(15 downto 2) = "00011111111111" then -- Measurement meas_ce_s <= '1'; - data_o_s <= meas_out_s; elsif address_f_s(15) = '1' then -- Tumbl External BUS master_tumbl_xmem_ce_s <= '1'; - data_o_s <= master_tumbl_xmem_out_s; end if; end if; + if tumbl_ce_r = '1' then -- Tumbl + data_o_s <= tumbl_out_s; + elsif meas_ce_r = '1' then -- Measurement + data_o_s <= meas_out_s; + elsif master_tumbl_xmem_ce_r = '1' then -- Tumbl External BUS + data_o_s <= master_tumbl_xmem_out_s; + end if; + end process; -- If RD and BLS is not high, we must keep DATA at high impedance @@ -554,9 +558,9 @@ tumbl_bus_o: begin -- Defaults - irc_proc_next_ce_s <= '0'; - lxmaster_next_ce_s <= '0'; - lxfncapprox_next_ce_s <= '0'; + irc_proc_ce_s <= '0'; + lxmaster_ce_s <= '0'; + lxfncapprox_ce_s <= '0'; master_tumbl_xmem_lock_s <= '0'; -- addr_v := (others => '0'); @@ -578,11 +582,11 @@ tumbl_bus_o: -- LX FNC AP: 0x0C00 - 0x0C1F (32-bit address) -- LX MASTER: 0x1000 - 0x17FF (32-bit address) if addr_v(14 downto 5) = "0001000000" then - irc_proc_next_ce_s <= '1'; + irc_proc_ce_s <= '1'; elsif addr_v(14 downto 5) = "0001100000" then - lxfncapprox_next_ce_s <= '1'; + lxfncapprox_ce_s <= '1'; elsif addr_v(14 downto 11) = "0010" then - lxmaster_next_ce_s <= '1'; + lxmaster_ce_s <= '1'; end if; end if; @@ -590,8 +594,8 @@ tumbl_bus_o: -- Inputs to Tumbl (enabling and address muxing) tumbl_bus_i: - process(irc_proc_ce_s, irc_proc_out_s, lxmaster_ce_s, lxmaster_out_s, - lxfncapprox_ce_s, lxfncapprox_out_s, tumbl_xmemb_i_s) + process(irc_proc_ce_r, irc_proc_out_s, lxmaster_ce_r, lxmaster_out_s, + lxfncapprox_ce_r, lxfncapprox_out_s, tumbl_xmemb_i_s) begin tumbl_xmemb_i_s.data <= (others => 'X'); @@ -599,12 +603,12 @@ tumbl_bus_i: -- NOTE: This is input to Tumbl EXEQ - with MUL instruction for input > 18-bit, -- (i.e. more DSPs in a sequence), this already has tough timing constraints -- and SmartXplorer has to be used with XiSE or use Synplify. - if irc_proc_ce_s = '1' then + if irc_proc_ce_r = '1' then tumbl_xmemb_i_s.data <= irc_proc_out_s; - elsif lxmaster_ce_s = '1' then + elsif lxmaster_ce_r = '1' then tumbl_xmemb_i_s.data(15 downto 0) <= lxmaster_out_s; tumbl_xmemb_i_s.data(31 downto 16) <= (others => '0'); - elsif lxfncapprox_ce_s = '1' then + elsif lxfncapprox_ce_r = '1' then tumbl_xmemb_i_s.data <= lxfncapprox_out_s; end if; -- 2.39.2