URL
https://opencores.org/ocsvn/w11/w11/trunk
Subversion Repositories w11
[/] [w11/] [tags/] [w11a_V0.74/] [rtl/] [w11a/] [pdp11_dmscnt.vhd] - Rev 40
Go to most recent revision | Compare with Previous | Blame | View Log
-- $Id: pdp11_dmscnt.vhd 784 2016-07-09 22:17:01Z mueller $ -- -- Copyright 2015-2016 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de> -- -- This program is free software; you may redistribute and/or modify it under -- the terms of the GNU General Public License as published by the Free -- Software Foundation, either version 2, or at your option any later version. -- -- This program is distributed in the hope that it will be useful, but -- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- for complete details. -- ------------------------------------------------------------------------------ -- Module Name: pdp11_dmscnt - syn -- Description: pdp11: debug&moni: state counter -- -- Dependencies: memlib/ram_2swsr_rfirst_gen -- Test bench: - -- -- Target Devices: generic -- Tool versions: ise 14.7; viv 2014.4-2016.1; ghdl 0.31-0.33 -- -- Synthesized (xst): -- Date Rev ise Target flop lutl lutm slic t peri -- 2015-06-26 695 14.7 131013 xc6slx16-2 91 107 0 41 s 5.4 -- -- Revision History: - -- Date Rev Version Comment -- 2016-05-22 767 1.1.1 don't init N_REGS (vivado fix for fsm inference) -- 2015-12-28 721 1.1 use laddr/waddr; use ena instead of cnt; -- 2015-07-19 702 1.0 Initial version -- 2015-06-26 695 1.0 First draft ------------------------------------------------------------------------------ -- -- rbus registers: -- -- Addr Bits Name r/w/f Function -- -- 00 cntl r/w/- control -- 01 clr r/w/- if 1 starts mem clear -- 00 ena r/w/- if 1 enables counting -- 01 addr r/w/- memory address -- 10:02 laddr r/w/- line address (state number) -- 01:00 waddr r/-/- word address (cleared on write) -- 10 15:00 data r/-/- memory data -- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.slvtypes.all; use work.memlib.all; use work.rblib.all; use work.pdp11.all; -- ---------------------------------------------------------------------------- entity pdp11_dmscnt is -- debug&moni: state counter generic ( RB_ADDR : slv16 := slv(to_unsigned(16#0040#,16))); port ( CLK : in slbit; -- clock RESET : in slbit; -- reset RB_MREQ : in rb_mreq_type; -- rbus: request RB_SRES : out rb_sres_type; -- rbus: response DM_STAT_SE : in dm_stat_se_type; -- debug and monitor status - sequencer DM_STAT_DP : in dm_stat_dp_type; -- debug and monitor status - data path DM_STAT_CO : in dm_stat_co_type -- debug and monitor status - core ); end pdp11_dmscnt; architecture syn of pdp11_dmscnt is constant rbaddr_cntl : slv2 := "00"; -- cntl address offset constant rbaddr_addr : slv2 := "01"; -- addr address offset constant rbaddr_data : slv2 := "10"; -- data address offset constant cntl_rbf_clr : integer := 1; constant cntl_rbf_ena : integer := 0; subtype addr_rbf_mem is integer range 10 downto 2; subtype addr_rbf_word is integer range 1 downto 0; type state_type is ( s_idle, -- s_idle: rbus access or count s_mread -- s_mread: memory read ); type regs_type is record state : state_type; -- state rbsel : slbit; -- rbus select clr : slbit; -- clr flag ena0 : slbit; -- ena flag ena1 : slbit; -- ena flag (delayed) snum0 : slv9; -- snum stage 0 snum1 : slv9; -- snum stage 1 same : slbit; -- same snum flag laddr : slv9; -- line addr waddr : slv2; -- word addr scnt : slv(35 downto 0); -- scnt buffer mbuf : slv20; -- lsb memory buffer end record regs_type; constant regs_init : regs_type := ( s_idle, -- state '0', -- rbsel '0','0','0', -- clr,ena0,ena1 (others=>'0'), -- snum0 (others=>'0'), -- snum1 '0', -- same (others=>'0'), -- laddr (others=>'0'), -- waddr (others=>'0'), -- scnt (others=>'0') -- mbuf ); signal R_REGS : regs_type := regs_init; signal N_REGS : regs_type; -- don't init (vivado fix for fsm infer) signal CMEM_CEA : slbit := '0'; signal CMEM_CEB : slbit := '0'; signal CMEM_WEA : slbit := '0'; signal CMEM_WEB : slbit := '0'; signal CMEM_ADDRA : slv9 := (others=>'0'); signal CMEM_DIB : slv(35 downto 0) := (others=>'0'); signal CMEM_DOA : slv(35 downto 0) := (others=>'0'); constant cmem_data_zero : slv(35 downto 0) := (others=>'0'); begin CMEM : ram_2swsr_rfirst_gen generic map ( AWIDTH => 9, DWIDTH => 36) port map ( CLKA => CLK, CLKB => CLK, ENA => CMEM_CEA, ENB => CMEM_CEB, WEA => CMEM_WEA, WEB => CMEM_WEB, ADDRA => CMEM_ADDRA, ADDRB => R_REGS.snum1, DIA => cmem_data_zero, DIB => CMEM_DIB, DOA => CMEM_DOA, DOB => open ); proc_regs: process (CLK) begin if rising_edge(CLK) then if RESET = '1' then R_REGS <= regs_init; else R_REGS <= N_REGS; end if; end if; end process proc_regs; proc_next: process (R_REGS, RB_MREQ, DM_STAT_SE, DM_STAT_DP, DM_STAT_DP.psw, -- xst needs sub-records DM_STAT_CO, CMEM_DOA) variable r : regs_type := regs_init; variable n : regs_type := regs_init; variable irb_ack : slbit := '0'; variable irb_busy : slbit := '0'; variable irb_err : slbit := '0'; variable irb_dout : slv16 := (others=>'0'); variable irbena : slbit := '0'; variable icea : slbit := '0'; variable iwea : slbit := '0'; variable iweb : slbit := '0'; variable iaddra : slv9 := (others=>'0'); variable iscnt0 : slv(35 downto 0) := (others=>'0'); variable iscnt1 : slv(35 downto 0) := (others=>'0'); begin r := R_REGS; n := R_REGS; irb_ack := '0'; irb_busy := '0'; irb_err := '0'; irb_dout := (others=>'0'); irbena := RB_MREQ.re or RB_MREQ.we; icea := '0'; iwea := '0'; iweb := '0'; iaddra := r.snum0; -- rbus address decoder n.rbsel := '0'; if RB_MREQ.aval='1' then if RB_MREQ.addr(15 downto 2)=RB_ADDR(15 downto 2) then n.rbsel := '1'; end if; end if; case r.state is when s_idle => -- s_idle: rbus access or count ------ -- rbus transactions if r.rbsel = '1' then irb_ack := irbena; -- ack all accesses case RB_MREQ.addr(1 downto 0) is when rbaddr_cntl => -- cntl ------------------ if RB_MREQ.we = '1' then n.clr := RB_MREQ.din(cntl_rbf_clr); if RB_MREQ.din(cntl_rbf_clr) = '1' then -- if clr set n.laddr := (others=>'0'); -- reset mem addr end if; n.ena0 := RB_MREQ.din(cntl_rbf_ena); end if; when rbaddr_addr => -- addr ------------------ if RB_MREQ.we = '1' then if r.clr = '1' then -- if clr active irb_err := '1'; -- block addr writes else -- otherwise n.laddr := RB_MREQ.din(addr_rbf_mem); -- set mem addr n.waddr := (others=>'0'); -- clr word addr end if; end if; when rbaddr_data => -- data ------------------ if RB_MREQ.we = '1' then -- writes not allowed irb_err := '1'; end if; if RB_MREQ.re = '1' then if r.clr = '1' then -- if clr active irb_err := '1'; -- block data reads else -- otherwise case r.waddr is -- handle word addr when "00" => -- 1st access icea := '1'; -- enable mem read iaddra := r.laddr; -- of current line irb_busy := '1'; n.state := s_mread; when "01" => -- 2nd part n.waddr := "10"; -- inc word addr when "10" => -- 3rd part n.waddr := "00"; -- wrap to next line n.laddr := slv(unsigned(r.laddr) + 1); when others => null; end case; end if; end if; when others => -- <> -------------------- irb_err := '1'; end case; end if; when s_mread => --s_mread: memory read --------------- irb_ack := irbena; -- ack access n.waddr := "01"; -- inc word addr n.mbuf := CMEM_DOA(35 downto 16); -- capture msb part n.state := s_idle; when others => null; end case; -- rbus output driver if r.rbsel = '1' then case RB_MREQ.addr(1 downto 0) is when rbaddr_cntl => -- cntl ------------------ irb_dout(cntl_rbf_clr) := r.clr; irb_dout(cntl_rbf_ena) := r.ena0; when rbaddr_addr => -- addr ------------------ irb_dout(addr_rbf_mem) := r.laddr; irb_dout(addr_rbf_word) := r.waddr; when rbaddr_data => -- data ------------------ case r.waddr is when "00" => irb_dout := CMEM_DOA(15 downto 0); when "01" => irb_dout := r.mbuf(15 downto 0); when "10" => irb_dout(3 downto 0) := r.mbuf(19 downto 16); when others => null; end case; when others => null; end case; end if; -- latch state number -- 1 msb determined from cpu mode: 0 if kernel and 1 when user or super -- 8 lsb taken from sequencer snum n.snum0(8) := '0'; if DM_STAT_DP.psw.cmode /= c_psw_kmode then n.snum0(8) := '1'; end if; n.snum0(7 downto 0) := DM_STAT_SE.snum; n.snum1 := r.snum0; -- incrementer pipeline n.same := '0'; if r.snum0=r.snum1 and r.ena1 ='1' then -- in same state ? n.same := '1'; -- don't read mem and remember else -- otherwise icea := '1'; -- enable mem read end if; -- increment state count if r.same = '0' then -- was mem read ? iscnt0 := CMEM_DOA; -- take memory value else -- otherwise iscnt0 := r.scnt; -- use scnt reg end if; iscnt1 := slv(unsigned(iscnt0) + 1); -- increment n.scnt := iscnt1; -- and store -- finally setup memory access n.ena1 := r.ena0; if r.clr = '1' then -- mem clear action icea := '1'; iwea := '1'; iaddra := r.laddr; n.laddr := slv(unsigned(r.laddr) + 1); if r.laddr = "111111111" then n.clr := '0'; end if; elsif r.ena1 = '1' then -- state count action iweb := '1'; end if; N_REGS <= n; CMEM_CEA <= icea; CMEM_CEB <= iweb; CMEM_WEA <= iwea; CMEM_WEB <= iweb; CMEM_ADDRA <= iaddra; CMEM_DIB <= iscnt1; RB_SRES.ack <= irb_ack; RB_SRES.err <= irb_err; RB_SRES.busy <= irb_busy; RB_SRES.dout <= irb_dout; end process proc_next; end syn;
Go to most recent revision | Compare with Previous | Blame | View Log