📄 ddrsp16a.vhd
字号:
ba := genmux(r.cfg.bsize, haddr(29 downto 22)) & genmux(r.cfg.bsize, haddr(28 downto 21));-- generate chip select adec := genmux(r.cfg.bsize, haddr(30 downto 23)); rams := adec & not adec;-- sdram access FSM if r.trfc /= "000" then v.trfc := r.trfc - 1; end if; case r.sdstate is when sidle => if (startsd = '1') and (r.cfg.command = "000") and (r.cmstate = midle) and (r.istate = finish) then v.address := raddr; v.ba := ba; if ra.acc.hio = '0' then v.sdcsn := not rams(1 downto 0); v.rasn := '0'; v.sdstate := act1; else v.sdstate := ioreg1; end if; end if; v.waddr := ra.acc.haddr(7 downto 2); when act1 => v.rasn := '1'; v.trfc := r.cfg.trfc; if r.cfg.trcd = '1' then v.sdstate := act2; else v.sdstate := act3; v.hready := ra.acc.hwrite; end if; v.waddr := ra.acc.haddr(7 downto 2); when act2 => v.sdstate := act3; v.hready := ra.acc.hwrite; when act3 => v.casn := '0'; v.address := ra.acc.haddr(13 downto 11) & '0' & ra.acc.haddr(10 downto 2) & '0'; v.dqm := dqm; if ra.acc.hwrite = '1' then v.waddr := r.waddr + 1; v.sdstate := wr1; v.sdwen := '0'; v.bdrive := '0'; v.qdrive := '1'; if (r.waddr /= ra.raddr) then v.hready := '1'; end if; else v.sdstate := rd1; end if; when wr1 => v.sdwen := '1'; v.casn := '1'; v.qdrive := '1'; v.waddr := r.waddr + 1; v.address(8 downto 3) := r.waddr; if (r.waddr <= ra.raddr) and (r.waddr /= "000000") and (r.hready = '1') then v.hready := '1'; if (r.hready = '1') and (r.waddr(1 downto 0) = "00") then v.sdwen := '0'; v.casn := '0'; end if; else v.sdstate := wr2; v.dqm := (others => '1'); --v.bdrive := '1'; v.startsdold := r.startsd; end if; when wr2 => v.sdstate := wr3; v.qdrive := '1'; when wr3 => v.sdstate := wr4a; v.qdrive := '1'; when wr4a => v.bdrive := '1'; v.rasn := '0'; v.sdwen := '0'; v.sdstate := wr4; v.qdrive := '1'; when wr4 => v.sdcsn := "11"; v.rasn := '1'; v.sdwen := '1'; v.qdrive := '0'; v.sdstate := wr5; when wr5 => v.sdstate := sidle; when rd1 => v.casn := '1'; v.sdstate := rd7; if ra.acc.haddr(4 downto 2) = "011" then v.casn := '0'; v.burst := '1'; v.address(5 downto 3) := "100"; end if; when rd7 => v.casn := '1'; v.sdstate := rd2; if ra.acc.haddr(4 downto 2) = "010" then v.casn := '0'; v.burst := '1'; v.address(5 downto 3) := "100"; end if; when rd2 => v.casn := '1'; v.sdstate := rd3; if ra.acc.haddr(4 downto 2) = "001" then v.casn := '0'; v.burst := '1'; v.address(5 downto 3) := "100"; end if; when rd3 => if fast = 0 then v.startsdold := r.startsd; end if; v.sdstate := rd4; v.hready := '1'; v.casn := '1'; if r.sdwen = '0' then v.rasn := '1'; v.sdwen := '1'; v.sdcsn := "11"; v.dqm := (others => '1'); elsif ra.acc.haddr(4 downto 2) = "000" then v.casn := '0'; v.burst := '1'; v.address(5) := '1'; v.waddr := v.address(8 downto 3); end if; if v.hready = '1' then v.waddr := r.waddr + 1; end if; when rd4 => v.hready := '1'; v.casn := '1'; if (r.sdcsn /= "11") and (r.waddr(1 downto 0) = "11") and (r.burst = '1') then v.burst := '0'; elsif (r.sdcsn = "11") or (r.waddr(1 downto 0) = "11") then v.dqm := (others => '1'); v.burst := '0'; if fast /= 0 then v.startsdold := r.startsd; end if; if (r.sdcsn /= "11") then v.rasn := '0'; v.sdwen := '0'; v.sdstate := rd5; else if r.cfg.trp = '1' then v.sdstate := rd6; else v.sdstate := sidle; end if; end if; end if; if v.hready = '1' then v.waddr := r.waddr + 1; end if; when rd5 => if r.cfg.trp = '1' then v.sdstate := rd6; else v.sdstate := sidle; end if; v.sdcsn := (others => '1'); v.rasn := '1'; v.sdwen := '1'; v.dqm := (others => '1'); when rd6 => v.sdstate := sidle; v.dqm := (others => '1'); v.sdcsn := (others => '1'); v.rasn := '1'; v.sdwen := '1'; when ioreg1 => readdata := regsd; v.sdstate := ioreg2; if ra.acc.hwrite = '0' then v.hready := '1'; end if; when ioreg2 => readdata := regsd; v.sdstate := sidle; writecfg := ra.acc.hwrite; v.startsdold := r.startsd; when others => v.sdstate := sidle; end case;-- sdram commands case r.cmstate is when midle => if r.sdstate = sidle then case r.cfg.command is when CMD_PRE => -- precharge v.sdcsn := (others => '0'); v.rasn := '0'; v.sdwen := '0'; v.address(12) := '1'; v.cmstate := active; when CMD_REF => -- auto-refresh v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0'; v.cmstate := active; when CMD_EMR => -- load-ext-mode-reg v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0'; v.sdwen := '0'; v.cmstate := active; v.ba := "01"; v.address := "00000000000000"; when CMD_LMR => -- load-mode-reg v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0'; v.sdwen := '0'; v.cmstate := active; v.ba := "00"; v.address := "00000" & r.cfg.dllrst & "0" & "01" & "00011"; when others => null; end case; end if; when active => v.sdcsn := (others => '1'); v.rasn := '1'; v.casn := '1'; v.sdwen := '1'; v.cfg.command := "000"; v.cmstate := leadout; v.trfc := r.cfg.trfc; when others => if r.trfc = "000" then v.cmstate := midle; end if; end case;-- sdram init case r.istate is when iidle => if r.cfg.renable = '1' then v.cfg.cke := '1'; v.cfg.dllrst := '1'; if r.cfg.cke = '1' then v.istate := pre; v.cfg.command := CMD_PRE; end if; end if; when pre => if r.cfg.command = "000" then v.cfg.command := "11" & r.cfg.dllrst; -- CMD_LMR/CMD_EMR if r.cfg.dllrst = '1' then v.istate := emode; else v.istate := lmode; end if; end if; when emode => if r.cfg.command = "000" then v.istate := lmode; v.cfg.command := CMD_LMR; end if; when lmode => if r.cfg.command = "000" then if r.cfg.dllrst = '1' then if r.refresh(9 downto 8) = "00" then -- > 200 clocks delay v.cfg.command := CMD_PRE; v.istate := ref1; end if; else v.istate := finish; --v.cfg.command := CMD_LMR; v.cfg.refon := '1'; v.cfg.renable := '0'; end if; end if; when ref1 => if r.cfg.command = "000" then v.cfg.command := CMD_REF; v.cfg.dllrst := '0'; v.istate := ref2; end if; when ref2 => if r.cfg.command = "000" then v.cfg.command := CMD_REF; v.istate := pre; end if; when others => if r.cfg.renable = '1' then v.istate := iidle; v.cfg.dllrst := '1'; end if; end case;-- second part of main fsm case r.mstate is when active => if v.hready = '1' then v.mstate := midle; end if; when others => null; end case;-- sdram refresh counter if ((r.cfg.refon = '1') and (r.istate = finish)) or (r.cfg.dllrst = '1') then v.refresh := r.refresh - 1; if (v.refresh(11) and not r.refresh(11)) = '1' then v.refresh := r.cfg.refresh; if r.cfg.dllrst = '0' then v.cfg.command := "100"; end if; end if; end if;-- AHB register access if (ra.acc.hio and ra.acc.hwrite and writecfg) = '1' then v.cfg.refresh := wdata(11 downto 0); v.cfg.cke := wdata(15); v.cfg.renable := wdata(16); v.cfg.dllrst := wdata(17); v.cfg.command := wdata(20 downto 18); v.cfg.csize := wdata(22 downto 21); v.cfg.bsize := wdata(25 downto 23); v.cfg.trcd := wdata(26); v.cfg.trfc := wdata(29 downto 27); v.cfg.trp := wdata(30); v.cfg.refon := wdata(31); end if; v.nbdrive := not v.bdrive; if oepol = 1 then bdrive := r.nbdrive; vbdrive := (others => v.nbdrive); else bdrive := r.bdrive; vbdrive := (others => v.bdrive);end if; -- reset if rst = '0' then v.sdstate := sidle; v.mstate := midle; v.istate := finish; v.cmstate := midle; v.cfg.command := "000"; v.cfg.csize := conv_std_logic_vector(col-9, 2); v.cfg.bsize := conv_std_logic_vector(log2(Mbyte/8), 3); if MHz > 100 then v.cfg.trcd := '1'; else v.cfg.trcd := '0'; end if; v.cfg.refon := '0'; v.cfg.trfc := conv_std_logic_vector(75*MHz/1000-2, 3); v.cfg.refresh := conv_std_logic_vector(7800*MHz/1000, 12); v.refresh := (others => '0'); if pwron = 1 then v.cfg.renable := '1'; else v.cfg.renable := '0'; end if; if MHz > 100 then v.cfg.trp := '1'; else v.cfg.trp := '0'; end if; v.dqm := (others => '1'); v.sdwen := '1'; v.rasn := '1'; v.casn := '1'; v.hready := '0'; v.startsd := '0'; v.startsdold := '0'; v.cfg.dllrst := '0'; v.cfg.cke := '0'; end if; ri <= v; ribdrive <= vbdrive; rwdata <= readdata; end process; sdo.sdcke <= (others => r.cfg.cke); ahbso.hconfig <= hconfig; ahbso.hirq <= (others => '0'); ahbso.hindex <= hindex; ahbregs : process(clk_ahb) begin if rising_edge(clk_ahb) then ra <= rai; end if; end process; ddrregs : process(clk_ddr, rst) begin if rising_edge(clk_ddr) then r <= ri; rbdrive <= ribdrive; end if; if (rst = '0') then r.sdcsn <= (others => '1'); r.bdrive <= '1'; r.nbdrive <= '0'; if oepol = 0 then rbdrive <= (others => '1'); else rbdrive <= (others => '0'); end if; r.cfg.cke <= '0'; end if; end process; ddr_read_regs : process(clkread) begin if rising_edge(clkread) then rwrite <= ri.hready; waddr2 <= r.waddr; end if; end process; sdo.address <= '0' & ri.address; sdo.ba <= ri.ba; sdo.bdrive <= r.nbdrive when oepol = 1 else r.bdrive; sdo.qdrive <= not (ri.qdrive or r.nbdrive); sdo.vbdrive <= rbdrive; sdo.sdcsn <= ri.sdcsn; sdo.sdwen <= ri.sdwen; sdo.dqm <= "111111111111" & r.dqm; sdo.rasn <= ri.rasn; sdo.casn <= ri.casn; sdo.data <= zero32 & zero32 & zero32 & wdata; read_buff : syncram_2p generic map (tech => memtech, abits => 6, dbits => 32, sepclk => 1, wrfst => 0) port map ( rclk => clk_ahb, renable => vcc, raddress => rai.raddr, dataout => rdata, wclk => clk_ddr, write => ri.hready,-- dataout => rdata, wclk => clkread, write => rwrite, waddress => r.waddr, datain => rwdata);-- waddress => waddr2, datain => rwdata); write_buff : syncram_2p generic map (tech => memtech, abits => 6, dbits => 32, sepclk => 1, wrfst => 0) port map ( rclk => clk_ddr, renable => vcc, raddress => r.waddr, dataout => wdata, wclk => clk_ahb, write => ra.write, waddress => ra.haddr(7 downto 2), datain => ahbsi.hwdata);-- pragma translate_off bootmsg : report_version generic map ( msg1 => "ddrsp" & tost(hindex) & ": 16-bit DDR266 controller rev " & tost(REVISION) & ", " & tost(Mbyte) & " Mbyte, " & tost(MHz) & " MHz DDR clock");-- pragma translate_onend;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -