- Added synthesis contraints
- Added ZPU processor - Optimized wb_ddr_ctrl_wb_dc* to meet timing - Added cache frontend
This commit is contained in:
@@ -11,4 +11,5 @@ run
|
||||
-sd coregen/
|
||||
-rtlview no
|
||||
-iob auto
|
||||
-keep_hierarchy soft
|
||||
-keep_hierarchy soft
|
||||
-uc constr/2d_display_engine.xcf
|
||||
22
Makefile
22
Makefile
@@ -28,14 +28,19 @@ ddr2_sdram/vhdl_bl4/example_design/rtl/vhdl_bl4_s3_dq_iob.vhd \
|
||||
src/wb_interconnect.vhd \
|
||||
src/clk_reset.vhd src/wb_ddr_ctrl.vhd src/wb_ddr_ctrl_ddrwrap.vhd \
|
||||
src/wb_ddr_ctrl_wb.vhd src/wb_ddr_ctrl_wb_dc_fsm.vhd src/wb_ddr_ctrl_wb_dc.vhd \
|
||||
src/wb_ddr_ctrl_wb_sc_fe_fsm.vhd src/wb_ddr_ctrl_wb_sc_fe.vhd \
|
||||
src/wb_ddr_ctrl_wb_sc.vhd src/vga_syncgen.vhd src/vga_pixelgen.vhd \
|
||||
src/vga_pixelreader.vhd src/vga.vhd src/cpu.vhd src/toplevel.vhd
|
||||
src/vga_pixelreader.vhd src/vga.vhd \
|
||||
zy2000/zpu_config.vhd zy2000/zpupkg.vhd zy2000/zpu_core.vhd zy2000/zpu_wb_bridge.vhd \
|
||||
zy2000/zpu_system.vhd \
|
||||
src/toplevel.vhd
|
||||
SYN_INFILES=
|
||||
PSMFILES=
|
||||
CORES=wb_ddr_ctrl_wb_from_ddr wb_ddr_ctrl_wb_to_ddr vga_pixeldata_fifo
|
||||
PRJNAME=2d_display_engine
|
||||
NGCFILE=$(PRJNAME).ngc
|
||||
XSTFILE=$(PRJNAME).xst
|
||||
XCF=constr/$(PRJNAME).xcf
|
||||
UCF=constr/$(PRJNAME).ucf constr/vhdl_bl4.ucf
|
||||
PCFFILE=$(PRJNAME).pcf
|
||||
NGDFILE=$(PRJNAME).ngd
|
||||
@@ -46,8 +51,8 @@ TWRFILE=$(PRJNAME).twr
|
||||
PRJFILE=$(PRJNAME).prj
|
||||
PART=xc3s700an-fgg484-4
|
||||
NGDOPTS=-p $(PART) -aul -aut $(addprefix -uc ,$(UCF)) -sd coregen/
|
||||
MAPOPTS=-p $(PART) -cm area
|
||||
PAROPTS=-rl high -pl high
|
||||
MAPOPTS=-p $(PART) -cm balanced -timing -ol high -logic_opt on
|
||||
PAROPTS=-ol high
|
||||
BITGENOPTS=
|
||||
TRACEOPTS=-v -u 100
|
||||
|
||||
@@ -58,7 +63,8 @@ VLOGCOMPOPTS=-d x512Mb -d sg5E -d x16 -d MAX_MEM
|
||||
|
||||
SYNALLFILES=$(COMMON_INFILES) $(SYN_INFILES)
|
||||
SIMALLFILES=$(SIM_INFILES) $(COMMON_INFILES)
|
||||
SIMALLFILESXDB=$(addprefix isim/work/,$(notdir $(SIMALLFILES:.vhd=.vdb))) \
|
||||
SIMALLFILESXDB=isim/ieee_proposed/std_logic_1164_additions.vdb \
|
||||
$(addprefix isim/work/,$(notdir $(SIMALLFILES:.vhd=.vdb))) \
|
||||
$(addprefix isim/work/,$(notdir $(SIM_INFILES_VLOG:.v=.sdb)))
|
||||
CORESVDB=$(addprefix isim/work/,$(addsuffix .vdb,$(CORES)))
|
||||
|
||||
@@ -93,7 +99,7 @@ src/wb_interconnect.vhd: src/wishbone.defines
|
||||
$(PRJFILE): Makefile
|
||||
rm -f $(PRJFILE); for i in $(SYNALLFILES); do echo "vhdl work" $$i >> $(PRJFILE); done
|
||||
|
||||
$(NGCFILE): $(SYNALLFILES) $(PRJFILE) $(XSTFILE)
|
||||
$(NGCFILE): $(SYNALLFILES) $(PRJFILE) $(XSTFILE) $(XCF)
|
||||
$(XST) -ifn $(XSTFILE)
|
||||
|
||||
$(NGDFILE): $(NGCFILE) $(UCF)
|
||||
@@ -111,9 +117,15 @@ $(BITFILE): $(NCDFILE_R) $(PCFFILE)
|
||||
$(TWRFILE): $(NCDFILE_R) $(PCFFILE)
|
||||
$(TRCE) $(TRACEOPTS) -o $(TWRFILE) $(NCDFILE_R) $(PCFFILE)
|
||||
|
||||
isim/ieee_proposed/std_logic_1164_additions.vdb: tools/std_logic_1164_additions.vhdl
|
||||
$(VHPCOMP) --work ieee_proposed $<
|
||||
|
||||
isim/work/%.vdb: src/%.vhd
|
||||
$(VHPCOMP) $<
|
||||
|
||||
isim/work/%.vdb: zy2000/%.vhd
|
||||
$(VHPCOMP) $<
|
||||
|
||||
isim/work/%.vdb: ddr2_sdram/vhdl_bl4/example_design/rtl/%.vhd
|
||||
$(VHPCOMP) $<
|
||||
|
||||
|
||||
13
constr/2d_display_engine.xcf
Normal file
13
constr/2d_display_engine.xcf
Normal file
@@ -0,0 +1,13 @@
|
||||
# Timing constraints
|
||||
NET "CLKIN_50MHZ" PERIOD = 20.0ns HIGH 40%;
|
||||
NET "CLKIN_133MHZ" PERIOD = 7.51ns HIGH 40%;
|
||||
|
||||
#MODEL wb_ddr_ctrl_ddrwrap keep_hierarchy = yes ;
|
||||
#MODEL vhdl_bl4_infrastructure_top keep_hierarchy = yes ;
|
||||
#MODEL vhdl_bl4_cal_top keep_hierarchy = yes;
|
||||
|
||||
|
||||
#BEGIN MODEL vhdl_bl4_cal_top
|
||||
# INST cal_ctl0 keep_hierarchy = yes ;
|
||||
# INST tap_dly0 keep_hierarchy = yes ;
|
||||
#END;
|
||||
@@ -1,7 +1,7 @@
|
||||
##############################################################
|
||||
#
|
||||
# Xilinx Core Generator version 14.3
|
||||
# Date: Thu Feb 28 16:17:27 2013
|
||||
# Xilinx Core Generator version 14.4
|
||||
# Date: Sat Mar 02 09:52:53 2013
|
||||
#
|
||||
##############################################################
|
||||
#
|
||||
@@ -207,7 +207,7 @@ CSET write_data_count_width=4
|
||||
CSET wuser_width=1
|
||||
# END Parameters
|
||||
# BEGIN Extra information
|
||||
MISC pkg_timestamp=2012-07-25T18:11:59Z
|
||||
MISC pkg_timestamp=2012-11-19T12:39:56Z
|
||||
# END Extra information
|
||||
GENERATE
|
||||
# CRC: cfabdd53
|
||||
# CRC: d79cc6cb
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
##############################################################
|
||||
#
|
||||
# Xilinx Core Generator version 14.3
|
||||
# Date: Thu Feb 28 16:33:31 2013
|
||||
# Xilinx Core Generator version 14.4
|
||||
# Date: Sat Mar 02 09:54:41 2013
|
||||
#
|
||||
##############################################################
|
||||
#
|
||||
@@ -207,7 +207,7 @@ CSET write_data_count_width=4
|
||||
CSET wuser_width=1
|
||||
# END Parameters
|
||||
# BEGIN Extra information
|
||||
MISC pkg_timestamp=2012-07-25T18:11:59Z
|
||||
MISC pkg_timestamp=2012-11-19T12:39:56Z
|
||||
# END Extra information
|
||||
GENERATE
|
||||
# CRC: dad99623
|
||||
# CRC: c2ee8dbb
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
create_project -force -part xc3s700an-fgg484-4 postsynth planahead
|
||||
set_property design_mode GateLvl [current_fileset]
|
||||
import_files 2d_display_engine.ngc coregen/wb_ddr_ctrl_wb_from_ddr.ngc coregen/wb_ddr_ctrl_wb_to_ddr.ngc
|
||||
import_files 2d_display_engine.ngc coregen/wb_ddr_ctrl_wb_from_ddr.ngc coregen/wb_ddr_ctrl_wb_to_ddr.ngc coregen/vga_pixeldata_fifo.ngc
|
||||
import_files -fileset constrs_1 constr/2d_display_engine.ucf constr/vhdl_bl4.ucf
|
||||
|
||||
@@ -130,23 +130,25 @@ architecture Mixed of toplevel is
|
||||
hsync : out std_ulogic);
|
||||
end component;
|
||||
|
||||
component cpu
|
||||
component zpu_system
|
||||
generic (
|
||||
burst_length : integer);
|
||||
simulate : boolean);
|
||||
port (
|
||||
clk : in std_logic;
|
||||
rst : in std_logic;
|
||||
enable_vga : out std_logic;
|
||||
cpu_wbm_i : in cpu_wbm_i_type;
|
||||
cpu_wbm_o : out cpu_wbm_o_type);
|
||||
areset : in std_logic;
|
||||
cpu_clk : in std_logic;
|
||||
enable : in std_logic;
|
||||
interrupt : in std_logic;
|
||||
zpu_status : out std_logic_vector(63 downto 0);
|
||||
zpu_wb_i : in zpu_wbm_i_type;
|
||||
zpu_wb_o : out zpu_wbm_o_type);
|
||||
end component;
|
||||
|
||||
component intercon
|
||||
port (
|
||||
vga_wbm_i : out vga_wbm_i_type;
|
||||
vga_wbm_o : in vga_wbm_o_type;
|
||||
cpu_wbm_i : out cpu_wbm_i_type;
|
||||
cpu_wbm_o : in cpu_wbm_o_type;
|
||||
zpu_wbm_i : out zpu_wbm_i_type;
|
||||
zpu_wbm_o : in zpu_wbm_o_type;
|
||||
sdram_ctrl_wbs_i : out sdram_ctrl_wbs_i_type;
|
||||
sdram_ctrl_wbs_o : in sdram_ctrl_wbs_o_type;
|
||||
clk : in std_logic;
|
||||
@@ -157,8 +159,8 @@ signal sysClk, sysRst : std_logic;
|
||||
|
||||
signal vga_wbm_i : vga_wbm_i_type;
|
||||
signal vga_wbm_o : vga_wbm_o_type;
|
||||
signal cpu_wbm_o : cpu_wbm_o_type;
|
||||
signal cpu_wbm_i : cpu_wbm_i_type;
|
||||
signal zpu_wbm_o : zpu_wbm_o_type;
|
||||
signal zpu_wbm_i : zpu_wbm_i_type;
|
||||
signal sdram_ctrl_wbs_i : sdram_ctrl_wbs_i_type;
|
||||
signal sdram_ctrl_wbs_o : sdram_ctrl_wbs_o_type;
|
||||
|
||||
@@ -203,6 +205,9 @@ ddr_ctrl0 : wb_ddr_ctrl
|
||||
wbs_o => sdram_ctrl_wbs_o
|
||||
);
|
||||
|
||||
-- disable vga core for testing
|
||||
enable_vga <= '0';
|
||||
|
||||
vga_inst: vga
|
||||
port map (
|
||||
clk_in => sysClk,
|
||||
@@ -219,22 +224,24 @@ vga_inst: vga
|
||||
vsync => vga_vsync,
|
||||
hsync => vga_hsync);
|
||||
|
||||
cpu_1: cpu
|
||||
zpu_system_inst: zpu_system
|
||||
generic map (
|
||||
burst_length => 16)
|
||||
simulate => false)
|
||||
port map (
|
||||
clk => sysClk,
|
||||
rst => sysRst,
|
||||
enable_vga => enable_vga,
|
||||
cpu_wbm_i => cpu_wbm_i,
|
||||
cpu_wbm_o => cpu_wbm_o);
|
||||
areset => sysRst,
|
||||
cpu_clk => sysClk,
|
||||
enable => '1',
|
||||
interrupt => '0',
|
||||
zpu_status => open,
|
||||
zpu_wb_i => zpu_wbm_i,
|
||||
zpu_wb_o => zpu_wbm_o);
|
||||
|
||||
intercon_1: intercon
|
||||
port map (
|
||||
vga_wbm_i => vga_wbm_i,
|
||||
vga_wbm_o => vga_wbm_o,
|
||||
cpu_wbm_i => cpu_wbm_i,
|
||||
cpu_wbm_o => cpu_wbm_o,
|
||||
zpu_wbm_i => zpu_wbm_i,
|
||||
zpu_wbm_o => zpu_wbm_o,
|
||||
sdram_ctrl_wbs_i => sdram_ctrl_wbs_i,
|
||||
sdram_ctrl_wbs_o => sdram_ctrl_wbs_o,
|
||||
clk => sysClk,
|
||||
|
||||
@@ -71,6 +71,7 @@ architecture Behavioral of wb_ddr_ctrl_wb_dc is
|
||||
component wb_ddr_ctrl_wb_dc_fsm
|
||||
port (
|
||||
ddr2_clk0 : in std_ulogic;
|
||||
ddr2_clk90 : in std_ulogic;
|
||||
ddr2_clk180 : in std_ulogic;
|
||||
ddr2_reset : in std_ulogic;
|
||||
ctrl_data_valid : in std_logic;
|
||||
@@ -113,6 +114,7 @@ begin
|
||||
wb_ddr_ctrl_wb_dc_fsm_inst: wb_ddr_ctrl_wb_dc_fsm
|
||||
port map (
|
||||
ddr2_clk0 => ddr2_clk0,
|
||||
ddr2_clk90 => ddr2_clk90,
|
||||
ddr2_clk180 => ddr2_clk180,
|
||||
ddr2_reset => ddr2_reset,
|
||||
ctrl_data_valid => ctrl_data_valid,
|
||||
|
||||
@@ -35,6 +35,7 @@ entity wb_ddr_ctrl_wb_dc_fsm is
|
||||
port (
|
||||
-- Control signals
|
||||
ddr2_clk0 : in std_ulogic;
|
||||
ddr2_clk90 : in std_ulogic;
|
||||
ddr2_clk180 : in std_ulogic;
|
||||
ddr2_reset : in std_ulogic;
|
||||
|
||||
@@ -122,6 +123,7 @@ ctrl_fsm_state : process(ddr2_clk180)
|
||||
ctrl_state <= S_IDLE;
|
||||
end if;
|
||||
when S_REQUEST_INIT =>
|
||||
fifo_pending <= '-';
|
||||
if we = '1' then
|
||||
ctrl_state <= S_WRITE1;
|
||||
else
|
||||
@@ -130,10 +132,12 @@ ctrl_fsm_state : process(ddr2_clk180)
|
||||
burst_start_adr <= row_addr;
|
||||
|
||||
when S_WRITE1 =>
|
||||
fifo_pending <= '-';
|
||||
if ctrl_cmd_ack = '1' then
|
||||
ctrl_state <= S_WRITE2;
|
||||
end if;
|
||||
when S_WRITE2 =>
|
||||
fifo_pending <= '-';
|
||||
if fifo_from_sys_valid = '0' or row_addr /= burst_start_adr or
|
||||
we = '0' or ctrl_auto_ref_req = '1' then
|
||||
-- next request incompatible with burst type, or auto refresh requested
|
||||
@@ -143,6 +147,7 @@ ctrl_fsm_state : process(ddr2_clk180)
|
||||
ctrl_state <= S_WRITE3;
|
||||
end if;
|
||||
when S_WRITE3 =>
|
||||
fifo_pending <= '-';
|
||||
ctrl_state <= S_WRITE2;
|
||||
|
||||
when S_WRITE_END1 =>
|
||||
@@ -155,14 +160,18 @@ ctrl_fsm_state : process(ddr2_clk180)
|
||||
end if;
|
||||
|
||||
when S_READ1 =>
|
||||
fifo_pending <= '-';
|
||||
if ctrl_cmd_ack = '1' then
|
||||
ctrl_state <= S_READ2;
|
||||
end if;
|
||||
when S_READ2 =>
|
||||
fifo_pending <= '-';
|
||||
ctrl_state <= S_READ3;
|
||||
when S_READ3 =>
|
||||
fifo_pending <= '-';
|
||||
ctrl_state <= S_READ4;
|
||||
when S_READ4 =>
|
||||
fifo_pending <= '-';
|
||||
if fifo_from_sys_valid = '0' or row_addr /= burst_start_adr or
|
||||
we = '1' or ctrl_auto_ref_req = '1' then
|
||||
-- next request incompatible with burst type, or auto refresh requested
|
||||
@@ -172,6 +181,7 @@ ctrl_fsm_state : process(ddr2_clk180)
|
||||
ctrl_state <= S_READ5;
|
||||
end if;
|
||||
when S_READ5 =>
|
||||
fifo_pending <= '-';
|
||||
ctrl_state <= S_READ4;
|
||||
|
||||
when S_READ_END1 =>
|
||||
@@ -200,7 +210,7 @@ ctrl_fsm_state : process(ddr2_clk180)
|
||||
|
||||
|
||||
ctrl_fsm_out : process(ctrl_state, ddr2_reset, we, ctrl_cmd_ack, fifo_from_sys_valid,
|
||||
row_addr, burst_start_adr, ctrl_auto_ref_req)
|
||||
row_addr, burst_start_adr, ctrl_auto_ref_req, fifo_pending)
|
||||
begin
|
||||
ddr_dmask_rst <= '0'; -- dmask register reset
|
||||
ddr_dmask_en <= '0'; -- dmask register enable
|
||||
@@ -240,14 +250,17 @@ ctrl_fsm_out : process(ctrl_state, ddr2_reset, we, ctrl_cmd_ack, fifo_from_sys_v
|
||||
end if;
|
||||
ctrl_command_register_d <= ctrl_command_write;
|
||||
when S_WRITE2 =>
|
||||
ddr_dmask_en <= '1';
|
||||
ddr_dout_en <= '1';
|
||||
ddr_dout_high <= '0';
|
||||
if fifo_from_sys_valid = '0' or row_addr /= burst_start_adr or
|
||||
we = '0' or ctrl_auto_ref_req = '1' then
|
||||
-- next request incompatible with burst type, or auto refresh requested
|
||||
|
||||
else
|
||||
ddr_dmask_en <= '1';
|
||||
ddr_dout_en <= '1';
|
||||
ddr_dout_high <= '0';
|
||||
--ddr_dmask_en <= '1';
|
||||
--ddr_dout_en <= '1';
|
||||
--ddr_dout_high <= '0';
|
||||
--fifo_from_sys_read_int <= '1';
|
||||
end if;
|
||||
ctrl_command_register_d <= ctrl_command_write;
|
||||
@@ -272,12 +285,13 @@ ctrl_fsm_out : process(ctrl_state, ddr2_reset, we, ctrl_cmd_ack, fifo_from_sys_v
|
||||
ctrl_command_register_d <= ctrl_command_read;
|
||||
fifo_from_sys_read_int <= '1';
|
||||
when S_READ4 =>
|
||||
ddr_address_en <= '1';
|
||||
if fifo_from_sys_valid = '0' or row_addr /= burst_start_adr or
|
||||
we = '1' or ctrl_auto_ref_req = '1' then
|
||||
-- next request incompatible with burst type, or auto refresh requested
|
||||
ctrl_burst_done_d <= '1';
|
||||
else
|
||||
ddr_address_en <= '1';
|
||||
--ddr_address_en <= '1';
|
||||
--fifo_from_sys_read_int <= '1';
|
||||
end if;
|
||||
when S_READ5 =>
|
||||
|
||||
336
src/wb_ddr_ctrl_wb_sc_fe.vhd
Normal file
336
src/wb_ddr_ctrl_wb_sc_fe.vhd
Normal file
@@ -0,0 +1,336 @@
|
||||
----------------------------------------------------------------------------------
|
||||
-- Company:
|
||||
-- Engineer:
|
||||
--
|
||||
-- Create Date: 11/06/2012 03:04:35 PM
|
||||
-- Design Name:
|
||||
-- Module Name: wb_ddr_ctrl_wb_sc_fe - Behavioral
|
||||
-- Project Name:
|
||||
-- Target Devices:
|
||||
-- Tool Versions:
|
||||
-- Description: Memory controller - system clock domain - Cache front-end -
|
||||
-- Data path
|
||||
--
|
||||
-- Dependencies:
|
||||
--
|
||||
-- Revision:
|
||||
-- Revision 0.01 - File Created
|
||||
-- Additional Comments:
|
||||
--
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
|
||||
-- Uncomment the following library declaration if using
|
||||
-- arithmetic functions with Signed or Unsigned values
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
-- Uncomment the following library declaration if instantiating
|
||||
-- any Xilinx primitives in this code.
|
||||
library UNISIM;
|
||||
use UNISIM.VComponents.all;
|
||||
|
||||
use work.intercon_package.all;
|
||||
|
||||
entity wb_ddr_ctrl_wb_sc_fe is
|
||||
generic (
|
||||
line_size : integer := 16;
|
||||
lines : integer := 64;
|
||||
assoc : integer := 2;
|
||||
line_size_ln2 : integer := 4;
|
||||
lines_ln2 : integer := 6;
|
||||
assoc_ln2 : integer := 1;
|
||||
addr_width : integer := 24
|
||||
);
|
||||
port (
|
||||
-- Wishbone slave
|
||||
clk_i : in std_logic;
|
||||
rst_i : in std_logic;
|
||||
wbs_i : in sdram_ctrl_wbs_i_type;
|
||||
wbs_o : out sdram_ctrl_wbs_o_type;
|
||||
|
||||
-- To backend
|
||||
mem_adr : out std_logic_vector(addr_width-line_size_ln2-1 downto 0);
|
||||
mem_rdrq : out std_logic;
|
||||
mem_wrrq : out std_logic;
|
||||
mem_dat_o : out std_logic_vector(31 downto 0);
|
||||
mem_ack : in std_logic;
|
||||
mem_dat_i : in std_logic_vector(31 downto 0)
|
||||
);
|
||||
end wb_ddr_ctrl_wb_sc_fe;
|
||||
|
||||
architecture Behavioral of wb_ddr_ctrl_wb_sc_fe is
|
||||
attribute ram_style : string;
|
||||
attribute priority_extract : string;
|
||||
|
||||
component wb_ddr_ctrl_wb_sc_fe_fsm
|
||||
generic (
|
||||
line_size : integer;
|
||||
lines : integer;
|
||||
assoc : integer;
|
||||
line_size_ln2 : integer;
|
||||
lines_ln2 : integer;
|
||||
assoc_ln2 : integer;
|
||||
addr_width : integer);
|
||||
port (
|
||||
clk_i : in std_logic;
|
||||
rst_i : in std_logic;
|
||||
cyc_i : in std_logic;
|
||||
stb_i : in std_logic;
|
||||
we_i : in std_logic;
|
||||
adr_tag_eq : in std_logic_vector(assoc-1 downto 0);
|
||||
eject_dirty : in std_logic;
|
||||
mem_offset : in unsigned(line_size_ln2-1 downto 0);
|
||||
ack_o : out std_logic;
|
||||
update_lru : out std_logic := '0';
|
||||
set_dirty : out std_logic := '0';
|
||||
set_valid : out std_logic := '0';
|
||||
cache_write : out std_logic := '0';
|
||||
cache_from_mem : out std_logic := '0';
|
||||
cache_to_mem : out std_logic := '0';
|
||||
mem_rdrq : out std_logic := '0';
|
||||
mem_wrrq : out std_logic := '0');
|
||||
end component;
|
||||
|
||||
-- Derived parameters
|
||||
constant tag_width : integer := addr_width-line_size_ln2-(lines_ln2-assoc_ln2);
|
||||
constant index_width : integer := lines_ln2-assoc_ln2;
|
||||
constant offset_width : integer := line_size_ln2;
|
||||
|
||||
-- Cache control signals / memory
|
||||
subtype tag_t is std_logic_vector(assoc*tag_width-1 downto 0);
|
||||
subtype lru_t is unsigned(assoc*assoc_ln2-1 downto 0);
|
||||
type cc_tag_a is array(lines/assoc-1 downto 0) of tag_t;
|
||||
type cc_lru_a is array(lines/assoc-1 downto 0) of lru_t;
|
||||
type cc_valid_a is array(lines/assoc-1 downto 0) of std_logic_vector(assoc-1 downto 0);
|
||||
type cc_dirty_a is array(lines/assoc-1 downto 0) of std_logic_vector(assoc-1 downto 0);
|
||||
signal cc_tag : cc_tag_a := (others => (others => '-'));
|
||||
signal cc_lru : cc_lru_a := (others => (others => '-'));
|
||||
signal cc_valid : cc_valid_a := (others => (others => '0'));
|
||||
signal cc_dirty : cc_dirty_a := (others => (others => '-'));
|
||||
attribute ram_style of cc_tag : signal is "block";
|
||||
attribute ram_style of cc_lru : signal is "block";
|
||||
attribute ram_style of cc_valid : signal is "block";
|
||||
attribute ram_style of cc_dirty : signal is "block";
|
||||
signal cc_we : std_logic := '0';
|
||||
signal cc_wr_addr, cc_rd_addr : unsigned(lines_ln2-assoc_ln2-1 downto 0) := (others => '-');
|
||||
signal cc_tag_wr_data, cc_tag_rd_data : tag_t := (others => '-');
|
||||
signal cc_lru_wr_data, cc_lru_rd_data : lru_t := (others => '-');
|
||||
signal cc_valid_wr_data, cc_valid_rd_data : std_logic_vector(assoc-1 downto 0) := (others => '0');
|
||||
signal cc_dirty_wr_data, cc_dirty_rd_data : std_logic_vector(assoc-1 downto 0) := (others => '-');
|
||||
|
||||
-- Convenience variable for cc_tag_rd_data
|
||||
type tag_a is array(assoc-1 downto 0) of std_logic_vector(tag_width-1 downto 0);
|
||||
signal tags : tag_a := (others => (others => '-'));
|
||||
|
||||
-- Cache data signals / memory
|
||||
type cache_arr is array(lines*line_size-1 downto 0) of std_logic_vector(31 downto 0);
|
||||
signal cache : cache_arr := (others => (others => '-'));
|
||||
attribute ram_style of cache : signal is "block";
|
||||
-- signal cache_we : std_logic := '0';
|
||||
signal cache_wr_addr, cache_rd_addr : unsigned(lines_ln2+line_size_ln2-1 downto 0) := (others => '0');
|
||||
signal cache_wr_data, cache_rd_data : std_logic_vector(31 downto 0) := (others => '-');
|
||||
signal cache_bwe : std_logic_vector(3 downto 0) := (others => '-');
|
||||
|
||||
-- Convenience variables for adr_i
|
||||
signal adr_index : unsigned(index_width-1 downto 0);
|
||||
signal adr_offset : unsigned(offset_width-1 downto 0);
|
||||
signal adr_tag : std_logic_vector(tag_width-1 downto 0);
|
||||
|
||||
-- Tag comparator output
|
||||
signal adr_tag_eq : std_logic_vector(assoc-1 downto 0);
|
||||
|
||||
-- LRU comparator output
|
||||
signal lru_eq0 : std_logic_vector(assoc-1 downto 0);
|
||||
|
||||
-- Priority encoders
|
||||
signal adr_tag_eq_num, eject_num : unsigned(assoc_ln2-1 downto 0);
|
||||
attribute priority_extract of adr_tag_eq_num : signal is "yes";
|
||||
attribute priority_extract of eject_num : signal is "yes";
|
||||
|
||||
-- control signals
|
||||
signal update_lru, set_dirty, set_valid, cache_write, cache_from_mem, eject_dirty : std_logic;
|
||||
signal cache_to_mem : std_logic;
|
||||
signal mem_offset : unsigned(offset_width-1 downto 0);
|
||||
signal mem_rdrq_int, mem_wrrq_int : std_logic;
|
||||
begin
|
||||
|
||||
cache_rd_addr <= adr_index & adr_tag_eq_num & adr_offset when cache_to_mem = '0' else
|
||||
adr_index & eject_num & mem_offset;
|
||||
cache_wr_addr <= adr_index & adr_tag_eq_num & adr_offset when cache_from_mem = '0' else
|
||||
adr_index & eject_num & mem_offset;
|
||||
--cache_we <= cache_write or (cache_from_mem and mem_ack);
|
||||
cache_wr_data <= wbs_i.dat_i when cache_write = '1' else
|
||||
mem_dat_i when cache_from_mem = '1' else
|
||||
(others => '-');
|
||||
cache_bwe <= wbs_i.sel_i when cache_write = '1' else
|
||||
"1111" when cache_from_mem = '1' and mem_ack = '1' else
|
||||
"0000";
|
||||
|
||||
-- Memory for cache data
|
||||
cache_mem : process(clk_i)
|
||||
begin
|
||||
if rising_edge(clk_i) then
|
||||
if cache_bwe(0) = '1' then
|
||||
cache(to_integer(cache_wr_addr))(7 downto 0) <= cache_wr_data(7 downto 0);
|
||||
end if;
|
||||
if cache_bwe(1) = '1' then
|
||||
cache(to_integer(cache_wr_addr))(15 downto 8) <= cache_wr_data(15 downto 8);
|
||||
end if;
|
||||
if cache_bwe(2) = '1' then
|
||||
cache(to_integer(cache_wr_addr))(23 downto 16) <= cache_wr_data(23 downto 16);
|
||||
end if;
|
||||
if cache_bwe(3) = '1' then
|
||||
cache(to_integer(cache_wr_addr))(31 downto 24) <= cache_wr_data(31 downto 24);
|
||||
end if;
|
||||
cache_rd_data <= cache(to_integer(cache_rd_addr));
|
||||
end if;
|
||||
end process cache_mem;
|
||||
|
||||
wbs_o.dat_o <= cache_rd_data;
|
||||
mem_dat_o <= cache_rd_data;
|
||||
|
||||
mem_adr <= adr_tag & std_logic_vector(adr_index) when cache_from_mem = '1' else
|
||||
tags(to_integer(eject_num)) & std_logic_vector(adr_index) when cache_to_mem = '1' else
|
||||
(others => '-');
|
||||
|
||||
cc_wr_data_gen : for i in 0 to assoc-1 generate
|
||||
cc_tag_wr_data((i+1)*tag_width-1 downto i*tag_width) <=
|
||||
adr_tag when eject_num = i and set_valid = '1' else
|
||||
cc_tag_rd_data((i+1)*tag_width-1 downto i*tag_width);
|
||||
|
||||
cc_lru_wr_data((i+1)*assoc_ln2-1 downto assoc_ln2*i) <=
|
||||
to_unsigned(assoc-1,assoc_ln2) when adr_tag_eq(i) = '1' and update_lru = '1' else
|
||||
cc_lru_rd_data((i+1)*assoc_ln2-1 downto assoc_ln2*i) when cc_lru_rd_data((i+1)*assoc_ln2-1 downto assoc_ln2*i) = 0 else
|
||||
cc_lru_rd_data((i+1)*assoc_ln2-1 downto assoc_ln2*i)-1 when update_lru = '1' else
|
||||
cc_lru_rd_data((i+1)*assoc_ln2-1 downto assoc_ln2*i);
|
||||
|
||||
cc_valid_wr_data(i) <=
|
||||
'1' when eject_num = i and set_valid = '1' else
|
||||
cc_valid_rd_data(i);
|
||||
|
||||
cc_dirty_wr_data(i) <=
|
||||
'1' when adr_tag_eq(i) = '1' and set_dirty = '1' else
|
||||
'0' when eject_num = i and set_valid = '1' else
|
||||
cc_dirty_rd_data(i);
|
||||
end generate;
|
||||
|
||||
cc_wr_addr <= adr_index when update_lru = '1' or set_dirty = '1' or set_valid = '1' else
|
||||
(others => '-');
|
||||
cc_we <= update_lru or set_dirty or set_valid;
|
||||
|
||||
-- Memory for cache control
|
||||
cc_mem : process(clk_i)
|
||||
variable cc_wr_addr_int : integer range 0 to lines/assoc-1;
|
||||
variable cc_rd_addr_int : integer range 0 to lines/assoc-1;
|
||||
begin
|
||||
if falling_edge(clk_i) then
|
||||
cc_wr_addr_int := to_integer(cc_wr_addr);
|
||||
cc_rd_addr_int := to_integer(cc_rd_addr);
|
||||
if cc_we = '1' then
|
||||
cc_tag(cc_wr_addr_int) <= cc_tag_wr_data;
|
||||
cc_lru(cc_wr_addr_int) <= cc_lru_wr_data;
|
||||
cc_valid(cc_wr_addr_int) <= cc_valid_wr_data;
|
||||
cc_dirty(cc_wr_addr_int) <= cc_dirty_wr_data;
|
||||
end if;
|
||||
cc_tag_rd_data <= cc_tag(cc_rd_addr_int);
|
||||
cc_lru_rd_data <= cc_lru(cc_rd_addr_int);
|
||||
cc_valid_rd_data <= cc_valid(cc_rd_addr_int);
|
||||
cc_dirty_rd_data <= cc_dirty(cc_rd_addr_int);
|
||||
end if;
|
||||
end process cc_mem;
|
||||
|
||||
assert addr_width+1 = wbs_i.adr_i'high report "Invalid address width, check parameters" severity error;
|
||||
adr_index <= unsigned(wbs_i.adr_i(offset_width+index_width+1 downto offset_width+2));
|
||||
adr_offset <=unsigned(wbs_i.adr_i(offset_width+1 downto 2));
|
||||
adr_tag <= wbs_i.adr_i(addr_width+1 downto offset_width+index_width+2);
|
||||
|
||||
tags_gen : for i in 0 to assoc-1 generate
|
||||
tags(i) <= cc_tag_rd_data((i+1)*tag_width-1 downto i*tag_width);
|
||||
end generate;
|
||||
|
||||
cc_rd_addr <= adr_index;
|
||||
|
||||
tag_compare : for i in 0 to assoc-1 generate
|
||||
adr_tag_eq(i) <= cc_valid_rd_data(i) when tags(i) = adr_tag else
|
||||
'0';
|
||||
end generate;
|
||||
|
||||
lru_compare : for i in 0 to assoc-1 generate
|
||||
lru_eq0(i) <= '1' when cc_lru_rd_data((i+1)*assoc_ln2-1 downto assoc_ln2*i) = 0 else
|
||||
'1' when cc_valid_rd_data(i) = '0' else
|
||||
'0';
|
||||
end generate;
|
||||
|
||||
-- The comb. process for..loop version does not synthesize properly, so do
|
||||
-- this manually
|
||||
assert assoc = 2 or assoc = 4 report "Unsupported associativity" severity error;
|
||||
pe_assoc_2 : if assoc = 2 generate
|
||||
adr_tag_eq_num <= to_unsigned(0,1) when adr_tag_eq(0) = '1' else
|
||||
to_unsigned(1,1) when adr_tag_eq(1) = '1' else
|
||||
(others => '-');
|
||||
eject_num <= to_unsigned(0,1) when lru_eq0(0) = '1' else
|
||||
to_unsigned(1,1) when lru_eq0(1) = '1' else
|
||||
to_unsigned(0,1);
|
||||
end generate;
|
||||
pe_assoc_4 : if assoc = 4 generate
|
||||
adr_tag_eq_num <= to_unsigned(0,2) when adr_tag_eq(0) = '1' else
|
||||
to_unsigned(1,2) when adr_tag_eq(1) = '1' else
|
||||
to_unsigned(2,2) when adr_tag_eq(2) = '1' else
|
||||
to_unsigned(3,2) when adr_tag_eq(3) = '1' else
|
||||
(others => '-');
|
||||
eject_num <= to_unsigned(0,2) when lru_eq0(0) = '1' else
|
||||
to_unsigned(1,2) when lru_eq0(1) = '1' else
|
||||
to_unsigned(2,2) when lru_eq0(2) = '1' else
|
||||
to_unsigned(3,2) when lru_eq0(3) = '1' else
|
||||
to_unsigned(0,1);
|
||||
end generate;
|
||||
|
||||
eject_dirty <= cc_dirty_rd_data(to_integer(eject_num)) and cc_valid_rd_data(to_integer(eject_num));
|
||||
|
||||
-- Offset counter
|
||||
mem_offset_ctr : process(clk_i)
|
||||
begin
|
||||
if rising_edge(clk_i) then
|
||||
if mem_rdrq_int = '1' or mem_wrrq_int = '1' then
|
||||
mem_offset <= to_unsigned(0,line_size_ln2);
|
||||
elsif mem_ack = '1' then
|
||||
mem_offset <= mem_offset + 1;
|
||||
end if;
|
||||
end if;
|
||||
end process mem_offset_ctr;
|
||||
|
||||
wb_ddr_ctrl_wb_sc_fe_fsm_inst: wb_ddr_ctrl_wb_sc_fe_fsm
|
||||
generic map (
|
||||
line_size => line_size,
|
||||
lines => lines,
|
||||
assoc => assoc,
|
||||
line_size_ln2 => line_size_ln2,
|
||||
lines_ln2 => lines_ln2,
|
||||
assoc_ln2 => assoc_ln2,
|
||||
addr_width => addr_width)
|
||||
port map (
|
||||
clk_i => clk_i,
|
||||
rst_i => rst_i,
|
||||
cyc_i => wbs_i.cyc_i,
|
||||
stb_i => wbs_i.stb_i,
|
||||
we_i => wbs_i.we_i,
|
||||
adr_tag_eq => adr_tag_eq,
|
||||
eject_dirty => eject_dirty,
|
||||
mem_offset => mem_offset,
|
||||
ack_o => wbs_o.ack_o,
|
||||
update_lru => update_lru,
|
||||
set_dirty => set_dirty,
|
||||
set_valid => set_valid,
|
||||
cache_write => cache_write,
|
||||
cache_from_mem => cache_from_mem,
|
||||
cache_to_mem => cache_to_mem,
|
||||
mem_rdrq => mem_rdrq_int,
|
||||
mem_wrrq => mem_wrrq_int);
|
||||
|
||||
mem_rdrq <= mem_rdrq_int;
|
||||
mem_wrrq <= mem_wrrq_int;
|
||||
|
||||
end Behavioral;
|
||||
278
src/wb_ddr_ctrl_wb_sc_fe_fsm.vhd
Normal file
278
src/wb_ddr_ctrl_wb_sc_fe_fsm.vhd
Normal file
@@ -0,0 +1,278 @@
|
||||
----------------------------------------------------------------------------------
|
||||
-- Company:
|
||||
-- Engineer:
|
||||
--
|
||||
-- Create Date: 11/06/2012 03:04:35 PM
|
||||
-- Design Name:
|
||||
-- Module Name: wb_ddr_ctrl_wb_sc_fe_fsm - Behavioral
|
||||
-- Project Name:
|
||||
-- Target Devices:
|
||||
-- Tool Versions:
|
||||
-- Description: Memory controller - system clock domain - Cache front-end -
|
||||
-- Control path
|
||||
--
|
||||
-- Dependencies:
|
||||
--
|
||||
-- Revision:
|
||||
-- Revision 0.01 - File Created
|
||||
-- Additional Comments:
|
||||
--
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
|
||||
-- Uncomment the following library declaration if using
|
||||
-- arithmetic functions with Signed or Unsigned values
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
-- Uncomment the following library declaration if instantiating
|
||||
-- any Xilinx primitives in this code.
|
||||
library UNISIM;
|
||||
use UNISIM.VComponents.all;
|
||||
|
||||
use work.intercon_package.all;
|
||||
|
||||
entity wb_ddr_ctrl_wb_sc_fe_fsm is
|
||||
generic (
|
||||
line_size : integer := 16;
|
||||
lines : integer := 64;
|
||||
assoc : integer := 2;
|
||||
line_size_ln2 : integer := 4;
|
||||
lines_ln2 : integer := 6;
|
||||
assoc_ln2 : integer := 1;
|
||||
addr_width : integer := 24
|
||||
);
|
||||
port (
|
||||
clk_i : in std_logic;
|
||||
rst_i : in std_logic;
|
||||
|
||||
cyc_i : in std_logic;
|
||||
stb_i : in std_logic;
|
||||
we_i : in std_logic;
|
||||
adr_tag_eq : in std_logic_vector(assoc-1 downto 0);
|
||||
eject_dirty : in std_logic;
|
||||
mem_offset : in unsigned(line_size_ln2-1 downto 0);
|
||||
|
||||
ack_o : out std_logic;
|
||||
update_lru : out std_logic := '0';
|
||||
set_dirty : out std_logic := '0';
|
||||
set_valid : out std_logic := '0';
|
||||
cache_write : out std_logic := '0';
|
||||
cache_from_mem : out std_logic := '0';
|
||||
cache_to_mem : out std_logic := '0';
|
||||
mem_rdrq : out std_logic := '0';
|
||||
mem_wrrq : out std_logic := '0'
|
||||
);
|
||||
end wb_ddr_ctrl_wb_sc_fe_fsm;
|
||||
|
||||
architecture Behavioral of wb_ddr_ctrl_wb_sc_fe_fsm is
|
||||
type states is (S_IDLE, S_WRITEBACK, S_FETCH, S_WAIT, S_WAIT_FETCH);
|
||||
signal state : states := S_IDLE;
|
||||
begin
|
||||
|
||||
cache_ctrl : process(clk_i)
|
||||
begin
|
||||
if rising_edge(clk_i) then
|
||||
ack_o <= '0';
|
||||
update_lru <= '0';
|
||||
set_dirty <= '0';
|
||||
set_valid <= '0';
|
||||
cache_write <= '0';
|
||||
cache_from_mem <= '0';
|
||||
cache_to_mem <= '0';
|
||||
mem_rdrq <= '0';
|
||||
mem_wrrq <= '0';
|
||||
|
||||
case state is
|
||||
when S_IDLE =>
|
||||
if cyc_i = '1' and stb_i = '1' then
|
||||
if we_i = '1' then
|
||||
if to_integer(unsigned(adr_tag_eq)) = 0 then
|
||||
-- miss
|
||||
if eject_dirty = '1' then
|
||||
cache_to_mem <= '1';
|
||||
mem_wrrq <= '1';
|
||||
state <= S_WRITEBACK;
|
||||
else
|
||||
cache_from_mem <= '1';
|
||||
mem_rdrq <= '1';
|
||||
state <= S_FETCH;
|
||||
end if;
|
||||
else
|
||||
-- hit
|
||||
ack_o <= '1';
|
||||
update_lru <= '1';
|
||||
set_dirty <= '1';
|
||||
cache_write <= '1';
|
||||
state <= S_WAIT;
|
||||
end if;
|
||||
else
|
||||
if to_integer(unsigned(adr_tag_eq)) = 0 then
|
||||
-- miss
|
||||
if eject_dirty = '1' then
|
||||
cache_to_mem <= '1';
|
||||
mem_wrrq <= '1';
|
||||
state <= S_WRITEBACK;
|
||||
else
|
||||
cache_from_mem <= '1';
|
||||
mem_rdrq <= '1';
|
||||
state <= S_FETCH;
|
||||
end if;
|
||||
else
|
||||
-- hit
|
||||
ack_o <= '1';
|
||||
update_lru <= '1';
|
||||
state <= S_WAIT;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
when S_WAIT =>
|
||||
state <= S_IDLE;
|
||||
when S_FETCH =>
|
||||
cache_from_mem <= '1';
|
||||
if mem_offset = line_size-1 then
|
||||
set_valid <= '1';
|
||||
state <= S_WAIT;
|
||||
end if;
|
||||
when S_WRITEBACK =>
|
||||
cache_to_mem <= '1';
|
||||
if mem_offset = line_size-1 then
|
||||
cache_to_mem <= '0';
|
||||
state <= S_WAIT_FETCH;
|
||||
end if;
|
||||
when S_WAIT_FETCH =>
|
||||
cache_from_mem <= '1';
|
||||
mem_rdrq <= '1';
|
||||
state <= S_FETCH;
|
||||
end case;
|
||||
end if;
|
||||
end process cache_ctrl;
|
||||
|
||||
--cache_ctrl : process(clk_i)
|
||||
-- begin
|
||||
-- if rising_edge(clk_i) then
|
||||
-- cache_we <= '0';
|
||||
-- cache_wr_data <= (others => '-');
|
||||
-- line_info_we <= '0';
|
||||
-- line_info_wr_data <= dontcare_line_info;
|
||||
-- mem_adr <= (others => '-');
|
||||
-- mem_rdrq <= '0';
|
||||
-- mem_wrrq <= '0';
|
||||
|
||||
-- case state is
|
||||
-- when S_IDLE =>
|
||||
-- if wbs_i.stb_i = '1' and wbs_i.cyc_i = '1' then
|
||||
-- if wbs_i.we_i = '1' then
|
||||
-- if to_integer(unsigned(adr_tag_eq)) = 0 then
|
||||
-- -- miss
|
||||
-- if line_info_rd_data.valid(eject_num) = '1' and
|
||||
-- line_info_rd_data.dirty(eject_num) = '1' then
|
||||
-- cache_rd_addr <= adr_index*line_size*assoc+eject_num*line_size+0;
|
||||
-- ctr <= 0;
|
||||
-- state <= S_WRITEBACK1;
|
||||
-- else
|
||||
-- mem_adr <= wbs_i.adr_i(addr_width+1 downto line_size_ln2+2);
|
||||
-- mem_rdrq <= '1';
|
||||
-- ctr <= 0;
|
||||
-- state <= S_FETCH;
|
||||
-- end if;
|
||||
-- else
|
||||
-- -- hit
|
||||
-- wbs_o.ack_o <= '1';
|
||||
-- cache_wr_data <= wbs_i.dat_i;
|
||||
-- cache_wr_addr <= adr_index*line_size*assoc+adr_tag_eq_num*line_size+adr_offset;
|
||||
-- cache_we <= '1';
|
||||
-- line_info_wr_data <= line_info_rd_data;
|
||||
-- line_info_wr_data.dirty(adr_tag_eq_num) <= '1';
|
||||
-- for i in 0 to assoc-1 loop
|
||||
-- if i = adr_tag_eq_num then
|
||||
-- line_info_wr_data.lru(i) <= assoc-1;
|
||||
-- else
|
||||
-- if line_info_rd_data.lru(i) > 0 then
|
||||
-- line_info_wr_data.lru(i) <= line_info_rd_data.lru(i) - 1;
|
||||
-- end if;
|
||||
-- end if;
|
||||
-- end loop;
|
||||
-- line_info_wr_addr <= line_info_rd_addr;
|
||||
-- line_info_we <= '1';
|
||||
-- state <= S_WAIT;
|
||||
-- end if;
|
||||
-- else
|
||||
-- if to_integer(unsigned(adr_tag_eq)) = 0 then
|
||||
-- -- miss
|
||||
-- if line_info_rd_data.valid(eject_num) = '1' and
|
||||
-- line_info_rd_data.dirty(eject_num) = '1' then
|
||||
-- cache_rd_addr <= adr_index*line_size*assoc+eject_num*line_size+0;
|
||||
-- ctr <= 0;
|
||||
-- state <= S_WRITEBACK1;
|
||||
-- else
|
||||
-- mem_adr <= wbs_i.adr_i(addr_width+1 downto line_size_ln2+2);
|
||||
-- mem_rdrq <= '1';
|
||||
-- ctr <= 0;
|
||||
-- state <= S_FETCH;
|
||||
-- end if;
|
||||
-- else
|
||||
-- -- hit
|
||||
-- cache_rd_addr <= adr_index*line_size*assoc+adr_tag_eq_num*line_size+adr_offset;
|
||||
-- line_info_wr_data <= line_info_rd_data;
|
||||
-- for i in 0 to assoc-1 loop
|
||||
-- if i = adr_tag_eq_num then
|
||||
-- line_info_wr_data.lru(i) <= assoc-1;
|
||||
-- else
|
||||
-- if line_info_rd_data.lru(i) > 0 then
|
||||
-- line_info_wr_data.lru(i) <= line_info_rd_data.lru(i) - 1;
|
||||
-- end if;
|
||||
-- end if;
|
||||
-- end loop;
|
||||
-- line_info_wr_addr <= line_info_rd_addr;
|
||||
-- line_info_we <= '1';
|
||||
-- state <= S_READHIT;
|
||||
-- end if;
|
||||
-- end if;
|
||||
-- end if;
|
||||
-- when S_WAIT =>
|
||||
-- state <= S_IDLE;
|
||||
-- when S_READHIT =>
|
||||
-- wbs_o.ack_o <= '1';
|
||||
-- state <= S_WAIT;
|
||||
|
||||
-- when S_FETCH =>
|
||||
-- if mem_ack = '1' then
|
||||
-- cache_wr_data <= mem_dat_i;
|
||||
-- cache_wr_addr <= adr_index*line_size*assoc+eject_num*line_size+ctr;
|
||||
-- cache_we <= '1';
|
||||
-- if ctr = line_size-1 then
|
||||
-- line_info_wr_data <= line_info_rd_data;
|
||||
-- line_info_wr_data.valid(eject_num) <= '1';
|
||||
-- line_info_wr_data.dirty(eject_num) <= '0';
|
||||
-- line_info_wr_data.tag(eject_num) <= adr_tag;
|
||||
-- line_info_wr_addr <= line_info_rd_addr;
|
||||
-- line_info_we <= '1';
|
||||
-- state <= S_IDLE; -- restart request
|
||||
-- else
|
||||
-- ctr <= ctr + 1;
|
||||
-- end if;
|
||||
-- end if;
|
||||
-- when S_WRITEBACK1 =>
|
||||
-- mem_adr <= wbs_i.adr_i(addr_width+1 downto line_size_ln2+2);
|
||||
-- mem_wrrq <= '1';
|
||||
-- state <= S_WRITEBACK2;
|
||||
-- when S_WRITEBACK2 =>
|
||||
-- if mem_ack = '1' then
|
||||
-- cache_rd_addr <= adr_index*line_size*assoc+eject_num*line_size+ctr;
|
||||
-- if ctr = line_size-1 then
|
||||
-- mem_adr <= wbs_i.adr_i(addr_width+1 downto line_size_ln2+2);
|
||||
-- mem_rdrq <= '1';
|
||||
-- ctr <= 0;
|
||||
-- state <= S_FETCH;
|
||||
-- else
|
||||
-- ctr <= ctr + 1;
|
||||
-- end if;
|
||||
-- end if;
|
||||
-- end case;
|
||||
-- end if;
|
||||
-- end process cache_ctrl;
|
||||
end Behavioral;
|
||||
|
||||
@@ -32,16 +32,17 @@ master vga
|
||||
priority_sdram_ctrl=3
|
||||
end master vga
|
||||
|
||||
master cpu
|
||||
# zy2000 ZPU core with wishbone bridge
|
||||
master zpu
|
||||
type=rw
|
||||
lock_o=0
|
||||
tga_o=1
|
||||
tgc_o=1
|
||||
tga_o=0
|
||||
tgc_o=0
|
||||
tgd_o=0
|
||||
err_i=0
|
||||
rty_i=0
|
||||
priority_sdram_ctrl=2
|
||||
end master cpu
|
||||
end master zpu
|
||||
|
||||
slave sdram_ctrl
|
||||
type=rw
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
-- Author : Matthias Blankertz <matthias@blankertz.org>
|
||||
-- Company :
|
||||
-- Created : 2013-02-26
|
||||
-- Last update: 2013-03-02
|
||||
-- Last update: 2013-03-03
|
||||
-- Platform :
|
||||
-- Standard : VHDL'93
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -23,6 +23,8 @@ library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
use work.intercon_package.all;
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
entity wb_ddr_ctrl_tb is
|
||||
@@ -55,16 +57,8 @@ architecture testbench of wb_ddr_ctrl_tb is
|
||||
ddr2_ck_n : out std_logic_vector(0 downto 0);
|
||||
clk_i : in std_ulogic;
|
||||
rst_i : in std_ulogic;
|
||||
dat_i : in std_ulogic_vector(31 downto 0);
|
||||
dat_o : out std_ulogic_vector(31 downto 0);
|
||||
ack_o : out std_ulogic;
|
||||
adr_i : in std_ulogic_vector(25 downto 2);
|
||||
cyc_i : in std_ulogic;
|
||||
sel_i : in std_ulogic_vector(3 downto 0);
|
||||
stb_i : in std_ulogic;
|
||||
we_i : in std_ulogic;
|
||||
cti_i : in std_ulogic_vector(2 downto 0);
|
||||
bte_i : in std_ulogic_vector(1 downto 0));
|
||||
wbs_i : in sdram_ctrl_wbs_i_type;
|
||||
wbs_o : out sdram_ctrl_wbs_o_type);
|
||||
end component;
|
||||
|
||||
component ddr2_model
|
||||
@@ -108,16 +102,16 @@ architecture testbench of wb_ddr_ctrl_tb is
|
||||
signal ddr2_ck_n : std_logic_vector(0 downto 0);
|
||||
signal clk_i : std_ulogic := '0';
|
||||
signal rst_i : std_ulogic;
|
||||
signal dat_i : std_ulogic_vector(31 downto 0) := (others => '-');
|
||||
signal dat_o : std_ulogic_vector(31 downto 0);
|
||||
signal dat_i : std_logic_vector(31 downto 0) := (others => '-');
|
||||
signal dat_o : std_logic_vector(31 downto 0);
|
||||
signal ack_o : std_ulogic;
|
||||
signal adr_i : std_ulogic_vector(25 downto 2) := (others => '-');
|
||||
signal adr_i : std_logic_vector(25 downto 2) := (others => '-');
|
||||
signal cyc_i : std_ulogic := '0';
|
||||
signal sel_i : std_ulogic_vector(3 downto 0) := (others => '0');
|
||||
signal sel_i : std_logic_vector(3 downto 0) := (others => '0');
|
||||
signal stb_i : std_ulogic := '0';
|
||||
signal we_i : std_ulogic := '0';
|
||||
signal cti_i : std_ulogic_vector(2 downto 0) := (others => '0');
|
||||
signal bte_i : std_ulogic_vector(1 downto 0) := (others => '0');
|
||||
signal cti_i : std_logic_vector(2 downto 0) := (others => '0');
|
||||
signal bte_i : std_logic_vector(1 downto 0) := (others => '0');
|
||||
|
||||
begin -- testbench
|
||||
|
||||
@@ -144,16 +138,16 @@ begin -- testbench
|
||||
ddr2_ck_n => ddr2_ck_n,
|
||||
clk_i => clk_i,
|
||||
rst_i => rst_i,
|
||||
dat_i => dat_i,
|
||||
dat_o => dat_o,
|
||||
ack_o => ack_o,
|
||||
adr_i => adr_i,
|
||||
cyc_i => cyc_i,
|
||||
sel_i => sel_i,
|
||||
stb_i => stb_i,
|
||||
we_i => we_i,
|
||||
cti_i => cti_i,
|
||||
bte_i => bte_i);
|
||||
wbs_i.dat_i => dat_i,
|
||||
wbs_i.adr_i => adr_i,
|
||||
wbs_i.cyc_i => cyc_i,
|
||||
wbs_i.sel_i => sel_i,
|
||||
wbs_i.stb_i => stb_i,
|
||||
wbs_i.we_i => we_i,
|
||||
wbs_i.cti_i => cti_i,
|
||||
wbs_i.bte_i => bte_i,
|
||||
wbs_o.dat_o => dat_o,
|
||||
wbs_o.ack_o => ack_o);
|
||||
|
||||
rst_dqs_div_in <= rst_dqs_div_out after 100 ps;
|
||||
|
||||
@@ -181,7 +175,7 @@ begin -- testbench
|
||||
|
||||
-- waveform generation
|
||||
WaveGen_Proc: process
|
||||
variable expected_data : std_ulogic_vector(31 downto 0);
|
||||
variable expected_data : std_logic_vector(31 downto 0);
|
||||
begin
|
||||
-- insert signal assignments here
|
||||
ddr2_reset <= '1';
|
||||
@@ -269,9 +263,9 @@ begin -- testbench
|
||||
we_i <= '1' after 2 ns;
|
||||
dat_i <= x"d000000d" after 2 ns;
|
||||
for i in 0 to 7 loop
|
||||
adr_i <= std_ulogic_vector(to_unsigned(256+i,24)) after 2 ns;
|
||||
dat_i(23 downto 16) <= std_ulogic_vector(to_unsigned(i,8)) after 2 ns;
|
||||
dat_i(15 downto 8) <= std_ulogic_vector(to_unsigned(i,8)) after 2 ns;
|
||||
adr_i <= std_logic_vector(to_unsigned(256+i,24)) after 2 ns;
|
||||
dat_i(23 downto 16) <= std_logic_vector(to_unsigned(i,8)) after 2 ns;
|
||||
dat_i(15 downto 8) <= std_logic_vector(to_unsigned(i,8)) after 2 ns;
|
||||
sel_i <= "1111" after 2 ns;
|
||||
if i = 7 then -- EOB
|
||||
cti_i <= "111" after 2 ns;
|
||||
@@ -292,9 +286,9 @@ begin -- testbench
|
||||
we_i <= '1' after 2 ns;
|
||||
dat_i <= x"d000000d" after 2 ns;
|
||||
for i in 7 to 31 loop
|
||||
adr_i <= std_ulogic_vector(to_unsigned(256+i,24)) after 2 ns;
|
||||
dat_i(23 downto 16) <= std_ulogic_vector(to_unsigned(i,8)) after 2 ns;
|
||||
dat_i(15 downto 8) <= std_ulogic_vector(to_unsigned(i,8)) after 2 ns;
|
||||
adr_i <= std_logic_vector(to_unsigned(256+i,24)) after 2 ns;
|
||||
dat_i(23 downto 16) <= std_logic_vector(to_unsigned(i,8)) after 2 ns;
|
||||
dat_i(15 downto 8) <= std_logic_vector(to_unsigned(i,8)) after 2 ns;
|
||||
sel_i <= "1111" after 2 ns;
|
||||
if i = 15 then -- EOB
|
||||
cti_i <= "111" after 2 ns;
|
||||
@@ -328,10 +322,10 @@ begin -- testbench
|
||||
stb_i <= '1' after 2 ns;
|
||||
we_i <= '0' after 2 ns;
|
||||
for i in 0 to 15 loop
|
||||
adr_i <= std_ulogic_vector(to_unsigned(256+i,24)) after 2 ns;
|
||||
adr_i <= std_logic_vector(to_unsigned(256+i,24)) after 2 ns;
|
||||
expected_data(31 downto 24) := x"d0";
|
||||
expected_data(23 downto 16) := std_ulogic_vector(to_unsigned(i,8));
|
||||
expected_data(15 downto 8) := std_ulogic_vector(to_unsigned(i,8));
|
||||
expected_data(23 downto 16) := std_logic_vector(to_unsigned(i,8));
|
||||
expected_data(15 downto 8) := std_logic_vector(to_unsigned(i,8));
|
||||
expected_data(7 downto 0) := x"0d";
|
||||
wait until rising_edge(clk_i);
|
||||
while ack_o = '0' loop
|
||||
@@ -349,10 +343,10 @@ begin -- testbench
|
||||
stb_i <= '1' after 2 ns;
|
||||
we_i <= '0' after 2 ns;
|
||||
for i in 16 to 31 loop
|
||||
adr_i <= std_ulogic_vector(to_unsigned(256+i,24)) after 2 ns;
|
||||
adr_i <= std_logic_vector(to_unsigned(256+i,24)) after 2 ns;
|
||||
expected_data(31 downto 24) := x"d0";
|
||||
expected_data(23 downto 16) := std_ulogic_vector(to_unsigned(i,8));
|
||||
expected_data(15 downto 8) := std_ulogic_vector(to_unsigned(i,8));
|
||||
expected_data(23 downto 16) := std_logic_vector(to_unsigned(i,8));
|
||||
expected_data(15 downto 8) := std_logic_vector(to_unsigned(i,8));
|
||||
expected_data(7 downto 0) := x"0d";
|
||||
wait until rising_edge(clk_i);
|
||||
while ack_o = '0' loop
|
||||
@@ -370,10 +364,10 @@ begin -- testbench
|
||||
stb_i <= '1' after 2 ns;
|
||||
we_i <= '0' after 2 ns;
|
||||
for i in 15 to 30 loop
|
||||
adr_i <= std_ulogic_vector(to_unsigned(256+i,24)) after 2 ns;
|
||||
adr_i <= std_logic_vector(to_unsigned(256+i,24)) after 2 ns;
|
||||
expected_data(31 downto 24) := x"d0";
|
||||
expected_data(23 downto 16) := std_ulogic_vector(to_unsigned(i,8));
|
||||
expected_data(15 downto 8) := std_ulogic_vector(to_unsigned(i,8));
|
||||
expected_data(23 downto 16) := std_logic_vector(to_unsigned(i,8));
|
||||
expected_data(15 downto 8) := std_logic_vector(to_unsigned(i,8));
|
||||
expected_data(7 downto 0) := x"0d";
|
||||
wait until rising_edge(clk_i);
|
||||
while ack_o = '0' loop
|
||||
@@ -392,9 +386,9 @@ begin -- testbench
|
||||
we_i <= '1' after 2 ns;
|
||||
dat_i <= x"d000000d" after 2 ns;
|
||||
for i in 0 to 15 loop
|
||||
adr_i <= std_ulogic_vector(to_unsigned(4088+i,24)) after 2 ns;
|
||||
dat_i(23 downto 16) <= std_ulogic_vector(to_unsigned(i,8)) after 2 ns;
|
||||
dat_i(15 downto 8) <= std_ulogic_vector(to_unsigned(i,8)) after 2 ns;
|
||||
adr_i <= std_logic_vector(to_unsigned(4088+i,24)) after 2 ns;
|
||||
dat_i(23 downto 16) <= std_logic_vector(to_unsigned(i,8)) after 2 ns;
|
||||
dat_i(15 downto 8) <= std_logic_vector(to_unsigned(i,8)) after 2 ns;
|
||||
sel_i <= "1111" after 2 ns;
|
||||
if i = 15 then -- EOB
|
||||
cti_i <= "111" after 2 ns;
|
||||
@@ -414,10 +408,10 @@ begin -- testbench
|
||||
stb_i <= '1' after 2 ns;
|
||||
we_i <= '0' after 2 ns;
|
||||
for i in 0 to 15 loop
|
||||
adr_i <= std_ulogic_vector(to_unsigned(4088+i,24)) after 2 ns;
|
||||
adr_i <= std_logic_vector(to_unsigned(4088+i,24)) after 2 ns;
|
||||
expected_data(31 downto 24) := x"d0";
|
||||
expected_data(23 downto 16) := std_ulogic_vector(to_unsigned(i,8));
|
||||
expected_data(15 downto 8) := std_ulogic_vector(to_unsigned(i,8));
|
||||
expected_data(23 downto 16) := std_logic_vector(to_unsigned(i,8));
|
||||
expected_data(15 downto 8) := std_logic_vector(to_unsigned(i,8));
|
||||
expected_data(7 downto 0) := x"0d";
|
||||
if i = 15 then -- EOB
|
||||
cti_i <= "111" after 2 ns;
|
||||
|
||||
283
tb/wb_ddr_ctrl_wb_sc_fe_tb.vhd
Normal file
283
tb/wb_ddr_ctrl_wb_sc_fe_tb.vhd
Normal file
@@ -0,0 +1,283 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- Title : Testbench for design "wb_ddr_ctrl_wb_sc_fe"
|
||||
-- Project :
|
||||
-------------------------------------------------------------------------------
|
||||
-- File : wb_ddr_ctrl_wb_sc_fe_tb.vhd
|
||||
-- Author : <Matthias@MATTHIAS-PC>
|
||||
-- Company :
|
||||
-- Created : 2013-03-03
|
||||
-- Last update: 2013-03-03
|
||||
-- Platform :
|
||||
-- Standard : VHDL'87
|
||||
-------------------------------------------------------------------------------
|
||||
-- Description:
|
||||
-------------------------------------------------------------------------------
|
||||
-- Copyright (c) 2013
|
||||
-------------------------------------------------------------------------------
|
||||
-- Revisions :
|
||||
-- Date Version Author Description
|
||||
-- 2013-03-03 1.0 Matthias Created
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
library ieee_proposed;
|
||||
use ieee_proposed.std_logic_1164_additions.all;
|
||||
use ieee.numeric_std.all;
|
||||
--library std;
|
||||
--use std.textio.all;
|
||||
use work.intercon_package.all;
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
entity wb_ddr_ctrl_wb_sc_fe_tb is
|
||||
|
||||
end wb_ddr_ctrl_wb_sc_fe_tb;
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
architecture testbench of wb_ddr_ctrl_wb_sc_fe_tb is
|
||||
|
||||
component wb_ddr_ctrl_wb_sc_fe
|
||||
generic (
|
||||
line_size : integer;
|
||||
lines : integer;
|
||||
assoc : integer;
|
||||
line_size_ln2 : integer;
|
||||
lines_ln2 : integer;
|
||||
assoc_ln2 : integer;
|
||||
addr_width : integer);
|
||||
port (
|
||||
clk_i : in std_logic;
|
||||
rst_i : in std_logic;
|
||||
wbs_i : in sdram_ctrl_wbs_i_type;
|
||||
wbs_o : out sdram_ctrl_wbs_o_type;
|
||||
mem_adr : out std_logic_vector(addr_width-line_size_ln2-1 downto 0);
|
||||
mem_rdrq : out std_logic;
|
||||
mem_wrrq : out std_logic;
|
||||
mem_dat_o : out std_logic_vector(31 downto 0);
|
||||
mem_ack : in std_logic;
|
||||
mem_dat_i : in std_logic_vector(31 downto 0));
|
||||
end component;
|
||||
|
||||
-- component generics
|
||||
constant line_size : integer := 16;
|
||||
constant lines : integer := 64;
|
||||
constant assoc : integer := 2;
|
||||
constant line_size_ln2 : integer := 4;
|
||||
constant lines_ln2 : integer := 6;
|
||||
constant assoc_ln2 : integer := 1;
|
||||
constant addr_width : integer := 24;
|
||||
|
||||
-- component ports
|
||||
signal clk_i : std_logic := '0';
|
||||
signal rst_i : std_logic := '0';
|
||||
signal wbs_i : sdram_ctrl_wbs_i_type;
|
||||
signal wbs_o : sdram_ctrl_wbs_o_type;
|
||||
signal mem_adr : std_logic_vector(addr_width-line_size_ln2-1 downto 0);
|
||||
signal mem_rdrq : std_logic;
|
||||
signal mem_wrrq : std_logic;
|
||||
signal mem_dat_o : std_logic_vector(31 downto 0);
|
||||
signal mem_ack : std_logic := '0';
|
||||
signal mem_dat_i : std_logic_vector(31 downto 0) := (others => '-');
|
||||
|
||||
begin -- testbench
|
||||
|
||||
-- component instantiation
|
||||
DUT: wb_ddr_ctrl_wb_sc_fe
|
||||
generic map (
|
||||
line_size => line_size,
|
||||
lines => lines,
|
||||
assoc => assoc,
|
||||
line_size_ln2 => line_size_ln2,
|
||||
lines_ln2 => lines_ln2,
|
||||
assoc_ln2 => assoc_ln2,
|
||||
addr_width => addr_width)
|
||||
port map (
|
||||
clk_i => clk_i,
|
||||
rst_i => rst_i,
|
||||
wbs_i => wbs_i,
|
||||
wbs_o => wbs_o,
|
||||
mem_adr => mem_adr,
|
||||
mem_rdrq => mem_rdrq,
|
||||
mem_wrrq => mem_wrrq,
|
||||
mem_dat_o => mem_dat_o,
|
||||
mem_ack => mem_ack,
|
||||
mem_dat_i => mem_dat_i);
|
||||
|
||||
-- clock generation
|
||||
clk_i <= not clk_i after 10 ns;
|
||||
|
||||
-- waveform generation
|
||||
WaveGen_Proc: process
|
||||
begin
|
||||
wbs_i.cyc_i <= '0';
|
||||
wbs_i.stb_i <= '0';
|
||||
wbs_i.we_i <= '-';
|
||||
wbs_i.adr_i <= (others => '-');
|
||||
wbs_i.dat_i <= (others => '-');
|
||||
wbs_i.sel_i <= (others => '-');
|
||||
|
||||
wait for 50 ns;
|
||||
|
||||
-- read miss w/o replace (tag 0 index 0)
|
||||
wait until rising_edge(clk_i);
|
||||
wbs_i.cyc_i <= '1';
|
||||
wbs_i.stb_i <= '1';
|
||||
wbs_i.we_i <= '0';
|
||||
wbs_i.adr_i <= x"000000";
|
||||
wait until rising_edge(clk_i);
|
||||
while wbs_o.ack_o = '0' loop
|
||||
wait until rising_edge(clk_i);
|
||||
end loop;
|
||||
assert wbs_o.dat_o = x"ffff000f" report "Read fail: expected 0xffff000f, got " & to_hstring(wbs_o.dat_o) severity error;
|
||||
wbs_i.cyc_i <= '0';
|
||||
wbs_i.stb_i <= '0';
|
||||
wait until rising_edge(clk_i);
|
||||
|
||||
-- read miss w/o replace (tag 1 index 0)
|
||||
wbs_i.cyc_i <= '1';
|
||||
wbs_i.stb_i <= '1';
|
||||
wbs_i.we_i <= '0';
|
||||
wbs_i.adr_i <= x"000200";
|
||||
wait until rising_edge(clk_i);
|
||||
while wbs_o.ack_o = '0' loop
|
||||
wait until rising_edge(clk_i);
|
||||
end loop;
|
||||
assert wbs_o.dat_o = x"ffff200f" report "Read fail: expected 0xffff200f, got " & to_hstring(wbs_o.dat_o) severity error;
|
||||
wbs_i.cyc_i <= '0';
|
||||
wbs_i.stb_i <= '0';
|
||||
wait until rising_edge(clk_i);
|
||||
|
||||
-- read hit (tag 0 index 0)
|
||||
wbs_i.cyc_i <= '1';
|
||||
wbs_i.stb_i <= '1';
|
||||
wbs_i.we_i <= '0';
|
||||
wbs_i.adr_i <= x"000005";
|
||||
wait until rising_edge(clk_i);
|
||||
while wbs_o.ack_o = '0' loop
|
||||
wait until rising_edge(clk_i);
|
||||
end loop;
|
||||
assert wbs_o.dat_o = x"ffff005f" report "Read fail: expected 0xffff005f, got " & to_hstring(wbs_o.dat_o) severity error;
|
||||
wbs_i.cyc_i <= '0';
|
||||
wbs_i.stb_i <= '0';
|
||||
wait until rising_edge(clk_i);
|
||||
|
||||
-- read miss w/ replace (tag 2 index 0)
|
||||
wbs_i.cyc_i <= '1';
|
||||
wbs_i.stb_i <= '1';
|
||||
wbs_i.we_i <= '0';
|
||||
wbs_i.adr_i <= x"000405";
|
||||
wait until rising_edge(clk_i);
|
||||
while wbs_o.ack_o = '0' loop
|
||||
wait until rising_edge(clk_i);
|
||||
end loop;
|
||||
assert wbs_o.dat_o = x"00000000" report "Read fail: expected 0x00000000, got "& to_hstring(wbs_o.dat_o) severity error;
|
||||
wbs_i.cyc_i <= '0';
|
||||
wbs_i.stb_i <= '0';
|
||||
wait until rising_edge(clk_i);
|
||||
|
||||
-- write hit (tag 2 index 0)
|
||||
wbs_i.cyc_i <= '1';
|
||||
wbs_i.stb_i <= '1';
|
||||
wbs_i.we_i <= '1';
|
||||
wbs_i.adr_i <= x"000404";
|
||||
wbs_i.dat_i <= x"deadbeef";
|
||||
wbs_i.sel_i <= "1111";
|
||||
wait until rising_edge(clk_i);
|
||||
while wbs_o.ack_o = '0' loop
|
||||
wait until rising_edge(clk_i);
|
||||
end loop;
|
||||
wbs_i.cyc_i <= '0';
|
||||
wbs_i.stb_i <= '0';
|
||||
wait until rising_edge(clk_i);
|
||||
|
||||
-- read hit (tag 0 index 0)
|
||||
wbs_i.cyc_i <= '1';
|
||||
wbs_i.stb_i <= '1';
|
||||
wbs_i.we_i <= '0';
|
||||
wbs_i.adr_i <= x"000005";
|
||||
wait until rising_edge(clk_i);
|
||||
while wbs_o.ack_o = '0' loop
|
||||
wait until rising_edge(clk_i);
|
||||
end loop;
|
||||
assert wbs_o.dat_o = x"ffff005f" report "Read fail: expected 0xffff005f, got " & to_hstring(wbs_o.dat_o) severity error;
|
||||
wbs_i.cyc_i <= '0';
|
||||
wbs_i.stb_i <= '0';
|
||||
wait until rising_edge(clk_i);
|
||||
|
||||
-- read miss w/dirty replace (tag 1 index 0)
|
||||
wbs_i.cyc_i <= '1';
|
||||
wbs_i.stb_i <= '1';
|
||||
wbs_i.we_i <= '0';
|
||||
wbs_i.adr_i <= x"000202";
|
||||
wait until rising_edge(clk_i);
|
||||
while wbs_o.ack_o = '0' loop
|
||||
wait until rising_edge(clk_i);
|
||||
end loop;
|
||||
assert wbs_o.dat_o = x"ffff202f" report "Read fail: expected 0xffff202f, got " & to_hstring(wbs_o.dat_o) severity error;
|
||||
wbs_i.cyc_i <= '0';
|
||||
wbs_i.stb_i <= '0';
|
||||
wait until rising_edge(clk_i);
|
||||
|
||||
-- read miss w/ replace (tag 2 index 0)
|
||||
wbs_i.cyc_i <= '1';
|
||||
wbs_i.stb_i <= '1';
|
||||
wbs_i.we_i <= '0';
|
||||
wbs_i.adr_i <= x"000404";
|
||||
wait until rising_edge(clk_i);
|
||||
while wbs_o.ack_o = '0' loop
|
||||
wait until rising_edge(clk_i);
|
||||
end loop;
|
||||
assert wbs_o.dat_o = x"deadbeef" report "Read fail: expected 0xdeadbeef, got " & to_hstring(wbs_o.dat_o) severity error;
|
||||
wbs_i.cyc_i <= '0';
|
||||
wbs_i.stb_i <= '0';
|
||||
wait until rising_edge(clk_i);
|
||||
|
||||
wait;
|
||||
end process WaveGen_Proc;
|
||||
|
||||
-- memory simulation
|
||||
memory: process
|
||||
type mem_a is array(4*1024*1024-1 downto 0) of std_logic_vector(31 downto 0);
|
||||
variable mem : mem_a := (others => (others => '0'));
|
||||
variable base_adr : integer range 0 to (16*1024*1024/line_size)-1 := 0;
|
||||
begin
|
||||
-- initialize first 1k of memory with data for testing
|
||||
for i in 0 to 1023 loop
|
||||
mem(i) := x"ffff" & std_logic_vector(to_unsigned(i, 12)) & x"f";
|
||||
end loop;
|
||||
|
||||
while true loop
|
||||
wait until rising_edge(clk_i);
|
||||
if mem_rdrq = '1' then
|
||||
base_adr := to_integer(unsigned(mem_adr));
|
||||
for i in 0 to line_size-1 loop
|
||||
wait until rising_edge(clk_i);
|
||||
mem_ack <= '1';
|
||||
mem_dat_i <= mem(base_adr*line_size+i);
|
||||
end loop;
|
||||
wait until rising_edge(clk_i);
|
||||
mem_ack <= '0';
|
||||
elsif mem_wrrq = '1' then
|
||||
base_adr := to_integer(unsigned(mem_adr));
|
||||
mem_ack <= '1';
|
||||
wait until rising_edge(clk_i);
|
||||
for i in 0 to line_size-1 loop
|
||||
wait until rising_edge(clk_i);
|
||||
mem(base_adr*line_size+i) := mem_dat_o;
|
||||
end loop;
|
||||
mem_ack <= '0';
|
||||
end if;
|
||||
end loop;
|
||||
end process memory;
|
||||
|
||||
end testbench;
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
configuration wb_ddr_ctrl_wb_sc_fe_tb_testbench_cfg of wb_ddr_ctrl_wb_sc_fe_tb is
|
||||
for testbench
|
||||
end for;
|
||||
end wb_ddr_ctrl_wb_sc_fe_tb_testbench_cfg;
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
1737
tools/std_logic_1164_additions.vhdl
Normal file
1737
tools/std_logic_1164_additions.vhdl
Normal file
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,7 @@
|
||||
<db_ref_list>
|
||||
<db_ref path="./isim.wdb" id="1" type="auto">
|
||||
<top_modules>
|
||||
<top_module name="intercon_package" />
|
||||
<top_module name="numeric_std" />
|
||||
<top_module name="std_logic_1164" />
|
||||
<top_module name="std_logic_arith" />
|
||||
@@ -334,48 +335,13 @@
|
||||
<obj_property name="ElementShortName">rst_i</obj_property>
|
||||
<obj_property name="ObjectShortName">rst_i</obj_property>
|
||||
</wvobject>
|
||||
<wvobject fp_name="/wb_ddr_ctrl_tb/DUT/wb_0/system_cd_inst/dat_i" type="array" db_ref_id="1">
|
||||
<obj_property name="ElementShortName">dat_i[31:0]</obj_property>
|
||||
<obj_property name="ObjectShortName">dat_i[31:0]</obj_property>
|
||||
<obj_property name="Radix">HEXRADIX</obj_property>
|
||||
<wvobject fp_name="/wb_ddr_ctrl_tb/DUT/wb_0/system_cd_inst/wbs_i" type="array" db_ref_id="1">
|
||||
<obj_property name="ElementShortName">wbs_i</obj_property>
|
||||
<obj_property name="ObjectShortName">wbs_i</obj_property>
|
||||
</wvobject>
|
||||
<wvobject fp_name="/wb_ddr_ctrl_tb/DUT/wb_0/system_cd_inst/dat_o" type="array" db_ref_id="1">
|
||||
<obj_property name="ElementShortName">dat_o[31:0]</obj_property>
|
||||
<obj_property name="ObjectShortName">dat_o[31:0]</obj_property>
|
||||
<obj_property name="Radix">HEXRADIX</obj_property>
|
||||
</wvobject>
|
||||
<wvobject fp_name="/wb_ddr_ctrl_tb/DUT/wb_0/system_cd_inst/ack_o" type="logic" db_ref_id="1">
|
||||
<obj_property name="ElementShortName">ack_o</obj_property>
|
||||
<obj_property name="ObjectShortName">ack_o</obj_property>
|
||||
</wvobject>
|
||||
<wvobject fp_name="/wb_ddr_ctrl_tb/DUT/wb_0/system_cd_inst/adr_i" type="array" db_ref_id="1">
|
||||
<obj_property name="ElementShortName">adr_i[25:2]</obj_property>
|
||||
<obj_property name="ObjectShortName">adr_i[25:2]</obj_property>
|
||||
<obj_property name="Radix">HEXRADIX</obj_property>
|
||||
</wvobject>
|
||||
<wvobject fp_name="/wb_ddr_ctrl_tb/DUT/wb_0/system_cd_inst/cyc_i" type="logic" db_ref_id="1">
|
||||
<obj_property name="ElementShortName">cyc_i</obj_property>
|
||||
<obj_property name="ObjectShortName">cyc_i</obj_property>
|
||||
</wvobject>
|
||||
<wvobject fp_name="/wb_ddr_ctrl_tb/DUT/wb_0/system_cd_inst/sel_i" type="array" db_ref_id="1">
|
||||
<obj_property name="ElementShortName">sel_i[3:0]</obj_property>
|
||||
<obj_property name="ObjectShortName">sel_i[3:0]</obj_property>
|
||||
</wvobject>
|
||||
<wvobject fp_name="/wb_ddr_ctrl_tb/DUT/wb_0/system_cd_inst/stb_i" type="logic" db_ref_id="1">
|
||||
<obj_property name="ElementShortName">stb_i</obj_property>
|
||||
<obj_property name="ObjectShortName">stb_i</obj_property>
|
||||
</wvobject>
|
||||
<wvobject fp_name="/wb_ddr_ctrl_tb/DUT/wb_0/system_cd_inst/we_i" type="logic" db_ref_id="1">
|
||||
<obj_property name="ElementShortName">we_i</obj_property>
|
||||
<obj_property name="ObjectShortName">we_i</obj_property>
|
||||
</wvobject>
|
||||
<wvobject fp_name="/wb_ddr_ctrl_tb/DUT/wb_0/system_cd_inst/cti_i" type="array" db_ref_id="1">
|
||||
<obj_property name="ElementShortName">cti_i[2:0]</obj_property>
|
||||
<obj_property name="ObjectShortName">cti_i[2:0]</obj_property>
|
||||
</wvobject>
|
||||
<wvobject fp_name="/wb_ddr_ctrl_tb/DUT/wb_0/system_cd_inst/bte_i" type="array" db_ref_id="1">
|
||||
<obj_property name="ElementShortName">bte_i[1:0]</obj_property>
|
||||
<obj_property name="ObjectShortName">bte_i[1:0]</obj_property>
|
||||
<wvobject fp_name="/wb_ddr_ctrl_tb/DUT/wb_0/system_cd_inst/wbs_o" type="array" db_ref_id="1">
|
||||
<obj_property name="ElementShortName">wbs_o</obj_property>
|
||||
<obj_property name="ObjectShortName">wbs_o</obj_property>
|
||||
</wvobject>
|
||||
<wvobject fp_name="/wb_ddr_ctrl_tb/DUT/wb_0/system_cd_inst/ddr_din" type="array" db_ref_id="1">
|
||||
<obj_property name="ElementShortName">ddr_din[63:0]</obj_property>
|
||||
|
||||
5617
wb_ddr_ctrl_wb_sc_fe_tb.wcfg
Normal file
5617
wb_ddr_ctrl_wb_sc_fe_tb.wcfg
Normal file
File diff suppressed because it is too large
Load Diff
21
zy2000/zpu_config.vhd
Normal file
21
zy2000/zpu_config.vhd
Normal file
@@ -0,0 +1,21 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
package zpu_config is
|
||||
-- generate trace output or not.
|
||||
constant Generate_Trace : boolean := false;
|
||||
constant wordPower : integer := 5;
|
||||
-- during simulation, set this to '0' to get matching trace.txt
|
||||
constant DontCareValue : std_logic := '-';
|
||||
-- Clock frequency in MHz.
|
||||
constant ZPU_Frequency : std_logic_vector(7 downto 0) := x"32"; -- 50 MHz
|
||||
|
||||
-- This is the msb address bit. bytes=2^(maxAddrBitIncIO+1)
|
||||
constant maxAddrBitIncIO : integer := 27;
|
||||
|
||||
-- start byte address of stack.
|
||||
-- point to top of RAM - 2*words
|
||||
constant spStart : std_logic_vector(maxAddrBitIncIO downto 0) := x"3fffff8";
|
||||
|
||||
end zpu_config;
|
||||
948
zy2000/zpu_core.vhd
Normal file
948
zy2000/zpu_core.vhd
Normal file
@@ -0,0 +1,948 @@
|
||||
|
||||
-- Company: ZPU4 generic memory interface CPU
|
||||
-- Engineer: Øyvind Harboe
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
use IEEE.STD_LOGIC_arith.ALL;
|
||||
|
||||
library work;
|
||||
use work.zpu_config.all;
|
||||
use work.zpupkg.all;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
entity zpu_core is
|
||||
Port ( clk : in std_logic;
|
||||
areset : in std_logic;
|
||||
enable : in std_logic;
|
||||
mem_req : out std_logic;
|
||||
mem_we : out std_logic;
|
||||
mem_ack : in std_logic;
|
||||
mem_read : in std_logic_vector(wordSize-1 downto 0);
|
||||
mem_write : out std_logic_vector(wordSize-1 downto 0);
|
||||
out_mem_addr : out std_logic_vector(maxAddrBitIncIO downto 0);
|
||||
mem_writeMask: out std_logic_vector(wordBytes-1 downto 0);
|
||||
interrupt : in std_logic;
|
||||
break : out std_logic;
|
||||
zpu_status : out std_logic_vector(63 downto 0));
|
||||
end zpu_core;
|
||||
|
||||
architecture behave of zpu_core is
|
||||
|
||||
type InsnType is
|
||||
(
|
||||
State_AddTop,
|
||||
State_Dup,
|
||||
State_DupStackB,
|
||||
State_Pop,
|
||||
State_Popdown,
|
||||
State_Add,
|
||||
State_Or,
|
||||
State_And,
|
||||
State_Store,
|
||||
State_AddSP,
|
||||
State_Shift,
|
||||
State_Nop,
|
||||
State_Im,
|
||||
State_LoadSP,
|
||||
State_StoreSP,
|
||||
State_Emulate,
|
||||
State_Load,
|
||||
State_PushPC,
|
||||
State_PushSP,
|
||||
State_PopPC,
|
||||
State_PopPCRel,
|
||||
State_Not,
|
||||
State_Flip,
|
||||
State_PopSP,
|
||||
State_Neqbranch,
|
||||
State_Eq,
|
||||
State_Loadb,
|
||||
State_Mult,
|
||||
State_Lessthan,
|
||||
State_Lessthanorequal,
|
||||
State_Ulessthanorequal,
|
||||
State_Ulessthan,
|
||||
State_Pushspadd,
|
||||
State_Call,
|
||||
State_Callpcrel,
|
||||
State_Sub,
|
||||
State_Break,
|
||||
State_Storeb,
|
||||
State_Interrupt,
|
||||
State_InsnFetch
|
||||
);
|
||||
|
||||
type StateType is
|
||||
(
|
||||
State_Idle, -- using first state first on the list out of paranoia
|
||||
State_Load2,
|
||||
State_Popped,
|
||||
State_LoadSP2,
|
||||
State_LoadSP3,
|
||||
State_AddSP2,
|
||||
State_Fetch,
|
||||
State_Execute,
|
||||
State_Decode,
|
||||
State_Decode2,
|
||||
State_Resync,
|
||||
|
||||
State_StoreSP2,
|
||||
State_Resync2,
|
||||
State_Resync3,
|
||||
State_Loadb2,
|
||||
State_Storeb2,
|
||||
State_Mult2,
|
||||
State_Mult3,
|
||||
State_Mult5,
|
||||
State_Mult6,
|
||||
State_Mult4,
|
||||
State_BinaryOpResult
|
||||
);
|
||||
|
||||
|
||||
signal pc : std_logic_vector(maxAddrBitIncIO downto 0);
|
||||
signal sp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
|
||||
signal incSp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
|
||||
signal incIncSp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
|
||||
signal decSp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
|
||||
signal stackA : std_logic_vector(wordSize-1 downto 0);
|
||||
signal binaryOpResult : std_logic_vector(wordSize-1 downto 0);
|
||||
signal multResult2 : std_logic_vector(wordSize-1 downto 0);
|
||||
signal multResult3 : std_logic_vector(wordSize-1 downto 0);
|
||||
signal multResult : std_logic_vector(wordSize-1 downto 0);
|
||||
signal multA : std_logic_vector(wordSize-1 downto 0);
|
||||
signal multB : std_logic_vector(wordSize-1 downto 0);
|
||||
signal stackB : std_logic_vector(wordSize-1 downto 0);
|
||||
signal idim_flag : std_logic;
|
||||
signal busy : std_logic;
|
||||
signal mem_readEnable : std_logic;
|
||||
signal mem_addr : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
|
||||
signal mem_delayAddr : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
|
||||
signal mem_delayReadEnable : std_logic;
|
||||
signal mem_busy : std_logic;
|
||||
signal decodeWord : std_logic_vector(wordSize-1 downto 0);
|
||||
|
||||
|
||||
signal state : StateType;
|
||||
signal insn : InsnType;
|
||||
type InsnArray is array(0 to wordBytes-1) of InsnType;
|
||||
signal decodedOpcode : InsnArray;
|
||||
|
||||
type OpcodeArray is array(0 to wordBytes-1) of std_logic_vector(7 downto 0);
|
||||
|
||||
signal opcode : OpcodeArray;
|
||||
|
||||
|
||||
|
||||
|
||||
signal begin_inst : std_logic;
|
||||
signal trace_opcode : std_logic_vector(7 downto 0);
|
||||
signal trace_pc : std_logic_vector(maxAddrBitIncIO downto 0);
|
||||
signal trace_sp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
|
||||
signal trace_topOfStack : std_logic_vector(wordSize-1 downto 0);
|
||||
signal trace_topOfStackB : std_logic_vector(wordSize-1 downto 0);
|
||||
|
||||
signal out_mem_req : std_logic;
|
||||
|
||||
signal inInterrupt : std_logic;
|
||||
|
||||
-- state machine.
|
||||
|
||||
begin
|
||||
|
||||
zpu_status(maxAddrBitIncIO downto 0) <= trace_pc;
|
||||
zpu_status(31) <= '1';
|
||||
zpu_status(39 downto 32) <= trace_opcode;
|
||||
zpu_status(40) <= '1' when (state = State_Idle) else '0';
|
||||
zpu_status(62) <= '1';
|
||||
|
||||
traceFileGenerate:
|
||||
if Generate_Trace generate
|
||||
trace_file: trace port map (
|
||||
clk => clk,
|
||||
begin_inst => begin_inst,
|
||||
pc => trace_pc,
|
||||
opcode => trace_opcode,
|
||||
sp => trace_sp,
|
||||
memA => trace_topOfStack,
|
||||
memB => trace_topOfStackB,
|
||||
busy => busy,
|
||||
intsp => (others => 'U')
|
||||
);
|
||||
end generate;
|
||||
|
||||
|
||||
-- the memory subsystem will tell us one cycle later whether or
|
||||
-- not it is busy
|
||||
out_mem_addr(maxAddrBitIncIO downto minAddrBit) <= mem_addr;
|
||||
out_mem_addr(minAddrBit-1 downto 0) <= (others => '0');
|
||||
mem_req <= out_mem_req;
|
||||
|
||||
incSp <= sp + 1;
|
||||
incIncSp <= sp + 2;
|
||||
decSp <= sp - 1;
|
||||
|
||||
mem_busy <= out_mem_req and not mem_ack; -- '1' when the memory is busy
|
||||
|
||||
opcodeControl:
|
||||
process(clk, areset)
|
||||
variable tOpcode : std_logic_vector(OpCode_Size-1 downto 0);
|
||||
variable spOffset : std_logic_vector(4 downto 0);
|
||||
variable tSpOffset : std_logic_vector(4 downto 0);
|
||||
variable nextPC : std_logic_vector(maxAddrBitIncIO downto 0);
|
||||
variable tNextState : InsnType;
|
||||
variable tDecodedOpcode : InsnArray;
|
||||
variable tMultResult : std_logic_vector(wordSize*2-1 downto 0);
|
||||
begin
|
||||
if areset = '1' then
|
||||
state <= State_Idle;
|
||||
break <= '0';
|
||||
sp <= spStart(maxAddrBitIncIO downto minAddrBit);
|
||||
|
||||
pc <= (others => '0');
|
||||
idim_flag <= '0';
|
||||
begin_inst <= '0';
|
||||
mem_we <= '0';
|
||||
multA <= (others => '0');
|
||||
multB <= (others => '0');
|
||||
mem_writeMask <= (others => '1');
|
||||
out_mem_req <= '0';
|
||||
mem_addr <= (others => DontCareValue);
|
||||
mem_write <= (others => DontCareValue);
|
||||
inInterrupt <= '0';
|
||||
elsif (clk'event and clk = '1') then
|
||||
-- we must multiply unconditionally to get pipelined multiplication
|
||||
tMultResult := multA * multB;
|
||||
multResult3 <= multResult2;
|
||||
multResult2 <= multResult;
|
||||
multResult <= tMultResult(wordSize-1 downto 0);
|
||||
|
||||
|
||||
spOffset(4):=not opcode(conv_integer(pc(byteBits-1 downto 0)))(4);
|
||||
spOffset(3 downto 0):=opcode(conv_integer(pc(byteBits-1 downto 0)))(3 downto 0);
|
||||
nextPC := pc + 1;
|
||||
|
||||
-- prepare trace snapshot
|
||||
trace_opcode <= opcode(conv_integer(pc(byteBits-1 downto 0)));
|
||||
trace_pc <= pc;
|
||||
trace_sp <= sp;
|
||||
trace_topOfStack <= stackA;
|
||||
trace_topOfStackB <= stackB;
|
||||
begin_inst <= '0';
|
||||
|
||||
-- we terminate the requeset as soon as we get acknowledge
|
||||
if mem_ack = '1' then
|
||||
out_mem_req <= '0';
|
||||
mem_we <= '0';
|
||||
end if;
|
||||
|
||||
if interrupt='0' then
|
||||
inInterrupt <= '0'; -- no longer in an interrupt
|
||||
end if;
|
||||
|
||||
case state is
|
||||
when State_Idle =>
|
||||
if enable='1' then
|
||||
state <= State_Resync;
|
||||
end if;
|
||||
-- Initial state of ZPU, fetch top of stack + first instruction
|
||||
when State_Resync =>
|
||||
if mem_busy='0' then
|
||||
mem_addr <= sp;
|
||||
out_mem_req <= '1';
|
||||
state <= State_Resync2;
|
||||
end if;
|
||||
when State_Resync2 =>
|
||||
if mem_busy='0' then
|
||||
stackA <= mem_read;
|
||||
mem_addr <= incSp;
|
||||
out_mem_req <= '1';
|
||||
state <= State_Resync3;
|
||||
end if;
|
||||
when State_Resync3 =>
|
||||
if mem_busy='0' then
|
||||
stackB <= mem_read;
|
||||
mem_addr <= pc(maxAddrBitIncIO downto minAddrBit);
|
||||
out_mem_req <= '1';
|
||||
state <= State_Decode;
|
||||
end if;
|
||||
when State_Decode =>
|
||||
if mem_busy='0' then
|
||||
decodeWord <= mem_read;
|
||||
state <= State_Decode2;
|
||||
end if;
|
||||
when State_Decode2 =>
|
||||
-- decode 4 instructions in parallel
|
||||
for i in 0 to wordBytes-1 loop
|
||||
tOpcode := decodeWord((wordBytes-1-i+1)*8-1 downto (wordBytes-1-i)*8);
|
||||
|
||||
tSpOffset(4):=not tOpcode(4);
|
||||
tSpOffset(3 downto 0):=tOpcode(3 downto 0);
|
||||
|
||||
opcode(i) <= tOpcode;
|
||||
if (tOpcode(7 downto 7)=OpCode_Im) then
|
||||
tNextState:=State_Im;
|
||||
elsif (tOpcode(7 downto 5)=OpCode_StoreSP) then
|
||||
if tSpOffset = 0 then
|
||||
tNextState := State_Pop;
|
||||
elsif tSpOffset=1 then
|
||||
tNextState := State_PopDown;
|
||||
else
|
||||
tNextState :=State_StoreSP;
|
||||
end if;
|
||||
elsif (tOpcode(7 downto 5)=OpCode_LoadSP) then
|
||||
if tSpOffset = 0 then
|
||||
tNextState :=State_Dup;
|
||||
elsif tSpOffset = 1 then
|
||||
tNextState :=State_DupStackB;
|
||||
else
|
||||
tNextState :=State_LoadSP;
|
||||
end if;
|
||||
elsif (tOpcode(7 downto 5)=OpCode_Emulate) then
|
||||
tNextState :=State_Emulate;
|
||||
if tOpcode(5 downto 0)=OpCode_Neqbranch then
|
||||
tNextState :=State_Neqbranch;
|
||||
elsif tOpcode(5 downto 0)=OpCode_Eq then
|
||||
tNextState :=State_Eq;
|
||||
elsif tOpcode(5 downto 0)=OpCode_Lessthan then
|
||||
tNextState :=State_Lessthan;
|
||||
elsif tOpcode(5 downto 0)=OpCode_Lessthanorequal then
|
||||
--tNextState :=State_Lessthanorequal;
|
||||
elsif tOpcode(5 downto 0)=OpCode_Ulessthan then
|
||||
tNextState :=State_Ulessthan;
|
||||
elsif tOpcode(5 downto 0)=OpCode_Ulessthanorequal then
|
||||
--tNextState :=State_Ulessthanorequal;
|
||||
elsif tOpcode(5 downto 0)=OpCode_Loadb then
|
||||
tNextState :=State_Loadb;
|
||||
elsif tOpcode(5 downto 0)=OpCode_Mult then
|
||||
tNextState :=State_Mult;
|
||||
elsif tOpcode(5 downto 0)=OpCode_Storeb then
|
||||
tNextState :=State_Storeb;
|
||||
elsif tOpcode(5 downto 0)=OpCode_Pushspadd then
|
||||
tNextState :=State_Pushspadd;
|
||||
elsif tOpcode(5 downto 0)=OpCode_Callpcrel then
|
||||
tNextState :=State_Callpcrel;
|
||||
elsif tOpcode(5 downto 0)=OpCode_Call then
|
||||
--tNextState :=State_Call;
|
||||
elsif tOpcode(5 downto 0)=OpCode_Sub then
|
||||
tNextState :=State_Sub;
|
||||
elsif tOpcode(5 downto 0)=OpCode_PopPCRel then
|
||||
--tNextState :=State_PopPCRel;
|
||||
end if;
|
||||
elsif (tOpcode(7 downto 4)=OpCode_AddSP) then
|
||||
if tSpOffset = 0 then
|
||||
tNextState := State_Shift;
|
||||
elsif tSpOffset = 1 then
|
||||
tNextState := State_AddTop;
|
||||
else
|
||||
tNextState :=State_AddSP;
|
||||
end if;
|
||||
else
|
||||
case tOpcode(3 downto 0) is
|
||||
when OpCode_Nop =>
|
||||
tNextState :=State_Nop;
|
||||
when OpCode_PushSP =>
|
||||
tNextState :=State_PushSP;
|
||||
when OpCode_PopPC =>
|
||||
tNextState :=State_PopPC;
|
||||
when OpCode_Add =>
|
||||
tNextState :=State_Add;
|
||||
when OpCode_Or =>
|
||||
tNextState :=State_Or;
|
||||
when OpCode_And =>
|
||||
tNextState :=State_And;
|
||||
when OpCode_Load =>
|
||||
tNextState :=State_Load;
|
||||
when OpCode_Not =>
|
||||
tNextState :=State_Not;
|
||||
when OpCode_Flip =>
|
||||
tNextState :=State_Flip;
|
||||
when OpCode_Store =>
|
||||
tNextState :=State_Store;
|
||||
when OpCode_PopSP =>
|
||||
tNextState :=State_PopSP;
|
||||
when others =>
|
||||
tNextState := State_Break;
|
||||
|
||||
end case;
|
||||
end if;
|
||||
tDecodedOpcode(i) := tNextState;
|
||||
|
||||
end loop;
|
||||
|
||||
insn <= tDecodedOpcode(conv_integer(pc(byteBits-1 downto 0)));
|
||||
|
||||
-- once we wrap, we need to fetch
|
||||
tDecodedOpcode(0) := State_InsnFetch;
|
||||
|
||||
decodedOpcode <= tDecodedOpcode;
|
||||
state <= State_Execute;
|
||||
|
||||
|
||||
|
||||
-- Each instruction must:
|
||||
--
|
||||
-- 1. set idim_flag
|
||||
-- 2. increase pc if applicable
|
||||
-- 3. set next state if appliable
|
||||
-- 4. do it's operation
|
||||
|
||||
when State_Execute =>
|
||||
insn <= decodedOpcode(conv_integer(nextPC(byteBits-1 downto 0)));
|
||||
|
||||
case insn is
|
||||
when State_InsnFetch =>
|
||||
state <= State_Fetch;
|
||||
when State_Im =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '1';
|
||||
pc <= pc + 1;
|
||||
|
||||
if idim_flag='1' then
|
||||
stackA(wordSize-1 downto 7) <= stackA(wordSize-8 downto 0);
|
||||
stackA(6 downto 0) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(6 downto 0);
|
||||
else
|
||||
out_mem_req <= '1';
|
||||
mem_we <= '1';
|
||||
mem_addr <= incSp;
|
||||
mem_write <= stackB;
|
||||
stackB <= stackA;
|
||||
sp <= decSp;
|
||||
for i in wordSize-1 downto 7 loop
|
||||
stackA(i) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(6);
|
||||
end loop;
|
||||
stackA(6 downto 0) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(6 downto 0);
|
||||
end if;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_StoreSP =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
state <= State_StoreSP2;
|
||||
|
||||
out_mem_req <= '1';
|
||||
mem_we <= '1';
|
||||
mem_addr <= sp+spOffset;
|
||||
mem_write <= stackA;
|
||||
stackA <= stackB;
|
||||
sp <= incSp;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
|
||||
|
||||
when State_LoadSP =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
state <= State_LoadSP2;
|
||||
|
||||
sp <= decSp;
|
||||
out_mem_req <= '1';
|
||||
mem_we <= '1';
|
||||
mem_addr <= incSp;
|
||||
mem_write <= stackB;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_Emulate =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
sp <= decSp;
|
||||
out_mem_req <= '1';
|
||||
mem_we <= '1';
|
||||
mem_addr <= incSp;
|
||||
mem_write <= stackB;
|
||||
stackA <= (others => DontCareValue);
|
||||
stackA(maxAddrBitIncIO downto 0) <= pc + 1;
|
||||
stackB <= stackA;
|
||||
|
||||
-- The emulate address is:
|
||||
-- 98 7654 3210
|
||||
-- 0000 00aa aaa0 0000
|
||||
pc <= (others => '0');
|
||||
pc(9 downto 5) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(4 downto 0);
|
||||
state <= State_Fetch;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_Callpcrel =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
stackA <= (others => DontCareValue);
|
||||
stackA(maxAddrBitIncIO downto 0) <= pc + 1;
|
||||
|
||||
pc <= pc + stackA(maxAddrBitIncIO downto 0);
|
||||
state <= State_Fetch;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_Call =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
stackA <= (others => DontCareValue);
|
||||
stackA(maxAddrBitIncIO downto 0) <= pc + 1;
|
||||
pc <= stackA(maxAddrBitIncIO downto 0);
|
||||
state <= State_Fetch;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_AddSP =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
state <= State_AddSP2;
|
||||
|
||||
out_mem_req <= '1';
|
||||
mem_addr <= sp+spOffset;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_PushSP =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
pc <= pc + 1;
|
||||
|
||||
sp <= decSp;
|
||||
stackA <= (others => '0');
|
||||
stackA(maxAddrBitIncIO downto minAddrBit) <= sp;
|
||||
stackB <= stackA;
|
||||
out_mem_req <= '1';
|
||||
mem_we <= '1';
|
||||
mem_addr <= incSp;
|
||||
mem_write <= stackB;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_PopPC =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
pc <= stackA(maxAddrBitIncIO downto 0);
|
||||
sp <= incSp;
|
||||
|
||||
out_mem_req <= '1';
|
||||
mem_we <= '1';
|
||||
mem_addr <= incSp;
|
||||
mem_write <= stackB;
|
||||
state <= State_Resync;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_PopPCRel =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
pc <= stackA(maxAddrBitIncIO downto 0) + pc;
|
||||
sp <= incSp;
|
||||
|
||||
out_mem_req <= '1';
|
||||
mem_we <= '1';
|
||||
mem_addr <= incSp;
|
||||
mem_write <= stackB;
|
||||
state <= State_Resync;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_Add =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
stackA <= stackA + stackB;
|
||||
|
||||
out_mem_req <= '1';
|
||||
mem_addr <= incIncSp;
|
||||
sp <= incSp;
|
||||
state <= State_Popped;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_Sub =>
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
binaryOpResult <= stackB - stackA;
|
||||
state <= State_BinaryOpResult;
|
||||
when State_Pop =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
mem_addr <= incIncSp;
|
||||
out_mem_req <= '1';
|
||||
sp <= incSp;
|
||||
stackA <= stackB;
|
||||
state <= State_Popped;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_PopDown =>
|
||||
if mem_busy='0' then
|
||||
-- PopDown leaves top of stack unchanged
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
mem_addr <= incIncSp;
|
||||
out_mem_req <= '1';
|
||||
sp <= incSp;
|
||||
state <= State_Popped;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_Or =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
stackA <= stackA or stackB;
|
||||
out_mem_req <= '1';
|
||||
mem_addr <= incIncSp;
|
||||
sp <= incSp;
|
||||
state <= State_Popped;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_And =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
|
||||
stackA <= stackA and stackB;
|
||||
out_mem_req <= '1';
|
||||
mem_addr <= incIncSp;
|
||||
sp <= incSp;
|
||||
state <= State_Popped;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_Eq =>
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
|
||||
binaryOpResult <= (others => '0');
|
||||
if (stackA=stackB) then
|
||||
binaryOpResult(0) <= '1';
|
||||
end if;
|
||||
state <= State_BinaryOpResult;
|
||||
when State_Ulessthan =>
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
|
||||
binaryOpResult <= (others => '0');
|
||||
if (stackA<stackB) then
|
||||
binaryOpResult(0) <= '1';
|
||||
end if;
|
||||
state <= State_BinaryOpResult;
|
||||
when State_Ulessthanorequal =>
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
|
||||
binaryOpResult <= (others => '0');
|
||||
if (stackA<=stackB) then
|
||||
binaryOpResult(0) <= '1';
|
||||
end if;
|
||||
state <= State_BinaryOpResult;
|
||||
when State_Lessthan =>
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
|
||||
binaryOpResult <= (others => '0');
|
||||
if (signed(stackA)<signed(stackB)) then
|
||||
binaryOpResult(0) <= '1';
|
||||
end if;
|
||||
state <= State_BinaryOpResult;
|
||||
when State_Lessthanorequal =>
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
|
||||
binaryOpResult <= (others => '0');
|
||||
if (signed(stackA)<=signed(stackB)) then
|
||||
binaryOpResult(0) <= '1';
|
||||
end if;
|
||||
state <= State_BinaryOpResult;
|
||||
when State_Load =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
state <= State_Load2;
|
||||
|
||||
mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
|
||||
out_mem_req <= '1';
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
|
||||
when State_Dup =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
pc <= pc + 1;
|
||||
|
||||
sp <= decSp;
|
||||
stackB <= stackA;
|
||||
mem_write <= stackB;
|
||||
mem_addr <= incSp;
|
||||
out_mem_req <= '1';
|
||||
mem_we <= '1';
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_DupStackB =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
pc <= pc + 1;
|
||||
|
||||
sp <= decSp;
|
||||
stackA <= stackB;
|
||||
stackB <= stackA;
|
||||
mem_write <= stackB;
|
||||
mem_addr <= incSp;
|
||||
out_mem_req <= '1';
|
||||
mem_we <= '1';
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_Store =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
pc <= pc + 1;
|
||||
mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
|
||||
mem_write <= stackB;
|
||||
out_mem_req <= '1';
|
||||
mem_we <= '1';
|
||||
sp <= incIncSp;
|
||||
state <= State_Resync;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_PopSP =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
pc <= pc + 1;
|
||||
|
||||
mem_write <= stackB;
|
||||
mem_addr <= incSp;
|
||||
out_mem_req <= '1';
|
||||
mem_we <= '1';
|
||||
sp <= stackA(maxAddrBitIncIO downto minAddrBit);
|
||||
state <= State_Resync;
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_Nop =>
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
pc <= pc + 1;
|
||||
when State_Not =>
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
pc <= pc + 1;
|
||||
|
||||
stackA <= not stackA;
|
||||
when State_Flip =>
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
pc <= pc + 1;
|
||||
|
||||
for i in 0 to wordSize-1 loop
|
||||
stackA(i) <= stackA(wordSize-1-i);
|
||||
end loop;
|
||||
when State_AddTop =>
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
pc <= pc + 1;
|
||||
|
||||
stackA <= stackA + stackB;
|
||||
when State_Shift =>
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
pc <= pc + 1;
|
||||
|
||||
stackA(wordSize-1 downto 1) <= stackA(wordSize-2 downto 0);
|
||||
stackA(0) <= '0';
|
||||
when State_Pushspadd =>
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
pc <= pc + 1;
|
||||
|
||||
stackA <= (others => '0');
|
||||
stackA(maxAddrBitIncIO downto minAddrBit) <= stackA(maxAddrBitIncIO-minAddrBit downto 0)+sp;
|
||||
when State_Neqbranch =>
|
||||
-- branches are almost always taken as they form loops
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
sp <= incIncSp;
|
||||
if (stackB/=0) then
|
||||
pc <= stackA(maxAddrBitIncIO downto 0) + pc;
|
||||
else
|
||||
pc <= pc + 1;
|
||||
end if;
|
||||
-- need to fetch stack again.
|
||||
state <= State_Resync;
|
||||
when State_Mult =>
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
|
||||
multA <= stackA;
|
||||
multB <= stackB;
|
||||
state <= State_Mult2;
|
||||
when State_Break =>
|
||||
report "Break instruction encountered" severity failure;
|
||||
break <= '1';
|
||||
|
||||
when State_Loadb =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
state <= State_Loadb2;
|
||||
|
||||
mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
|
||||
out_mem_req <= '1';
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
when State_Storeb =>
|
||||
if mem_busy='0' then
|
||||
begin_inst <= '1';
|
||||
idim_flag <= '0';
|
||||
state <= State_Storeb2;
|
||||
|
||||
mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
|
||||
out_mem_req <= '1';
|
||||
else
|
||||
insn <= insn;
|
||||
end if;
|
||||
|
||||
when others =>
|
||||
-- sp <= (others => DontCareValue);
|
||||
report "Illegal instruction" severity failure;
|
||||
break <= '1';
|
||||
end case;
|
||||
|
||||
|
||||
when State_StoreSP2 =>
|
||||
if mem_busy='0' then
|
||||
mem_addr <= incSp;
|
||||
out_mem_req <= '1';
|
||||
state <= State_Popped;
|
||||
end if;
|
||||
when State_LoadSP2 =>
|
||||
if mem_busy='0' then
|
||||
state <= State_LoadSP3;
|
||||
out_mem_req <= '1';
|
||||
mem_addr <= sp+spOffset+1;
|
||||
end if;
|
||||
when State_LoadSP3 =>
|
||||
if mem_busy='0' then
|
||||
pc <= pc + 1;
|
||||
state <= State_Execute;
|
||||
stackB <= stackA;
|
||||
stackA <= mem_read;
|
||||
end if;
|
||||
when State_AddSP2 =>
|
||||
if mem_busy='0' then
|
||||
pc <= pc + 1;
|
||||
state <= State_Execute;
|
||||
stackA <= stackA + mem_read;
|
||||
end if;
|
||||
when State_Load2 =>
|
||||
if mem_busy='0' then
|
||||
stackA <= mem_read;
|
||||
pc <= pc + 1;
|
||||
state <= State_Execute;
|
||||
end if;
|
||||
when State_Loadb2 =>
|
||||
if mem_busy='0' then
|
||||
stackA <= (others => '0');
|
||||
stackA(7 downto 0) <= mem_read(((wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8+7) downto (wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8);
|
||||
pc <= pc + 1;
|
||||
state <= State_Execute;
|
||||
end if;
|
||||
when State_Storeb2 =>
|
||||
if mem_busy='0' then
|
||||
mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
|
||||
mem_write <= mem_read;
|
||||
mem_write(((wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8+7) downto (wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8) <= stackB(7 downto 0) ;
|
||||
out_mem_req <= '1';
|
||||
mem_we <= '1';
|
||||
pc <= pc + 1;
|
||||
sp <= incIncSp;
|
||||
state <= State_Resync;
|
||||
end if;
|
||||
when State_Fetch =>
|
||||
if mem_busy='0' then
|
||||
if interrupt='1' and inInterrupt='0' and idim_flag='0' then
|
||||
-- We got an interrupt
|
||||
inInterrupt <= '1';
|
||||
|
||||
sp <= decSp;
|
||||
out_mem_req <= '1';
|
||||
mem_we <= '1';
|
||||
mem_addr <= incSp;
|
||||
mem_write <= stackB;
|
||||
stackA <= (others => DontCareValue);
|
||||
stackA(maxAddrBitIncIO downto 0) <= pc;
|
||||
stackB <= stackA;
|
||||
|
||||
pc <= conv_std_logic_vector(32, maxAddrBitIncIo+1); -- interrupt address
|
||||
|
||||
report "ZPU jumped to interrupt!" severity note;
|
||||
else
|
||||
mem_addr <= pc(maxAddrBitIncIO downto minAddrBit);
|
||||
out_mem_req <= '1';
|
||||
state <= State_Decode;
|
||||
end if;
|
||||
end if;
|
||||
when State_Mult2 =>
|
||||
state <= State_Mult3;
|
||||
when State_Mult3 =>
|
||||
state <= State_Mult4;
|
||||
when State_Mult4 =>
|
||||
state <= State_Mult5;
|
||||
when State_Mult5 =>
|
||||
stackA <= multResult3;
|
||||
state <= State_Mult6;
|
||||
when State_Mult6 =>
|
||||
if mem_busy='0' then
|
||||
out_mem_req <= '1';
|
||||
mem_addr <= incIncSp;
|
||||
sp <= incSp;
|
||||
state <= State_Popped;
|
||||
end if;
|
||||
when State_BinaryOpResult =>
|
||||
if mem_busy='0' then
|
||||
-- NB!!!! we know that the memory isn't busy at this point!!!!
|
||||
out_mem_req <= '1';
|
||||
mem_addr <= incIncSp;
|
||||
sp <= incSp;
|
||||
stackA <= binaryOpResult;
|
||||
state <= State_Popped;
|
||||
end if;
|
||||
when State_Popped =>
|
||||
if mem_busy='0' then
|
||||
pc <= pc + 1;
|
||||
stackB <= mem_read;
|
||||
state <= State_Execute;
|
||||
end if;
|
||||
when others =>
|
||||
-- sp <= (others => DontCareValue);
|
||||
report "Illegal state" severity failure;
|
||||
break <= '1';
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
|
||||
end behave;
|
||||
121
zy2000/zpu_system.vhd
Normal file
121
zy2000/zpu_system.vhd
Normal file
@@ -0,0 +1,121 @@
|
||||
-- ZPU
|
||||
--
|
||||
-- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
|
||||
--
|
||||
-- The FreeBSD license
|
||||
--
|
||||
-- Redistribution and use in source and binary forms, with or without
|
||||
-- modification, are permitted provided that the following conditions
|
||||
-- are met:
|
||||
--
|
||||
-- 1. Redistributions of source code must retain the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer.
|
||||
-- 2. Redistributions in binary form must reproduce the above
|
||||
-- copyright notice, this list of conditions and the following
|
||||
-- disclaimer in the documentation and/or other materials
|
||||
-- provided with the distribution.
|
||||
--
|
||||
-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY
|
||||
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
--
|
||||
-- The views and conclusions contained in the software and documentation
|
||||
-- are those of the authors and should not be interpreted as representing
|
||||
-- official policies, either expressed or implied, of the ZPU Project.
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.all;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.all;
|
||||
|
||||
library work;
|
||||
use work.intercon_package.all;
|
||||
use work.zpupkg.all;
|
||||
use work.zpu_config.all;
|
||||
|
||||
entity zpu_system is
|
||||
generic(
|
||||
simulate : boolean := false);
|
||||
port (
|
||||
areset : in std_logic;
|
||||
cpu_clk : in std_logic;
|
||||
|
||||
-- ZPU Control signals
|
||||
enable : in std_logic;
|
||||
interrupt : in std_logic;
|
||||
|
||||
zpu_status : out std_logic_vector(63 downto 0);
|
||||
|
||||
-- wishbone interfaces
|
||||
zpu_wb_i : in zpu_wbm_i_type;
|
||||
zpu_wb_o : out zpu_wbm_o_type
|
||||
);
|
||||
end zpu_system;
|
||||
|
||||
architecture behave of zpu_system is
|
||||
|
||||
component zpu_wb_bridge
|
||||
port (
|
||||
clk : in std_logic;
|
||||
areset : in std_logic;
|
||||
mem_req : in std_logic;
|
||||
mem_we : in std_logic;
|
||||
mem_ack : out std_logic;
|
||||
mem_read : out std_logic_vector(wordSize-1 downto 0);
|
||||
mem_write : in std_logic_vector(wordSize-1 downto 0);
|
||||
out_mem_addr : in std_logic_vector(maxAddrBitIncIO downto 0);
|
||||
mem_writeMask : in std_logic_vector(wordBytes-1 downto 0);
|
||||
zpu_wb_i : in zpu_wbm_i_type;
|
||||
zpu_wb_o : out zpu_wbm_o_type);
|
||||
end component;
|
||||
|
||||
signal mem_req : std_logic;
|
||||
signal mem_we : std_logic;
|
||||
signal mem_ack : std_logic;
|
||||
signal mem_read : std_logic_vector(wordSize-1 downto 0);
|
||||
signal mem_write : std_logic_vector(wordSize-1 downto 0);
|
||||
signal out_mem_addr : std_logic_vector(maxAddrBitIncIO downto 0);
|
||||
signal mem_writeMask : std_logic_vector(wordBytes-1 downto 0);
|
||||
|
||||
|
||||
begin
|
||||
|
||||
my_zpu_core:
|
||||
zpu_core port map (
|
||||
clk => cpu_clk,
|
||||
areset => areset,
|
||||
enable => enable,
|
||||
mem_req => mem_req,
|
||||
mem_we => mem_we,
|
||||
mem_ack => mem_ack,
|
||||
mem_read => mem_read,
|
||||
mem_write => mem_write,
|
||||
out_mem_addr => out_mem_addr,
|
||||
mem_writeMask => mem_writeMask,
|
||||
interrupt => interrupt,
|
||||
zpu_status => zpu_status,
|
||||
break => open);
|
||||
|
||||
my_zpu_wb_bridge:
|
||||
zpu_wb_bridge port map (
|
||||
clk => cpu_clk,
|
||||
areset => areset,
|
||||
mem_req => mem_req,
|
||||
mem_we => mem_we,
|
||||
mem_ack => mem_ack,
|
||||
mem_read => mem_read,
|
||||
mem_write => mem_write,
|
||||
out_mem_addr => out_mem_addr,
|
||||
mem_writeMask => mem_writeMask,
|
||||
zpu_wb_i => zpu_wb_i,
|
||||
zpu_wb_o => zpu_wb_o);
|
||||
|
||||
end behave;
|
||||
84
zy2000/zpu_wb_bridge.vhd
Normal file
84
zy2000/zpu_wb_bridge.vhd
Normal file
@@ -0,0 +1,84 @@
|
||||
-- ZPU
|
||||
--
|
||||
-- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
|
||||
--
|
||||
-- The FreeBSD license
|
||||
--
|
||||
-- Redistribution and use in source and binary forms, with or without
|
||||
-- modification, are permitted provided that the following conditions
|
||||
-- are met:
|
||||
--
|
||||
-- 1. Redistributions of source code must retain the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer.
|
||||
-- 2. Redistributions in binary form must reproduce the above
|
||||
-- copyright notice, this list of conditions and the following
|
||||
-- disclaimer in the documentation and/or other materials
|
||||
-- provided with the distribution.
|
||||
--
|
||||
-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY
|
||||
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
--
|
||||
-- The views and conclusions contained in the software and documentation
|
||||
-- are those of the authors and should not be interpreted as representing
|
||||
-- official policies, either expressed or implied, of the ZPU Project.
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
|
||||
library work;
|
||||
use work.intercon_package.all;
|
||||
use work.zpupkg.all;
|
||||
use work.zpu_config.all;
|
||||
|
||||
entity zpu_wb_bridge is
|
||||
port (
|
||||
-- Native ZPU interface
|
||||
clk : in std_logic;
|
||||
areset : in std_logic;
|
||||
|
||||
mem_req : in std_logic;
|
||||
mem_we : in std_logic;
|
||||
mem_ack : out std_logic;
|
||||
mem_read : out std_logic_vector(wordSize-1 downto 0);
|
||||
mem_write : in std_logic_vector(wordSize-1 downto 0);
|
||||
out_mem_addr : in std_logic_vector(maxAddrBitIncIO downto 0);
|
||||
mem_writeMask : in std_logic_vector(wordBytes-1 downto 0);
|
||||
|
||||
-- Wishbone from ZPU
|
||||
zpu_wb_i : in zpu_wbm_i_type;
|
||||
zpu_wb_o : out zpu_wbm_o_type
|
||||
);
|
||||
|
||||
end zpu_wb_bridge;
|
||||
|
||||
architecture behave of zpu_wb_bridge is
|
||||
|
||||
begin
|
||||
|
||||
mem_read <= zpu_wb_i.dat_i;
|
||||
mem_ack <= zpu_wb_i.ack_i;
|
||||
|
||||
zpu_wb_o.adr_o <= out_mem_addr;
|
||||
zpu_wb_o.dat_o <= mem_write;
|
||||
zpu_wb_o.sel_o <= mem_writeMask;
|
||||
zpu_wb_o.stb_o <= mem_req;
|
||||
zpu_wb_o.cyc_o <= mem_req;
|
||||
zpu_wb_o.we_o <= mem_we;
|
||||
|
||||
end behave;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
168
zy2000/zpupkg.vhd
Normal file
168
zy2000/zpupkg.vhd
Normal file
@@ -0,0 +1,168 @@
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.all;
|
||||
use IEEE.STD_LOGIC_ARITH.all;
|
||||
|
||||
library work;
|
||||
use work.zpu_config.all;
|
||||
|
||||
package zpupkg is
|
||||
|
||||
-- This bit is set for read/writes to IO
|
||||
-- FIX!!! eventually this should be set to wordSize-1 so as to
|
||||
-- to make the address of IO independent of amount of memory
|
||||
-- reserved for CPU. Requires trivial tweaks in toolchain/runtime
|
||||
-- libraries.
|
||||
|
||||
constant byteBits : integer := wordPower-3; -- # of bits in a word that addresses bytes
|
||||
constant maxAddrBit : integer := maxAddrBitIncIO-1;
|
||||
constant ioBit : integer := maxAddrBit+1;
|
||||
constant wordSize : integer := 2**wordPower;
|
||||
constant wordBytes : integer := wordSize/8;
|
||||
constant minAddrBit : integer := byteBits;
|
||||
-- configurable internal stack size. Probably going to be 16 after toolchain is done
|
||||
constant stack_bits : integer := 5;
|
||||
constant stack_size : integer := 2**stack_bits;
|
||||
|
||||
component dualport_ram is
|
||||
port (clk : in std_logic;
|
||||
memAWriteEnable : in std_logic;
|
||||
memAAddr : in std_logic_vector(maxAddrBit downto minAddrBit);
|
||||
memAWrite : in std_logic_vector(wordSize-1 downto 0);
|
||||
memARead : out std_logic_vector(wordSize-1 downto 0);
|
||||
memBWriteEnable : in std_logic;
|
||||
memBAddr : in std_logic_vector(maxAddrBit downto minAddrBit);
|
||||
memBWrite : in std_logic_vector(wordSize-1 downto 0);
|
||||
memBRead : out std_logic_vector(wordSize-1 downto 0));
|
||||
end component;
|
||||
|
||||
component dram is
|
||||
port (clk : in std_logic;
|
||||
areset : in std_logic;
|
||||
mem_writeEnable : in std_logic;
|
||||
mem_readEnable : in std_logic;
|
||||
mem_addr : in std_logic_vector(maxAddrBit downto 0);
|
||||
mem_write : in std_logic_vector(wordSize-1 downto 0);
|
||||
mem_read : out std_logic_vector(wordSize-1 downto 0);
|
||||
mem_busy : out std_logic;
|
||||
mem_writeMask : in std_logic_vector(wordBytes-1 downto 0));
|
||||
end component;
|
||||
|
||||
|
||||
component trace is
|
||||
port(
|
||||
clk : in std_logic;
|
||||
begin_inst : in std_logic;
|
||||
pc : in std_logic_vector(maxAddrBitIncIO downto 0);
|
||||
opcode : in std_logic_vector(7 downto 0);
|
||||
sp : in std_logic_vector(maxAddrBitIncIO downto minAddrBit);
|
||||
memA : in std_logic_vector(wordSize-1 downto 0);
|
||||
memB : in std_logic_vector(wordSize-1 downto 0);
|
||||
busy : in std_logic;
|
||||
intSp : in std_logic_vector(stack_bits-1 downto 0)
|
||||
);
|
||||
end component;
|
||||
|
||||
component zpu_core is
|
||||
port ( clk : in std_logic;
|
||||
areset : in std_logic;
|
||||
enable : in std_logic;
|
||||
mem_req : out std_logic;
|
||||
mem_we : out std_logic;
|
||||
mem_ack : in std_logic;
|
||||
mem_read : in std_logic_vector(wordSize-1 downto 0);
|
||||
mem_write : out std_logic_vector(wordSize-1 downto 0);
|
||||
out_mem_addr : out std_logic_vector(maxAddrBitIncIO downto 0);
|
||||
mem_writeMask: out std_logic_vector(wordBytes-1 downto 0);
|
||||
interrupt : in std_logic;
|
||||
break : out std_logic;
|
||||
zpu_status : out std_logic_vector(63 downto 0));
|
||||
end component;
|
||||
|
||||
|
||||
|
||||
component timer is
|
||||
port(
|
||||
clk : in std_logic;
|
||||
areset : in std_logic;
|
||||
sample : in std_logic;
|
||||
reset : in std_logic;
|
||||
counter : out std_logic_vector(63 downto 0));
|
||||
end component;
|
||||
|
||||
component zpuio is
|
||||
port ( areset : in std_logic;
|
||||
cpu_clk : in std_logic;
|
||||
clk_status : in std_logic_vector(2 downto 0);
|
||||
cpu_din : in std_logic_vector(15 downto 0);
|
||||
cpu_a : in std_logic_vector(20 downto 0);
|
||||
cpu_we : in std_logic_vector(1 downto 0);
|
||||
cpu_re : in std_logic;
|
||||
cpu_dout : inout std_logic_vector(15 downto 0));
|
||||
end component;
|
||||
|
||||
|
||||
|
||||
|
||||
-- opcode decode constants
|
||||
constant OpCode_Im : std_logic_vector(7 downto 7) := "1";
|
||||
constant OpCode_StoreSP : std_logic_vector(7 downto 5) := "010";
|
||||
constant OpCode_LoadSP : std_logic_vector(7 downto 5) := "011";
|
||||
constant OpCode_Emulate : std_logic_vector(7 downto 5) := "001";
|
||||
constant OpCode_AddSP : std_logic_vector(7 downto 4) := "0001";
|
||||
constant OpCode_Short : std_logic_vector(7 downto 4) := "0000";
|
||||
|
||||
constant OpCode_Break : std_logic_vector(3 downto 0) := "0000";
|
||||
constant OpCode_Shiftleft: std_logic_vector(3 downto 0) := "0001";
|
||||
constant OpCode_PushSP : std_logic_vector(3 downto 0) := "0010";
|
||||
constant OpCode_PushInt : std_logic_vector(3 downto 0) := "0011";
|
||||
|
||||
constant OpCode_PopPC : std_logic_vector(3 downto 0) := "0100";
|
||||
constant OpCode_Add : std_logic_vector(3 downto 0) := "0101";
|
||||
constant OpCode_And : std_logic_vector(3 downto 0) := "0110";
|
||||
constant OpCode_Or : std_logic_vector(3 downto 0) := "0111";
|
||||
|
||||
constant OpCode_Load : std_logic_vector(3 downto 0) := "1000";
|
||||
constant OpCode_Not : std_logic_vector(3 downto 0) := "1001";
|
||||
constant OpCode_Flip : std_logic_vector(3 downto 0) := "1010";
|
||||
constant OpCode_Nop : std_logic_vector(3 downto 0) := "1011";
|
||||
|
||||
constant OpCode_Store : std_logic_vector(3 downto 0) := "1100";
|
||||
constant OpCode_PopSP : std_logic_vector(3 downto 0) := "1101";
|
||||
constant OpCode_Compare : std_logic_vector(3 downto 0) := "1110";
|
||||
constant OpCode_PopInt : std_logic_vector(3 downto 0) := "1111";
|
||||
|
||||
constant OpCode_Lessthan : std_logic_vector(5 downto 0) := conv_std_logic_vector(36, 6);
|
||||
constant OpCode_Lessthanorequal : std_logic_vector(5 downto 0) := conv_std_logic_vector(37, 6);
|
||||
constant OpCode_Ulessthan : std_logic_vector(5 downto 0) := conv_std_logic_vector(38, 6);
|
||||
constant OpCode_Ulessthanorequal : std_logic_vector(5 downto 0) := conv_std_logic_vector(39, 6);
|
||||
|
||||
constant OpCode_Swap : std_logic_vector(5 downto 0) := conv_std_logic_vector(40, 6);
|
||||
constant OpCode_Mult : std_logic_vector(5 downto 0) := conv_std_logic_vector(41, 6);
|
||||
|
||||
constant OpCode_Lshiftright : std_logic_vector(5 downto 0) := conv_std_logic_vector(42, 6);
|
||||
constant OpCode_Ashiftleft : std_logic_vector(5 downto 0) := conv_std_logic_vector(43, 6);
|
||||
constant OpCode_Ashiftright : std_logic_vector(5 downto 0) := conv_std_logic_vector(44, 6);
|
||||
constant OpCode_Call : std_logic_vector(5 downto 0) := conv_std_logic_vector(45, 6);
|
||||
|
||||
constant OpCode_Eq : std_logic_vector(5 downto 0) := conv_std_logic_vector(46, 6);
|
||||
constant OpCode_Neq : std_logic_vector(5 downto 0) := conv_std_logic_vector(47, 6);
|
||||
|
||||
constant OpCode_Sub : std_logic_vector(5 downto 0) := conv_std_logic_vector(49, 6);
|
||||
constant OpCode_Loadb : std_logic_vector(5 downto 0) := conv_std_logic_vector(51, 6);
|
||||
constant OpCode_Storeb : std_logic_vector(5 downto 0) := conv_std_logic_vector(52, 6);
|
||||
|
||||
constant OpCode_Eqbranch : std_logic_vector(5 downto 0) := conv_std_logic_vector(55, 6);
|
||||
constant OpCode_Neqbranch : std_logic_vector(5 downto 0) := conv_std_logic_vector(56, 6);
|
||||
constant OpCode_Poppcrel : std_logic_vector(5 downto 0) := conv_std_logic_vector(57, 6);
|
||||
|
||||
constant OpCode_Pushspadd : std_logic_vector(5 downto 0) := conv_std_logic_vector(61, 6);
|
||||
constant OpCode_Mult16x16 : std_logic_vector(5 downto 0) := conv_std_logic_vector(62, 6);
|
||||
constant OpCode_Callpcrel : std_logic_vector(5 downto 0) := conv_std_logic_vector(63, 6);
|
||||
|
||||
|
||||
|
||||
constant OpCode_Size : integer := 8;
|
||||
|
||||
|
||||
|
||||
end zpupkg;
|
||||
Reference in New Issue
Block a user