📄 ahb_slv.vhd
字号:
------------------------------------------------------------------------------- -- NON SEQUENCIAL, start of new burst if (csi.ahbsi.htrans = HTRANS_NONSEQ or v.new_burst = '1') then v.pre_read_valid := '0'; -- Determine how many words that is valid until DRRMEM -- will wrap within block case csi_synced.burstlength is when 2 => v.blockburstlength := csi_synced.burstlength - conv_integer(v.rwadrbuffer(0)); when 4 => v.blockburstlength := csi_synced.burstlength - conv_integer(v.rwadrbuffer(1 downto 0)); when 8 => v.blockburstlength := csi_synced.burstlength - conv_integer(v.rwadrbuffer(2 downto 0)); when others => null; end case; -- Commandbuffer full or AHB interface locked if next_rw_cmd_valid = csi_synced.rw_cmd_done or csi_synced.locked = '1' then v.hresp := HRESP_RETRY; v.hready := '0'; v.prev_retry := '1'; -- Put new command into command buffer else v.sync2_adr := next_rw_cmd_valid; --------------------------------------------------------------------------------- Read (non-seq) if csi.ahbsi.hwrite = '0' then v.hready := '0'; v.readcounter := 0; v.use_read_buffer := next_rw_cmd_valid; v.rw_cmd_valid := next_rw_cmd_valid; v.w_data_valid := next_rw_cmd_valid; -- keep in phase for read v.sync2_wdata := '0' & v.rwadrbuffer; v.sync2_write := '1'; -- Wait one cycle (maybe write before) v.sync_busy_adr := next_rw_cmd_valid & "00"; v.sync_busy := '1'; v.doRead := '0'; -- Predict (if space in buffer and option choosen) next read next_rw_cmd_valid := next_rw_cmd_valid +1; if next_rw_cmd_valid /= csi_synced.rw_cmd_done and csi_synced.r_predict = '1' then v.pre_read_buffer := next_rw_cmd_valid; v.pre_read_adr := v.rwadrbuffer + v.blockburstlength; v.pre_read_valid := '1'; v.rw_cmd_valid := next_rw_cmd_valid; v.w_data_valid := next_rw_cmd_valid; -- keep in phase -- Address cannot be saved due to syncram busy, write in -- next cycle v.sync2_busy := '1'; end if; --------------------------------------------------------------------------------- Write (non-seq) elsif csi_synced.w_prot = '0' then v.pre_read_valid := '0'; v.w_data_valid := v.rw_cmd_valid; v.rw_cmd_valid := next_rw_cmd_valid; v.writecounter := 0; v.use_write_buffer := next_rw_cmd_valid; v.sync2_wdata := '1' & v.rwadrbuffer; v.sync2_write := '1'; v.doWrite := '1'; v.hresp := HRESP_OKAY; v.hready := '1'; -- Write protection error else assert false report "Write when write protection enabled" severity warning; v.hresp := HRESP_ERROR; v.hready := '0'; v.prev_error := '1'; end if; -- write end if; -- cmdbuffer not full end if; -- non seq transfer end if; -- seq or non seq -- Slave not selected else v.w_data_valid := v.rw_cmd_valid; v.hready := '1'; v.hresp := HRESP_OKAY; end if; -- Always set HRDATA (to improve timing) if conv_std_logic_vector(v.readcounter,4)(0) = '0' then -- Even word v.read_data((dqsize-1) downto 0) := DSRAM_o.dataout1((dqsize-1) downto 0); else -- Odd word v.read_data((dqsize-1) downto 0) := DSRAM_o.dataout1((2*dqsize)-1 downto dqsize); end if; --Read data from syncram for i in 0 to ahbdata-1 loop if i >= v.ahbstartp*8 and i < (v.ahbstartp+v.burst_hsize)*8 then v.cur_hrdata(i) := v.read_data(i+(v.startp-v.ahbstartp)*8); end if; end loop; -- Calculate for next clk cycle -- If read cmd, dont try to read from syncram since maybe write before if v.sync_busy = '1' then v.cur_hready := '0'; v.cur_hresp := HRESP_OKAY; -- Read data is avalible elsif (csi_synced.rw_cmd_done = v.use_read_buffer or (csi_synced.rw_cmd_done = v.pre_read_buffer and v.pre_read_valid = '1')) and v.doRead = '1' then -- Set address for next read v.readcounter := v.readcounter +1; if v.readcounter = v.blockburstlength then v.sync_adr := (v.use_read_buffer+1) & "00"; else v.sync_adr := v.use_read_buffer & conv_std_logic_vector(v.readcounter,3)(2 downto 1); end if; v.doRead := '0'; v.cur_hready := '1'; v.cur_hresp := HRESP_OKAY; -- Waiting for read data elsif v.doRead = '1' then v.cur_hready := '0'; v.cur_hresp := HRESP_OKAY; else v.cur_hready := v.hready; v.cur_hresp := v.hresp; end if;--------------------------------------------------------------------------------- Reset if rst = '0' then v.readcounter := 0; v.writecounter := 0; v.blockburstlength:= 0; v.hready := '1'; v.hresp := HRESP_OKAY; v.rwadrbuffer := (others => '0'); v.use_read_buffer := (others => '1'); v.pre_read_buffer := (others => '1'); v.pre_read_adr := (others => '0'); v.pre_read_valid := '0'; v.use_write_buffer:= (others => '1'); v.rw_cmd_valid := (others => '1'); v.w_data_valid := (others => '1'); v.sync_adr := (others => '0'); v.sync_wdata := (others => '0'); v.sync_write := '0'; v.sync_busy := '0'; v.sync_busy_adr := (others => '0'); v.sync2_adr := (others => '0'); v.sync2_wdata := (others => '0'); v.sync2_write := '0'; v.sync2_busy := '0'; v.doRead := '0'; v.doWrite := '0'; v.new_burst := '0'; v.startp := 0; v.ahbstartp := 0; v.even_odd_write := 0; v.burst_hsize := 1; v.offset := "000"; v.ahboffset := "000"; v.read_data := (others => '0'); v.cur_hready := '0'; v.cur_hresp := HRESP_OKAY; v.prev_retry := '0'; v.prev_error := '0'; end if;--------------------------------------------------------------------------------- Set output signals ahbri <= v; cso.ahbso.hsplit <= (others => '0'); cso.ahbso.hcache <= '1'; cso.ahbso.hirq <= (others => '0'); cso.ahbso.hindex <= hindex; DSRAM_i.address1 <= v.sync_adr; DSRAM_i.datain1 <= v.sync_wdata; DSRAM_i.write1 <= v.sync_write; ASRAM_i.waddress <= v.sync2_adr; ASRAM_i.datain <= v.sync2_wdata; ASRAM_i.write <= v.sync2_write; end process;------------------------------------------------------------------------------- -- Purely combinatorial (no process) cso.ahbso.hconfig <= HCONFIG; DSRAM_i.address2 <= csi.dsramsi.address2; DSRAM_i.datain2 <= csi.dsramsi.datain2; DSRAM_i.write2 <= csi.dsramsi.write2; ASRAM_i.raddress <= csi.asramsi.raddress; cso.asramso <= ASRAM_o; cso.dsramso <= DSRAM_o;--------------------------------------------------------------------------------- AMBA AHB control clocked register ahbclk : process(hclk) begin if rising_edge(hclk) then ahbr <= ahbri; -- Registred outputs cso.rw_cmd_valid <= ahbri.rw_cmd_valid; cso.w_data_valid <= ahbri.w_data_valid; cso.burst_dm <= ahbri.burst_dm; cso.ahbso.hrdata <= ahbri.cur_hrdata; cso.ahbso.hresp <= ahbri.cur_hresp; cso.ahbso.hready <= ahbri.cur_hready; end if; end process;-- Register for incoming signals if separete clock domains sept : if sepclk = 1 generate sepp : process(hclk) begin if rising_edge(hclk) then csi_synced.burstlength <= csi.burstlength; csi_synced.r_predict <= csi.r_predict; csi_synced.w_prot <= csi.w_prot; csi_synced.locked <= csi.locked; csi_synced.rw_cmd_done <= csi.rw_cmd_done; end if; end process; end generate; sepf : if sepclk = 0 generate csi_synced.burstlength <= csi.burstlength; csi_synced.r_predict <= csi.r_predict; csi_synced.w_prot <= csi.w_prot; csi_synced.locked <= csi.locked; -- This sync below required since the current used syncram cannot write -- and read from the same location in the same cycle sepp : process(hclk) begin if rising_edge(hclk) then csi_synced.rw_cmd_done <= csi.rw_cmd_done; end if; end process; end generate;--------------------------------------------------------------------------------- SyncRAM-- Data syncram S0: syncram_dp generic map( tech => tech, abits => bufferadr, dbits => 2*(dqsize+dmsize)) port map( clk1 => hclk, address1 => DSRAM_i.address1, datain1 => DSRAM_i.datain1(2*(dqsize+dmsize)-1 downto 0), dataout1 => DSRAM_o.dataout1(2*(dqsize+dmsize)-1 downto 0), enable1 => vcc, write1 => DSRAM_i.write1, clk2 => clk0, address2 => DSRAM_i.address2, datain2 => DSRAM_i.datain2(2*(dqsize+dmsize)-1 downto 0), dataout2 => DSRAM_o.dataout2(2*(dqsize+dmsize)-1 downto 0), enable2 => vcc, write2 => DSRAM_i.write2);-- Address syncram S1: syncram_2p generic map( tech => tech*0, abits => log2(buffersize), dbits => ahbadr+1, sepclk => sepclk, wrfst => syncram_2p_write_through(tech)) port map( rclk => clk0, renable => vcc, raddress => ASRAM_i.raddress, dataout => ASRAM_o.dataout, wclk => hclk, write => ASRAM_i.write, waddress => ASRAM_i.waddress, datain => ASRAM_i.datain); -- End of AHB controller-------------------------------------------------------------------------------end rtl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -