---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
-- DBUS master
|
-- DBUS master
|
--
|
--
|
-- Part of the LXP32 CPU
|
-- Part of the LXP32 CPU
|
--
|
--
|
-- Copyright (c) 2016 by Alex I. Kuznetsov
|
-- Copyright (c) 2016 by Alex I. Kuznetsov
|
--
|
--
|
-- Manages data bus (DBUS) access.
|
-- Manages data bus (DBUS) access.
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use ieee.numeric_std.all;
|
use ieee.numeric_std.all;
|
|
|
entity lxp32_dbus is
|
entity lxp32_dbus is
|
generic(
|
generic(
|
RMW: boolean
|
RMW: boolean
|
);
|
);
|
port(
|
port(
|
clk_i: in std_logic;
|
clk_i: in std_logic;
|
rst_i: in std_logic;
|
rst_i: in std_logic;
|
|
|
valid_i: in std_logic;
|
valid_i: in std_logic;
|
|
|
cmd_dbus_i: in std_logic;
|
cmd_dbus_i: in std_logic;
|
cmd_dbus_store_i: in std_logic;
|
cmd_dbus_store_i: in std_logic;
|
cmd_dbus_byte_i: in std_logic;
|
cmd_dbus_byte_i: in std_logic;
|
cmd_signed_i: in std_logic;
|
cmd_signed_i: in std_logic;
|
addr_i: in std_logic_vector(31 downto 0);
|
addr_i: in std_logic_vector(31 downto 0);
|
wdata_i: in std_logic_vector(31 downto 0);
|
wdata_i: in std_logic_vector(31 downto 0);
|
|
|
rdata_o: out std_logic_vector(31 downto 0);
|
rdata_o: out std_logic_vector(31 downto 0);
|
we_o: out std_logic;
|
we_o: out std_logic;
|
busy_o: out std_logic;
|
busy_o: out std_logic;
|
|
|
dbus_cyc_o: out std_logic;
|
dbus_cyc_o: out std_logic;
|
dbus_stb_o: out std_logic;
|
dbus_stb_o: out std_logic;
|
dbus_we_o: out std_logic;
|
dbus_we_o: out std_logic;
|
dbus_sel_o: out std_logic_vector(3 downto 0);
|
dbus_sel_o: out std_logic_vector(3 downto 0);
|
dbus_ack_i: in std_logic;
|
dbus_ack_i: in std_logic;
|
dbus_adr_o: out std_logic_vector(31 downto 2);
|
dbus_adr_o: out std_logic_vector(31 downto 2);
|
dbus_dat_o: out std_logic_vector(31 downto 0);
|
dbus_dat_o: out std_logic_vector(31 downto 0);
|
dbus_dat_i: in std_logic_vector(31 downto 0)
|
dbus_dat_i: in std_logic_vector(31 downto 0)
|
);
|
);
|
end entity;
|
end entity;
|
|
|
architecture rtl of lxp32_dbus is
|
architecture rtl of lxp32_dbus is
|
|
|
signal strobe: std_logic:='0';
|
signal strobe: std_logic:='0';
|
signal we_out: std_logic:='0';
|
signal we_out: std_logic:='0';
|
signal we: std_logic;
|
signal we: std_logic;
|
signal byte_mode: std_logic;
|
signal byte_mode: std_logic;
|
signal sel: std_logic_vector(3 downto 0);
|
signal sel: std_logic_vector(3 downto 0);
|
signal sig: std_logic;
|
signal sig: std_logic;
|
signal rmw_mode: std_logic;
|
signal rmw_mode: std_logic;
|
|
|
signal dbus_rdata: std_logic_vector(31 downto 0);
|
signal dbus_rdata: std_logic_vector(31 downto 0);
|
signal selected_byte: std_logic_vector(7 downto 0);
|
signal selected_byte: std_logic_vector(7 downto 0);
|
|
|
begin
|
begin
|
|
|
process (clk_i) is
|
process (clk_i) is
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
if rst_i='1' then
|
if rst_i='1' then
|
we_out<='0';
|
we_out<='0';
|
strobe<='0';
|
strobe<='0';
|
sig<='-';
|
sig<='-';
|
byte_mode<='-';
|
byte_mode<='-';
|
sel<=(others=>'-');
|
sel<=(others=>'-');
|
we<='-';
|
we<='-';
|
rmw_mode<='-';
|
rmw_mode<='-';
|
dbus_adr_o<=(others=>'-');
|
dbus_adr_o<=(others=>'-');
|
dbus_dat_o<=(others=>'-');
|
dbus_dat_o<=(others=>'-');
|
else
|
else
|
we_out<='0';
|
we_out<='0';
|
if strobe='0' then
|
if strobe='0' then
|
if valid_i='1' and cmd_dbus_i='1' then
|
if valid_i='1' and cmd_dbus_i='1' then
|
strobe<='1';
|
strobe<='1';
|
sig<=cmd_signed_i;
|
sig<=cmd_signed_i;
|
|
|
dbus_adr_o<=addr_i(31 downto 2);
|
dbus_adr_o<=addr_i(31 downto 2);
|
|
|
if cmd_dbus_byte_i='0' then
|
if cmd_dbus_byte_i='0' then
|
byte_mode<='0';
|
byte_mode<='0';
|
dbus_dat_o<=wdata_i;
|
dbus_dat_o<=wdata_i;
|
sel<="1111";
|
sel<="1111";
|
|
|
-- synthesis translate_off
|
-- synthesis translate_off
|
assert addr_i(1 downto 0)="00"
|
assert addr_i(1 downto 0)="00"
|
report "Misaligned word-granular access on data bus"
|
report "Misaligned word-granular access on data bus"
|
severity warning;
|
severity warning;
|
-- synthesis translate_on
|
-- synthesis translate_on
|
else
|
else
|
byte_mode<='1';
|
byte_mode<='1';
|
dbus_dat_o<=wdata_i(7 downto 0)&wdata_i(7 downto 0)&
|
dbus_dat_o<=wdata_i(7 downto 0)&wdata_i(7 downto 0)&
|
wdata_i(7 downto 0)&wdata_i(7 downto 0);
|
wdata_i(7 downto 0)&wdata_i(7 downto 0);
|
|
|
case addr_i(1 downto 0) is
|
case addr_i(1 downto 0) is
|
when "00" => sel<="0001";
|
when "00" => sel<="0001";
|
when "01" => sel<="0010";
|
when "01" => sel<="0010";
|
when "10" => sel<="0100";
|
when "10" => sel<="0100";
|
when "11" => sel<="1000";
|
when "11" => sel<="1000";
|
when others =>
|
when others =>
|
end case;
|
end case;
|
end if;
|
end if;
|
|
|
if not RMW then
|
if not RMW then
|
we<=cmd_dbus_store_i;
|
we<=cmd_dbus_store_i;
|
rmw_mode<='0';
|
rmw_mode<='0';
|
else
|
else
|
we<=cmd_dbus_store_i and not cmd_dbus_byte_i;
|
we<=cmd_dbus_store_i and not cmd_dbus_byte_i;
|
rmw_mode<=cmd_dbus_store_i and cmd_dbus_byte_i;
|
rmw_mode<=cmd_dbus_store_i and cmd_dbus_byte_i;
|
end if;
|
end if;
|
end if;
|
end if;
|
else
|
else
|
if dbus_ack_i='1' then
|
if dbus_ack_i='1' then
|
if rmw_mode='1' and we='0' and RMW then
|
if rmw_mode='1' and we='0' and RMW then
|
we<='1';
|
we<='1';
|
for i in sel'range loop
|
for i in sel'range loop
|
if sel(i)='0' then
|
if sel(i)='0' then
|
dbus_dat_o(i*8+7 downto i*8)<=
|
dbus_dat_o(i*8+7 downto i*8)<=
|
dbus_dat_i(i*8+7 downto i*8);
|
dbus_dat_i(i*8+7 downto i*8);
|
end if;
|
end if;
|
end loop;
|
end loop;
|
else
|
else
|
strobe<='0';
|
strobe<='0';
|
if we='0' then
|
if we='0' then
|
we_out<='1';
|
we_out<='1';
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
dbus_cyc_o<=strobe;
|
dbus_cyc_o<=strobe;
|
dbus_stb_o<=strobe;
|
dbus_stb_o<=strobe;
|
dbus_we_o<=we;
|
dbus_we_o<=we;
|
|
|
sel_no_rmw_gen: if not RMW generate
|
sel_no_rmw_gen: if not RMW generate
|
dbus_sel_o<=sel;
|
dbus_sel_o<=sel;
|
end generate;
|
end generate;
|
|
|
sel_rmw_gen: if RMW generate
|
sel_rmw_gen: if RMW generate
|
dbus_sel_o<=(others=>'1');
|
dbus_sel_o<=(others=>'1');
|
end generate;
|
end generate;
|
|
|
process (clk_i) is
|
process (clk_i) is
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
dbus_rdata<=dbus_dat_i;
|
dbus_rdata<=dbus_dat_i;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
selected_byte_gen: for i in selected_byte'range generate
|
selected_byte_gen: for i in selected_byte'range generate
|
selected_byte(i)<=(dbus_rdata(i) and sel(0)) or
|
selected_byte(i)<=(dbus_rdata(i) and sel(0)) or
|
(dbus_rdata(i+8) and sel(1)) or
|
(dbus_rdata(i+8) and sel(1)) or
|
(dbus_rdata(i+16) and sel(2)) or
|
(dbus_rdata(i+16) and sel(2)) or
|
(dbus_rdata(i+24) and sel(3));
|
(dbus_rdata(i+24) and sel(3));
|
end generate;
|
end generate;
|
|
|
rdata_o<=dbus_rdata when byte_mode='0' else
|
rdata_o<=dbus_rdata when byte_mode='0' else
|
X"000000"&selected_byte when selected_byte(selected_byte'high)='0' or sig='0' else
|
X"000000"&selected_byte when selected_byte(selected_byte'high)='0' or sig='0' else
|
X"FFFFFF"&selected_byte;
|
X"FFFFFF"&selected_byte;
|
|
|
we_o<=we_out;
|
we_o<=we_out;
|
busy_o<=strobe or we_out;
|
busy_o<=strobe or we_out;
|
|
|
end architecture;
|
end architecture;
|
|
|