reset_i : in std_logic;
-- Data bus
address_i : in std_logic_vector(10 downto 0);
- next_ce_i : in std_logic;
+ ce_i : in std_logic;
data_i : in std_logic_vector(15 downto 0);
data_o : out std_logic_vector(15 downto 0);
--
bls_i : in std_logic_vector(1 downto 0);
+ --
+ rx_done_o : out std_logic;
-- Signals for LX Master
clock_i : in std_logic;
miso_i : in std_logic;
architecture Behavioral of bus_lxmaster is
+ constant cycle_cnt_width_c : natural := 12; -- number of bits
+ constant rx_done_div_width_c : natural := 5; -- number of bits
+ constant rx_done_cnt_width_c : natural := 5; -- number of bits
+
signal mem_trans_en_s : std_logic;
signal mem_trans_bls_s : std_logic_vector(1 downto 0);
signal mem_trans_addr_s : std_logic_vector(8 downto 0);
signal mem_trans_out_s : std_logic;
signal mem_trans_out_r : std_logic;
--
- signal state_o_s : std_logic;
- signal state_o_r : std_logic;
+ signal mem_recv_en_s : std_logic;
+ signal mem_recv_bls_s : std_logic_vector(1 downto 0);
+ signal mem_recv_addr_s : std_logic_vector(8 downto 0);
+ signal mem_recv_data_s : std_logic_vector(15 downto 0);
+ signal mem_recv_out_s : std_logic;
+ signal mem_recv_out_r : std_logic;
+ --
+ signal state_o_s : std_logic_vector(15 downto 0);
+ signal state_o_r : std_logic_vector(15 downto 0);
--
signal reset_reg_s : std_logic;
signal reset_reg_r : std_logic;
signal reset_reg_wr_s : std_logic;
--
signal reset_s : std_logic;
- signal ce_s : std_logic;
+ signal ce_r : std_logic;
--
signal register_trans_in_s : std_logic;
- signal register_trans_out_s : std_logic;
+ signal register_trans_out_s : std_logic_vector(1 downto 0);
signal register_trans_wr_s : std_logic;
-
+ signal register_cycle_in_s : std_logic_vector(cycle_cnt_width_c-1 downto 0);
+ signal register_cycle_out_s : std_logic_vector(cycle_cnt_width_c-1 downto 0);
+ signal register_cycle_wr_s : std_logic;
+ signal wdog_trans_in_s : std_logic;
+ signal wdog_trans_wr_s : std_logic;
+ --
+ signal register_recv_in_s : std_logic;
+ signal register_recv_out_s : std_logic_vector(1 downto 0);
+ signal register_recv_wr_s : std_logic;
+ signal rx_done_s : std_logic;
+ signal rx_done_ratio_s : std_logic_vector(rx_done_div_width_c-1 downto 0);
+ signal rx_done_ratio_r : std_logic_vector(rx_done_div_width_c-1 downto 0);
+ signal rx_done_ratio_wr_s : std_logic;
+ signal rx_done_cnt_r : natural range 0 to (2**rx_done_cnt_width_c - 1);
begin
master_transmitter: lxmaster_transmitter
+ generic map
+ (
+ cycle_cnt_width_g => cycle_cnt_width_c
+ )
port map
(
clk_i => clk_i,
register_i => register_trans_in_s,
register_o => register_trans_out_s,
register_we_i => register_trans_wr_s,
+ -- Cycle period
+ cycle_reg_i => register_cycle_in_s,
+ cycle_reg_o => register_cycle_out_s,
+ cycle_reg_we_i => register_cycle_wr_s,
+ -- Watchdog
+ wdog_i => wdog_trans_in_s,
+ wdog_we_i => wdog_trans_wr_s,
-- BRAM
mem_clk_i => clk_i,
mem_en_i => mem_trans_en_s,
mem_data_o => mem_trans_data_s
);
+master_receiver: lxmaster_receiver
+ port map
+ (
+ clk_i => clk_i,
+ reset_i => reset_s,
+ -- Receiver serial data
+ clock_i => clock_i,
+ miso_i => miso_i,
+ sync_i => sync_i,
+ -- Receive done pulse
+ rx_done_o => rx_done_s,
+ -- Register
+ register_i => register_recv_in_s,
+ register_o => register_recv_out_s,
+ register_we_i => register_recv_wr_s,
+ -- BRAM
+ mem_clk_i => clk_i,
+ mem_en_i => mem_recv_en_s,
+ mem_we_i => mem_recv_bls_s,
+ mem_addr_i => mem_recv_addr_s,
+ mem_data_i => data_i,
+ mem_data_o => mem_recv_data_s
+ );
+
+rx_done_divider : cnt_div
+ generic map (
+ cnt_width_g => rx_done_div_width_c
+ )
+ port map
+ (
+ clk_i => clk_i,
+ en_i => rx_done_s,
+ reset_i => reset_s,
+ ratio_i => rx_done_ratio_r,
+ q_out_o => rx_done_o
+ );
reset_s <= reset_reg_r or reset_i;
+
wire_in:
- process(next_ce_i, ce_s, reset_reg_r, bls_i, address_i, mem_trans_data_s, data_i, register_trans_out_s)
+ process(ce_i, ce_r, reset_reg_r, bls_i, address_i, mem_trans_data_s,
+ mem_recv_data_s, data_i, register_trans_out_s, register_recv_out_s,
+ register_cycle_out_s, rx_done_ratio_r, rx_done_cnt_r)
begin
mem_trans_en_s <= '0';
mem_trans_out_s <= '0';
mem_trans_bls_s <= (others => '0');
mem_trans_addr_s <= (others => '0');
- state_o_s <= '0';
- register_trans_wr_s <= '0';
+ mem_recv_en_s <= '0';
+ mem_recv_out_s <= '0';
+ mem_recv_bls_s <= (others => '0');
+ mem_recv_addr_s <= (others => '0');
+ state_o_s <= (others => '0');
reset_reg_s <= '0';
reset_reg_wr_s <= '0';
register_trans_in_s <= '0';
+ register_trans_wr_s <= '0';
+ register_cycle_in_s <= (others => '0');
+ register_cycle_wr_s <= '0';
+ register_recv_in_s <= '0';
+ register_recv_wr_s <= '0';
+ wdog_trans_in_s <= '0';
+ wdog_trans_wr_s <= '0';
+ rx_done_ratio_wr_s <= '0';
+ rx_done_ratio_s <= rx_done_ratio_r;
-- Incoming bus request
- if next_ce_i = '1' then
+ if ce_i = '1' then
-- Mapping:
-- 00 & xxxxxxxx - LX Master transmitter BRAM
-- 01 & xxxxxxxx - LX Master receiver BRAM
-- 10 & 00000000 - LX Master reset
-- 10 & 00000001 - LX Master transmitter register
- -- 10 & 00000010 - LX Master receiver register
+ -- 10 & 00000010 - LX Master watchdog
+ -- 10 & 00000011 - LX Master cycle period register
+ -- 10 & 00000100 - LX Master receiver control register
if address_i(10 downto 9) = "00" then
mem_trans_addr_s <= address_i(8 downto 0);
mem_trans_bls_s <= bls_i;
mem_trans_out_s <= '1';
+ elsif address_i(10 downto 9) = "01" then
+
+ mem_recv_addr_s <= address_i(8 downto 0);
+ mem_recv_en_s <= '1';
+ mem_recv_bls_s <= bls_i;
+ mem_recv_out_s <= '1';
+
else
- if address_i(8 downto 1) = "00000000" then
+ if address_i(8 downto 3) = "000000" then
- if address_i(0) = '0' then
+ if address_i(2 downto 0) = "000" then
-- LX Master reset
if bls_i(0) = '1' then
reset_reg_s <= data_i(0);
reset_reg_wr_s <= '1';
else
-- Ugh, hack :-)
- state_o_s <= reset_reg_r;
+ state_o_s(0) <= reset_reg_r;
+ state_o_s(1) <= '0';
+ state_o_s(15 downto 2) <= (others => '0');
end if;
- else
+ elsif address_i(2 downto 0) = "001" then
-- LX Master register
if bls_i(0) = '1' then
register_trans_in_s <= data_i(0);
register_trans_wr_s <= '1';
else
- state_o_s <= register_trans_out_s;
+ state_o_s(1 downto 0) <= register_trans_out_s;
+ state_o_s(15 downto 2) <= (others => '0');
+ end if;
+ elsif address_i(2 downto 0) = "010" then
+ if bls_i(0) = '1' then
+ wdog_trans_in_s <= data_i(0);
+ wdog_trans_wr_s <= '1';
+ end if;
+ elsif address_i(2 downto 0) = "011" then
+ -- LX Master period register
+ if bls_i(0) = '1' then
+ register_cycle_in_s <= data_i(cycle_cnt_width_c-1 downto 0);
+ register_cycle_wr_s <= '1';
+ else
+ state_o_s <= (15 downto cycle_cnt_width_c => '0') &
+ register_cycle_out_s;
+ end if;
+ elsif address_i(2 downto 0) = "100" then
+ if bls_i(0) = '1' then
+ register_recv_in_s <= data_i(0);
+ register_recv_wr_s <= '1';
+ else
+ state_o_s(1 downto 0) <= register_recv_out_s;
+ state_o_s(15 downto 2) <= (others => '0');
+ end if;
+ elsif address_i(2 downto 0) = "101" then
+ -- LX Master receiver done divisor
+ if bls_i(0) = '1' then
+ rx_done_ratio_s <= data_i(rx_done_div_width_c + 8 - 1 downto 8);
+ rx_done_ratio_wr_s <= '1';
+ else
+ state_o_s(rx_done_cnt_width_c - 1 downto 0) <=
+ std_logic_vector(to_unsigned(rx_done_cnt_r, rx_done_cnt_width_c));
+ state_o_s(7 downto rx_done_cnt_width_c) <= (others => '0');
+ state_o_s(rx_done_div_width_c + 8 - 1 downto 8) <= rx_done_ratio_r;
+ state_o_s(15 downto rx_done_div_width_c + 8) <= (others => '0');
end if;
end if;
end process;
wire_out:
- process(ce_s, mem_trans_data_s, mem_trans_out_r, state_o_r)
+ process(ce_r, mem_trans_data_s, mem_trans_out_r,
+ mem_recv_data_s, mem_recv_out_r, state_o_r)
begin
data_o <= (others => '0');
- if ce_s = '1' then
+ if ce_r = '1' then
if mem_trans_out_r = '1' then
- data_o <= mem_trans_data_s;
+ data_o <= mem_trans_data_s;
+ elsif mem_recv_out_r = '1' then
+ data_o <= mem_recv_data_s;
else
- data_o(0) <= state_o_r;
+ data_o <= state_o_r;
end if;
end if;
process
begin
wait until clk_i'event and clk_i= '1';
- ce_s <= next_ce_i;
+ ce_r <= ce_i;
mem_trans_out_r <= mem_trans_out_s;
+ mem_recv_out_r <= mem_recv_out_s;
state_o_r <= state_o_s;
if reset_i = '1' then
- reset_reg_r <= '1';
+ reset_reg_r <= '1';
elsif reset_reg_wr_s = '1' then
- reset_reg_r <= reset_reg_s;
+ reset_reg_r <= reset_reg_s;
+ end if;
+
+ if reset_i = '1' then
+ rx_done_ratio_r <= ( 0 => '1', others => '0');
+ elsif rx_done_ratio_wr_s = '1' then
+ rx_done_ratio_r <= rx_done_ratio_s;
+ end if;
+
+ if reset_i = '1' then
+ rx_done_cnt_r <= 0;
+ elsif rx_done_s = '1' then
+ rx_done_cnt_r <= rx_done_cnt_r + 1;
end if;
end process;