- Added synthesis contraints

- Added ZPU processor
- Optimized wb_ddr_ctrl_wb_dc* to meet timing
- Added cache frontend
This commit is contained in:
2013-03-04 12:55:59 +01:00
parent 34bec7d6c7
commit 321ea30ed8
23 changed files with 9737 additions and 134 deletions

View File

@@ -11,4 +11,5 @@ run
-sd coregen/
-rtlview no
-iob auto
-keep_hierarchy soft
-keep_hierarchy soft
-uc constr/2d_display_engine.xcf

View File

@@ -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) $<

View 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;

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -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,

View File

@@ -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 =>

View 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;

View 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;

View File

@@ -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

View File

@@ -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;

View 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;
-------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

BIN
vga.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

View File

@@ -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

File diff suppressed because it is too large Load Diff

21
zy2000/zpu_config.vhd Normal file
View 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
View 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
View 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
View 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
View 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;