📄 mctrl.vhd
字号:
case r.bstate is when idle => v.ws := wsnew; if r.bdrive(0) = '0' then if r.busw(1) = '1' then v.writedata := writedata; else v.writedata(31 downto 16) := writedata(31 downto 16); v.writedata8 := writedata(15 downto 0); end if; end if; if r.hsel = '1' then wprothitx := wpo.wprothit and not r.read; if (wprothitx or addrerr) = '1' then v.hresp := HRESP_ERROR; v.bstate := berr; elsif r.read = '0' then if (r.busw = "00") and (r.area /= io) and BUS8EN then v.bstate := bwrite8; elsif (r.busw = "01") and (r.area /= io) and BUS16EN then v.bstate := bwrite16; else v.bstate := bwrite; end if; v.wrn := wrn; v.writen := '0'; v.bdrive := bdrive; else if r.oen = '1' then v.ramoen := r.ramsn; v.oen := '0'; else if (r.busw = "00") and (r.area /= io) and BUS8EN then v.bstate := bread8; elsif (r.busw = "01") and (r.area /= io) and BUS16EN then v.bstate := bread16; else v.bstate := bread; end if; end if; end if; end if; when berr => v.bstate := idle; v.hsel := '0'; ready := '1'; v.hresp := HRESP_ERROR; v.ramsn := (others => '1'); v.romsn := (others => '1'); v.psel(0) := '1'; v.ramoen := (others => '1'); v.oen := '1'; v.iosn := "11"; when bread => if ((r.ws = "0000") and (r.ready = '0') and (bready = '1')) then if r.brmw = '0' then ready := '1'; v.address := ahbsi.haddr; v.echeck := '1'; end if; if (((ahbsi.hsel = '0') or (ahbsi.htrans /= HTRANS_SEQ)) or (r.hburst = HBURST_SINGLE)) then if r.brmw = '0' then v.ramsn := (others => '1'); v.romsn := (others => '1'); v.hsel := '0'; v.psel(0) := '1'; else v.echeck := '1'; end if; v.ramoen := (others => '1'); v.oen := '1'; v.iosn := "11"; v.bstate := idle; v.read := not r.hwrite; end if; end if; if r.ready = '1' then v.ws := rws; else if r.ws /= "0000" then v.ws := r.ws - 1; end if; end if; when bwrite => if (r.ws = "0000") and (bready = '1') then ready := '1'; v.wrn := (others => '1'); v.writen := '1'; v.echeck := '1'; v.ramsn := (others => '1'); v.romsn := (others => '1'); v.iosn := "11"; v.bdrive := (others => '0'); v.bstate := idle; v.hsel := '0'; v.psel(0) := '1'; end if; if r.ws /= "0000" then v.ws := r.ws - 1; end if; when bread8 => if BUS8EN then if (r.ws = "0000") and (r.ready8 = '0') then v.ready8 := '1'; v.ws := rws; v.address(1 downto 0) := r.address(1 downto 0) + 1; if (r.address(1 downto 0) = "11") then ready := '1'; v.address := ahbsi.haddr; v.echeck := '1'; if (((ahbsi.hsel = '0') or (ahbsi.htrans /= HTRANS_SEQ)) or (r.hburst = HBURST_SINGLE)) then v.ramoen := (others => '1'); v.oen := '1'; v.iosn := "11"; v.bstate := idle; v.ramsn := (others => '1'); v.romsn := (others => '1'); v.hsel := '0'; v.psel(0) := '1'; end if; end if; end if; if (r.ready8 = '1') then v.ws := rws; elsif r.ws /= "0000" then v.ws := r.ws - 1; end if; end if; when bwrite8 => if BUS8EN then if (r.ws = "0000") and (r.ready8 = '0') then v.ready8 := '1'; v.wrn := (others => '1'); v.writen := '1'; end if; if (r.ws = "0000") and ((r.address(1 downto 0) = "11") or ((r.address(1 downto 0) = "01") and (r.size = "01")) or (r.size = "00")) then ready := '1'; v.wrn := (others => '1'); v.writen := '1'; v.echeck := '1'; v.ramsn := (others => '1'); v.romsn := (others => '1'); v.iosn := "11"; v.bdrive := (others => '0'); v.bstate := idle; v.hsel := '0'; v.psel(0) := '1'; end if; if (r.ready8 = '1') then v.address(1 downto 0) := r.address(1 downto 0) + 1; v.ws := rws; -- v.writedata(31 downto 8) := r.writedata(23 downto 0); v.writedata(31 downto 16) := r.writedata(23 downto 16) & r.writedata8(15 downto 8); v.writedata8(15 downto 8) := r.writedata8(7 downto 0); v.bstate := idle; end if; if r.ws /= "0000" then v.ws := r.ws - 1; end if; end if; when bread16 => if BUS16EN then if (r.ws = "0000") and ((r.address(1) or r.brmw) = '1') and (r.ready8 = '0') then if r.brmw = '0' then ready := '1'; v.address := ahbsi.haddr; v.echeck := '1'; end if; if (((ahbsi.hsel = '0') or (ahbsi.htrans /= HTRANS_SEQ)) or (r.hburst = HBURST_SINGLE)) then if r.brmw = '0' then v.ramsn := (others => '1'); v.romsn := (others => '1'); v.hsel := '0'; v.psel(0) := '1'; end if; v.ramoen := (others => '1'); v.oen := '1'; v.iosn := "11"; v.bstate := idle; v.read := not r.hwrite; end if; end if; if (r.ws = "0000") and (r.ready8 = '0') then v.ready8 := '1'; v.ws := rws; if r.brmw = '0' then v.address(1) := not r.address(1); end if; end if; if r.ws /= "0000" then v.ws := r.ws - 1; end if; end if; when bwrite16 => if BUS16EN then if (r.ws = "0000") and ((r.address(1 downto 0) = "10") or (r.size(1) = '0')) then ready := '1'; v.wrn := (others => '1'); v.writen := '1'; v.echeck := '1'; v.ramsn := (others => '1'); v.romsn := (others => '1'); v.iosn := "11"; v.bdrive := (others => '0'); v.bstate := idle; v.hsel := '0'; v.psel(0) := '1'; end if; if (r.ws = "0000") and (r.ready8 = '0') then v.ready8 := '1'; v.wrn := (others => '1'); v.writen := '1'; end if; if (r.ready8 = '1') then v.address(1) := not r.address(1); v.ws := rws; v.writedata(31 downto 16) := r.writedata8(15 downto 0); v.bstate := idle; end if; if r.ws /= "0000" then v.ws := r.ws - 1; end if; end if; when others => end case;-- if BUSY or IDLE cycle seen, or if de-selected, return to idle state if (ahbsi.hready = '1') then if ((ahbsi.hsel = '0') or (ahbsi.htrans = HTRANS_BUSY) or (ahbsi.htrans = HTRANS_IDLE)) then v.bstate := idle; v.ramsn := (others => '1'); v.romsn := (others => '1'); v.ramoen := (others => '1'); v.oen := '1'; v.iosn := "11"; v.bdrive := (others => '0'); v.wrn := (others => '1'); v.writen := '1'; v.hsel := '0'; ready := ahbsi.hsel; v.psel(0) := '1'; elsif ahbsi.hsel = '1' then v.romsn := romsn; v.ramsn := ramsn; v.iosn := iosn & '1'; v.hsel := '1'; v.psel(0) := psel; if v.read = '1' then v.ramoen := ramsn; v.oen := leadin; end if; end if; end if;-- error checking and reporting noerror := '1'; if ((r.echeck and r.mcfg1.bexcen and not r.bexcn) = '1') then noerror := '0'; v.bstate := berr; v.hresp := HRESP_ERROR; end if;-- APB register access case apbi.paddr(3 downto 2) is when "00" => regsd(28 downto 0) := r.mcfg1.iowidth & r.mcfg1.brdyen & r.mcfg1.bexcen & "0" & r.mcfg1.iows & r.mcfg1.ioen & r.mcfg1.extlatch & "000000" & r.mcfg1.romwrite & '0' & r.mcfg1.romwidth & r.mcfg1.romwws & r.mcfg1.romrws; when "01" => regsd(12 downto 0) := r.mcfg2.rambanksz & "00" & r.mcfg2.rmw & r.mcfg2.ramwidth & r.mcfg2.ramwws & r.mcfg2.ramrws; when others => regsd := (others => '0'); end case; apbo.prdata <= regsd; if (apbi.psel and apbi.penable and apbi.pwrite) = '1' then case apbi.paddr(5 downto 2) is when "0000" => v.mcfg1.romrws := apbi.pwdata(3 downto 0); v.mcfg1.romwws := apbi.pwdata(7 downto 4); v.mcfg1.romwidth := apbi.pwdata(9 downto 8); v.mcfg1.romwrite := apbi.pwdata(11); v.mcfg1.extlatch := apbi.pwdata(18); v.mcfg1.ioen := apbi.pwdata(19); v.mcfg1.iows := apbi.pwdata(23 downto 20); v.mcfg1.bexcen := apbi.pwdata(25); v.mcfg1.brdyen := apbi.pwdata(26); v.mcfg1.iowidth := apbi.pwdata(28 downto 27); when "0001" => v.mcfg2.ramrws := apbi.pwdata(1 downto 0); v.mcfg2.ramwws := apbi.pwdata(3 downto 2); v.mcfg2.ramwidth := apbi.pwdata(5 downto 4); v.mcfg2.rmw := apbi.pwdata(6); v.mcfg2.rambanksz := apbi.pwdata(12 downto 9); when others => null; end case; end if;-- select appropriate data during reads case r.area is when rom | ram => dataout := memdata; if (r.area = rom) and (BOOTOPT /= memory) then if (r.psel(0) = '0') then v.readdata := promdata; end if; if r.psel(1) = '0' then dataout := r.readdata; end if; end if; when others => if BUS8EN and (r.busw = "00") then dataout := r.data(31 downto 24) & r.data(31 downto 24) & r.data(31 downto 24) & r.data(31 downto 24); elsif BUS16EN and (r.busw = "01") then dataout := r.data(31 downto 16) & r.data(31 downto 16); else dataout := r.data; end if; end case; v.ready := ready;-- generate memory address if RAWADDR and (r.mcfg1.extlatch = '1') then memo.address <= v.address(27 downto 0); else memo.address <= r.address(27 downto 0); end if;-- use d(15:0) as I/O ports (only usefull in 8/16-bit mode) if BUS8EN or BUS16EN then mctrlo.pioh <= r.data(15 downto 0); if (r.mcfg1.romwidth(1) or r.mcfg1.iowidth(1) or r.mcfg2.ramwidth(1)) = '0' then v.writedata(15 downto 0) := r.writedata(15 downto 0); if pioo.wrio = '1' then v.writedata(15 downto 0) := pioo.piol(31 downto 16); end if; v.wrn(3 downto 2) := "11"; v.bdrive(3 downto 2) := not pioo.piodir(17 downto 16); end if; else mctrlo.pioh <= (others => '0'); end if;-- reset if rst.syncrst = '0' then v.bstate := idle; v.read := '1'; v.wrn := "1111"; v.writen := '1'; v.mcfg1.romwrite := '0'; v.mcfg1.extlatch := '0'; v.mcfg1.ioen := '0'; v.mcfg1.brdyen := '0'; v.mcfg1.bexcen := '0'; v.hsel := '0'; if ((BOOTOPT = memory) or ((BOOTOPT = dual) and (pioo.io8lsb(4) = '0'))) then v.mcfg1.romrws := "1111"; v.mcfg1.romwws := "1111"; v.mcfg1.romwidth := pioo.io8lsb(1 downto 0); else v.mcfg2.ramrws := std_logic_vector(BRAMRWS(1 downto 0)); v.mcfg2.ramwws := std_logic_vector(BRAMWWS(1 downto 0)); v.mcfg1.romrws := "0001"; v.mcfg1.romwws := "0001"; v.mcfg1.romwidth := "11"; end if; end if;-- pragma translate_off for i in dataout'range loop --' if is_x(dataout(i)) then dataout(i) := '1'; end if; end loop;-- pragma translate_on-- drive various register inputs and external outputs ri <= v; memo.ramsn <= r.ramsn; memo.ramoen <= r.ramoen; memo.romsn <= r.romsn; memo.oen <= r.oen; memo.iosn <= r.iosn(0); memo.read <= r.read; memo.wrn <= r.wrn; memo.writen <= r.writen; memo.bdrive <= (not r.bdrive) and memi.wrn; memo.data <= r.writedata; ahbso.hrdata <= dataout; ahbso.hready <= r.ready and noerror; ahbso.hresp <= r.hresp; ahbso.hsplit <= (others => '0'); end process; stdregs : process(clk,rst) begin if rising_edge(clk) then r <= ri; end if; if rst.rawrst = '0' then r.ramsn <= (others => '1'); r.romsn <= (others => '1'); r.oen <= '1'; r.bdrive <= (others => '0'); r.iosn <= "11"; r.ramoen <= (others => '1'); end if; end process;-- optional boot-prom promgen : if (BOOTOPT /= memory) generate bprom0 : bprom port map (clk => clk, cs => r.psel(0), addr => r.address, data => promdata); end generate;end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -