You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
6.4 KiB
178 lines
6.4 KiB
library ieee; |
|
use ieee.std_logic_1164.all; |
|
use ieee.numeric_std.all; |
|
|
|
library work; |
|
use work.wishbone_types.all; |
|
|
|
entity wishbone_debug_master is |
|
port(clk : in std_ulogic; |
|
rst : in std_ulogic; |
|
|
|
-- Debug bus interface |
|
dmi_addr : in std_ulogic_vector(1 downto 0); |
|
dmi_din : in std_ulogic_vector(63 downto 0); |
|
dmi_dout : out std_ulogic_vector(63 downto 0); |
|
dmi_req : in std_ulogic; |
|
dmi_wr : in std_ulogic; |
|
dmi_ack : out std_ulogic; |
|
|
|
-- Wishbone master interface |
|
wb_out : out wishbone_master_out; |
|
wb_in : in wishbone_slave_out |
|
); |
|
end entity wishbone_debug_master; |
|
|
|
architecture behaviour of wishbone_debug_master is |
|
|
|
-- ** Register offsets definitions. All registers are 64-bit |
|
constant DBG_WB_ADDR : std_ulogic_vector(1 downto 0) := "00"; |
|
constant DBG_WB_DATA : std_ulogic_vector(1 downto 0) := "01"; |
|
constant DBG_WB_CTRL : std_ulogic_vector(1 downto 0) := "10"; |
|
constant DBG_WB_RSVD : std_ulogic_vector(1 downto 0) := "11"; |
|
|
|
-- CTRL register: |
|
-- |
|
-- bit 0..7 : SEL bits (byte enables) |
|
-- bit 8 : address auto-increment |
|
-- bit 10..9 : auto-increment value: |
|
-- 00 - +1 |
|
-- 01 - +2 |
|
-- 10 - +4 |
|
-- 11 - +8 |
|
|
|
-- ** Address and control registers and read data |
|
signal reg_addr : std_ulogic_vector(63 downto 0); |
|
signal reg_ctrl_out : std_ulogic_vector(63 downto 0); |
|
signal reg_ctrl : std_ulogic_vector(10 downto 0); |
|
signal data_latch : std_ulogic_vector(63 downto 0); |
|
|
|
type state_t is (IDLE, WB_CYCLE, DMI_WAIT); |
|
signal state : state_t; |
|
signal do_inc : std_ulogic; |
|
|
|
begin |
|
|
|
-- Hard wire unused bits to 0 |
|
reg_ctrl_out <= (63 downto 11 => '0', |
|
10 downto 0 => reg_ctrl); |
|
|
|
-- DMI read data mux |
|
with dmi_addr select dmi_dout <= |
|
reg_addr when DBG_WB_ADDR, |
|
data_latch when DBG_WB_DATA, |
|
reg_ctrl_out when DBG_WB_CTRL, |
|
(others => '0') when others; |
|
|
|
-- ADDR and CTRL register writes |
|
reg_write : process(clk) |
|
subtype autoinc_inc_t is integer range 1 to 8; |
|
function decode_autoinc(c : std_ulogic_vector(1 downto 0)) |
|
return autoinc_inc_t is |
|
begin |
|
case c is |
|
when "00" => return 1; |
|
when "01" => return 2; |
|
when "10" => return 4; |
|
when "11" => return 8; |
|
-- Below shouldn't be necessary but GHDL complains |
|
when others => return 8; |
|
end case; |
|
end function decode_autoinc; |
|
begin |
|
if rising_edge(clk) then |
|
if (rst) then |
|
reg_addr <= (others => '0'); |
|
reg_ctrl <= (others => '0'); |
|
else -- Standard register writes |
|
if do_inc = '1' then |
|
-- Address register auto-increment |
|
reg_addr <= std_ulogic_vector(unsigned(reg_addr) + |
|
decode_autoinc(reg_ctrl(10 downto 9))); |
|
elsif dmi_req and dmi_wr then |
|
if dmi_addr = DBG_WB_ADDR then |
|
reg_addr <= dmi_din; |
|
elsif dmi_addr = DBG_WB_CTRL then |
|
reg_ctrl <= dmi_din(10 downto 0); |
|
end if; |
|
end if; |
|
end if; |
|
end if; |
|
end process; |
|
|
|
-- ACK is hard wired to req for register writes. For data read/writes |
|
-- (aka commands), it's sent when the state machine got the WB ack. |
|
-- |
|
-- Note: We never set it to 1, we just pass dmi_req back when acking. |
|
-- This fullfills two purposes: |
|
-- |
|
-- * Avoids polluting the ack signal when another DMI slave is |
|
-- selected. This allows the decoder to just OR all the acks |
|
-- together rather than mux them. |
|
-- |
|
-- * Makes ack go down on the same cycle as req goes down, thus |
|
-- saving a clock cycle. This is safe because we know that |
|
-- the state machine will no longer be in DMI_WAIT state on |
|
-- the next cycle, so we won't be bouncing the signal back up. |
|
-- |
|
dmi_ack <= dmi_req when (dmi_addr /= DBG_WB_DATA or state = DMI_WAIT) else '0'; |
|
|
|
-- Some WB signals are direct wires from registers or DMI |
|
wb_out.adr <= reg_addr(wb_out.adr'left + wishbone_log2_width downto wishbone_log2_width); |
|
wb_out.dat <= dmi_din; |
|
wb_out.sel <= reg_ctrl(7 downto 0); |
|
wb_out.we <= dmi_wr; |
|
|
|
-- We always move WB cyc and stb simultaneously (no pipelining yet...) |
|
wb_out.cyc <= '1' when state = WB_CYCLE else '0'; |
|
|
|
-- Data latch. WB will take the read data away as soon as the cycle |
|
-- terminates but we must maintain it on DMI until req goes down, so |
|
-- we latch it. (Q: Should we move that latch to dmi_dtm itself ?) |
|
-- |
|
latch_reads : process(clk) |
|
begin |
|
if rising_edge(clk) then |
|
if state = WB_CYCLE and wb_in.ack = '1' and dmi_wr = '0' then |
|
data_latch <= wb_in.dat; |
|
end if; |
|
end if; |
|
end process; |
|
|
|
-- Command state machine (generate wb_cyc) |
|
wb_trigger : process(clk) |
|
begin |
|
if rising_edge(clk) then |
|
if (rst) then |
|
state <= IDLE; |
|
wb_out.stb <= '0'; |
|
do_inc <= '0'; |
|
else |
|
case state is |
|
when IDLE => |
|
if dmi_req = '1' and dmi_addr = DBG_WB_DATA then |
|
state <= WB_CYCLE; |
|
wb_out.stb <= '1'; |
|
end if; |
|
when WB_CYCLE => |
|
if wb_in.stall = '0' then |
|
wb_out.stb <= '0'; |
|
end if; |
|
if wb_in.ack then |
|
-- We shouldn't get the ack if we hadn't already cleared |
|
-- stb above but if this happen, don't leave it dangling. |
|
-- |
|
wb_out.stb <= '0'; |
|
state <= DMI_WAIT; |
|
do_inc <= reg_ctrl(8); |
|
end if; |
|
when DMI_WAIT => |
|
if dmi_req = '0' then |
|
state <= IDLE; |
|
end if; |
|
do_inc <= '0'; |
|
end case; |
|
end if; |
|
end if; |
|
end process; |
|
end architecture behaviour;
|
|
|