Author SHA1 Message Date
jens a67fbb643b This commit was manufactured by cvs2svn to create tag 'MIPS_R9'.
git-svn-id: http://moon:8086/svn/vhdl/tags/MIPS_R9@271 cc03376c-175c-47c8-b038-4cd826a8556b
2009-01-20 21:26:49 +00:00
51 changed files with 9405 additions and 4016 deletions
Binary file not shown.
+15
View File
@@ -0,0 +1,15 @@
## NOTE: Do not edit this file.
##
vlib work
vcom -explicit -93 "../../../PCK_FIO-1.16/PCK_FIO.vhd"
vcom -explicit -93 "../src/core/mips_types.vhd"
vcom -explicit -93 "../src/core/mips_instr.vhd"
vcom -explicit -93 "../src/core/mips_muldiv.vhd"
vcom -explicit -93 "../src/tb_mips_muldiv.vhd"
vsim -t 1ps -lib work tb_mips_muldiv
do {tb_mips_muldiv.wdo}
view wave
view structure
view signals
run 8ms
+78
View File
@@ -0,0 +1,78 @@
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate -format Logic /tb_mips_muldiv/rst
add wave -noupdate -format Logic /tb_mips_muldiv/clk
add wave -noupdate -format Logic /tb_mips_muldiv/mul_divn
add wave -noupdate -format Logic /tb_mips_muldiv/start
add wave -noupdate -format Logic /tb_mips_muldiv/busy
add wave -noupdate -format Logic /tb_mips_muldiv/s_un
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/ref_hi
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/din_hi
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/din_lo
add wave -noupdate -format Logic /tb_mips_muldiv/hilo_sel
add wave -noupdate -format Logic /tb_mips_muldiv/hilo_we
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/dout
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/ref_result
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/md_result
add wave -noupdate -format Logic /tb_mips_muldiv/check
add wave -noupdate -format Logic /tb_mips_muldiv/uut/pre_sum_vld
add wave -noupdate -format Logic /tb_mips_muldiv/uut/mul_en
add wave -noupdate -format Logic /tb_mips_muldiv/uut/sum_en
add wave -noupdate -divider FSM
add wave -noupdate -format Literal /tb_mips_muldiv/uut/cycle_cnt
add wave -noupdate -format Logic /tb_mips_muldiv/uut/cycle_cnt_load
add wave -noupdate -format Literal /tb_mips_muldiv/uut/cycle_cnt_preset
add wave -noupdate -format Literal /tb_mips_muldiv/uut/s
add wave -noupdate -format Literal /tb_mips_muldiv/uut/sn
add wave -noupdate -divider {Multiplier internals}
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_mips_muldiv/uut/pprod
add wave -noupdate -format Literal /tb_mips_muldiv/uut/ppadd_cyi
add wave -noupdate -format Literal /tb_mips_muldiv/uut/ppadd_cyo
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/ppadd_op1
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/ppadd_op2
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/ppadd_res
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/pp_op2
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/pp_op2_r
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/add_op1
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/add_op2
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/add_res
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/pp_reg
add wave -noupdate -divider {Divider internals}
add wave -noupdate -format Logic /tb_mips_muldiv/busy
add wave -noupdate -format Logic /tb_mips_muldiv/s_un
add wave -noupdate -format Logic /tb_mips_muldiv/uut/div_start
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/din_hi
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/din_lo
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/result
add wave -noupdate -format Logic /tb_mips_muldiv/uut/div_add_cyi
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/div_add_op1
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/div_add_op2
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/div_add_res
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/div_m
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/div_m_n
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/div_a
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/div_q
add wave -noupdate -format Logic /tb_mips_muldiv/uut/div_qbit
add wave -noupdate -format Logic /tb_mips_muldiv/uut/div_en
add wave -noupdate -divider FSM
add wave -noupdate -format Literal /tb_mips_muldiv/uut/cycle_cnt
add wave -noupdate -format Logic /tb_mips_muldiv/uut/cycle_cnt_load
add wave -noupdate -format Literal /tb_mips_muldiv/uut/cycle_cnt_preset
add wave -noupdate -format Literal /tb_mips_muldiv/uut/s
add wave -noupdate -format Literal /tb_mips_muldiv/uut/sn
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {7735999838 ps} 0} {{Cursor 2} {512321 ps} 0}
configure wave -namecolwidth 149
configure wave -valuecolwidth 171
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 100
configure wave -griddelta 40
configure wave -timeline 1
update
WaveRestoreZoom {0 ps} {8400 us}
+57
View File
@@ -0,0 +1,57 @@
## NOTE: Do not edit this file.
##
vlib work
# RAMS
vcom -explicit -93 "../../../misc/dpram_2w2r.vhd"
vcom -explicit -93 "../../../misc/dpram_1w1r.vhd"
vcom -explicit -93 "../../../misc/dpram_1w1r_dist.vhd"
# FIFOS
vcom -explicit -93 "../../../FIFO/src/fifo_ctrl_pkg.vhd"
vcom -explicit -93 "../../../FIFO/src/sync_fifo_ctrl.vhd"
vcom -explicit -93 "../../../FIFO/src/fifo_sync_dist.vhd"
# UART
vcom -explicit -93 "../../../uart/bbfifo_16x8.vhd"
vcom -explicit -93 "../../../uart/kcuart_rx.vhd"
vcom -explicit -93 "../../../uart/kcuart_tx.vhd"
vcom -explicit -93 "../../../uart/uart_rx.vhd"
vcom -explicit -93 "../../../uart/uart_tx.vhd"
vcom -explicit -93 "../../../uart/uart_wb.vhd"
# GPIO
vcom -explicit -93 "../../../misc/gpio_wb.vhd"
# Async port
vcom -explicit -93 "../../../misc/async_types.vhd"
vcom -explicit -93 "../../../misc/async_port_wb.vhd"
vcom -explicit -93 "../src/async_defs.vhd"
# ROM
vcom -explicit -93 "../src/bootloader.ROM.vhd"
vcom -explicit -93 "../../../misc/rom_wb.vhd"
# MIPS
vcom -explicit -93 "../src/core/mips_types.vhd"
vcom -explicit -93 "../src/core/mips_instr.vhd"
vcom -explicit -93 "../src/core/mips_idecode_rom.vhd"
vcom -explicit -93 "../src/core/mips_reg.vhd"
vcom -explicit -93 "../src/core/mips_shifter.vhd"
vcom -explicit -93 "../src/core/mips_alu.vhd"
vcom -explicit -93 "../src/core/mips_muldiv.vhd"
vcom -explicit -93 "../src/core/mips_cop.vhd"
vcom -explicit -93 "../src/core/mips_icache.vhd"
vcom -explicit -93 "../src/core/mips_dcache.vhd"
vcom -explicit -93 "../src/core/mips_biu.vhd"
vcom -explicit -93 "../src/core/mips_bcu.vhd"
vcom -explicit -93 "../src/core/mips_pipeline.vhd"
vcom -explicit -93 "../src/core/mips_top.vhd"
vcom -explicit -93 "../src/tb_mips_top.vhd"
vsim -t 1ps -lib work tb_mips_top
do {tb_mips_top.wdo}
view wave
view structure
view signals
run 1600us
+67
View File
@@ -0,0 +1,67 @@
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate -divider {TOP interface}
add wave -noupdate -format Logic /tb_mips_top/clk
add wave -noupdate -format Literal /tb_mips_top/debug
add wave -noupdate -format Logic /tb_mips_top/stb_o
add wave -noupdate -format Logic /tb_mips_top/ack_i
add wave -noupdate -format Logic /tb_mips_top/srdy_i
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/addr_o
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/dat_i
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/dat_o
add wave -noupdate -format Logic /tb_mips_top/we_o
add wave -noupdate -format Literal /tb_mips_top/sel_o
add wave -noupdate -format Logic /tb_mips_top/cyc_o
add wave -noupdate -format Logic /tb_mips_top/mrdy_o
add wave -noupdate -format Literal /tb_mips_top/int
add wave -noupdate -divider {External components}
add wave -noupdate -format Logic /tb_mips_top/clk
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/gpo0
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/gpo1
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/gpi0
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/gpi1
add wave -noupdate -format Logic /tb_mips_top/clk
add wave -noupdate -format Logic /tb_mips_top/rx
add wave -noupdate -format Logic /tb_mips_top/tx
add wave -noupdate -format Logic /tb_mips_top/clk
add wave -noupdate -format Literal /tb_mips_top/mem_area
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/sram_a
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/sram_d
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/flash_a
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/flash_d
add wave -noupdate -format Logic /tb_mips_top/flash_cs_n
add wave -noupdate -format Logic /tb_mips_top/flash_oe_n
add wave -noupdate -format Logic /tb_mips_top/sram_cs_n
add wave -noupdate -format Literal /tb_mips_top/sram_wr_n
add wave -noupdate -format Logic /tb_mips_top/sram_oe_n
add wave -noupdate -divider ALU
add wave -noupdate -format Logic /tb_mips_top/clk
add wave -noupdate -format Literal /tb_mips_top/uut/inst_pipeline/hdu
add wave -noupdate -divider PC
add wave -noupdate -format Logic /tb_mips_top/clk
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/uut/inst_pipeline/pc
add wave -noupdate -divider PC
add wave -noupdate -format Logic /tb_mips_top/clk
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_mips_top/uut/inst_pipeline/id_stage
add wave -noupdate -format Logic /tb_mips_top/clk
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_mips_top/uut/inst_pipeline/ex_stage
add wave -noupdate -format Logic /tb_mips_top/clk
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_mips_top/uut/inst_pipeline/mem_stage
add wave -noupdate -format Logic /tb_mips_top/clk
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_mips_top/uut/inst_pipeline/wb_stage
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {1199854590 ps} 0}
configure wave -namecolwidth 188
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 100
configure wave -griddelta 40
configure wave -timeline 1
update
WaveRestoreZoom {0 ps} {1260 us}
+60
View File
@@ -0,0 +1,60 @@
-------------------------------------------------------------------------
-- Project: MIPS System controller
-- This file:
--
-- Copyright (C) 2008 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
use work.async_types.all;
package async_defs is
constant ts_flash : async_timespec_t :=
(
ncyc_access => 1,
ncyc_pulse_rd => 12,
ncyc_pulse_wr => 7,
ncyc_cs_hold => 1,
ncyc_release => 1,
ncyc_pulse_rst => 8,
pol_cs => '0',
pol_oe => '0',
pol_we => '0',
pol_rst => '0'
);
constant ts_sram : async_timespec_t :=
(
ncyc_access => 1,
ncyc_pulse_rd => 12,
ncyc_pulse_wr => 7,
ncyc_cs_hold => 1,
ncyc_release => 1,
ncyc_pulse_rst => 8,
pol_cs => '0',
pol_oe => '0',
pol_we => '0',
pol_rst => '0'
);
end async_defs;
File diff suppressed because it is too large Load Diff
+431
View File
@@ -0,0 +1,431 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
library work;
use work.mips_types.all;
ENTITY dcache IS
Generic
(
cache_size : natural := 2048; -- words
line_size : natural := 8 -- words
);
Port
(
RST_I : in STD_LOGIC;
CLK_I : in STD_LOGIC;
ACK_I : in STD_LOGIC;
SRDY_I : in STD_LOGIC;
ADDR_O : out word_t;
DAT_I : in word_t;
STB_O : out STD_LOGIC;
CYC_O : out STD_LOGIC;
en : in STD_LOGIC;
cpu_en : in STD_LOGIC;
cpu_we : in STD_LOGIC;
cpu_be : in unsigned(3 downto 0);
cpu_addr : in word_t;
cpu_din : in word_t;
cpu_dout : out word_t;
cpu_busy : out STD_LOGIC
);
END dcache;
ARCHITECTURE behavior OF dcache IS
COMPONENT dpram_1w1r
GENERIC
(
addr_width : integer := 3;
data_width : integer := 8
);
PORT (
clka : in STD_LOGIC;
clkb : in STD_LOGIC;
en_a : in STD_LOGIC;
en_b : in STD_LOGIC;
we_a : in STD_LOGIC;
addr_a : in unsigned (addr_width-1 downto 0);
addr_b : in unsigned (addr_width-1 downto 0);
din_a : in unsigned (data_width-1 downto 0);
dout_b : out unsigned (data_width-1 downto 0)
);
END COMPONENT;
COMPONENT dpram_2w2r is
GENERIC
(
addr_width : integer := 3;
data_width : integer := 8
);
PORT
(
clk_a : in STD_LOGIC;
clk_b : in STD_LOGIC;
en_a : in STD_LOGIC;
en_b : in STD_LOGIC;
we_a : in STD_LOGIC;
we_b : in STD_LOGIC;
addr_a : in unsigned (addr_width-1 downto 0);
addr_b : in unsigned (addr_width-1 downto 0);
din_a : in unsigned (data_width-1 downto 0);
din_b : in unsigned (data_width-1 downto 0);
dout_a : out unsigned (data_width-1 downto 0);
dout_b : out unsigned (data_width-1 downto 0)
);
END COMPONENT;
function lg2(x : natural) return natural is
begin
return natural(ceil(log2(real(x))));
end lg2;
function po2(x : natural) return natural is
begin
return 2**lg2(x);
end po2;
constant word_index_width : natural := lg2(line_size);
constant cache_index_width : natural := lg2(cache_size) - word_index_width;
constant tag_width : natural := 32 - word_index_width - cache_index_width - 2;
constant tag_parity_width : natural := 3;
constant tram_data_width : natural := 1 + tag_parity_width + tag_width;
constant tram_addr_width : natural := cache_index_width;
subtype tram_data_t is unsigned (tram_data_width-1 downto 0);
type dcache_entry_t is record
valid : std_logic;
tv_p : unsigned(tag_parity_width-1 downto 0);
tag : unsigned(tag_width-1 downto 0);
end record;
alias cpu_word_index is cpu_addr(word_index_width+1 downto 2);
alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
function to_dcache_entry(x : tram_data_t) return dcache_entry_t is
variable result : dcache_entry_t;
begin
result.valid := x(0);
result.tv_p := x(3 downto 1);
result.tag := x(tag_width+3 downto 4);
return result;
end to_dcache_entry;
function to_tram_data(x : dcache_entry_t) return tram_data_t is
variable result : tram_data_t;
begin
result(0) := x.valid;
result(3 downto 1) := x.tv_p;
result(tag_width+3 downto 4) := x.tag;
return result;
end to_tram_data;
type cache_state_t is (init, ready, flush, mem_request, mem_access, mem_wait, mem_data, upd_cache, rd_cache);
signal s, sn : cache_state_t;
signal cache_busy : std_logic;
signal cache_hit : std_logic;
signal tag_match : std_logic;
signal word_index_reg : unsigned(word_index_width-1 downto 0);
signal cache_index_reg : unsigned(cache_index_width-1 downto 0);
signal tag_index_reg : unsigned(tag_width-1 downto 0);
signal cache_entry_in : dcache_entry_t;
signal cache_entry_out : dcache_entry_t;
signal cpu_dram_addr : unsigned(lg2(cache_size)-1 downto 0);
signal cpu_dram_dout : word_t;
signal cpu_dram_din : word_t;
signal cpu_data_reg : word_t;
signal cpu_be_reg : unsigned(3 downto 0);
signal cpu_we_reg : std_logic;
signal ctrl_dram_en : std_logic;
signal ctrl_dram_addr : unsigned(lg2(cache_size)-1 downto 0);
signal ctrl_dram_din : word_t;
signal ctrl_dram_we : unsigned(3 downto 0);
signal cpu_dram_we : unsigned(3 downto 0);
signal cpu_dram_en : std_logic;
signal cpu_en2 : std_logic;
signal cpu_we2 : std_logic;
signal tram_addr_rd : unsigned(cache_index_width-1 downto 0);
signal tram_dout : tram_data_t;
signal tram_addr_wr : unsigned(cache_index_width-1 downto 0);
signal tram_din : tram_data_t;
signal tram_re : std_logic;
signal tram_we : std_logic;
signal ram_index_count : natural range 0 to 2**word_index_width-1;
signal ram_index_count_rst : std_logic;
signal cache_index_count : natural range 0 to 2**cache_index_width-1;
signal cache_index_count_en : std_logic;
signal mem_index_count : natural range 0 to 2**word_index_width-1;
signal mem_index_count_en : std_logic;
signal mem_index_count_rst : std_logic;
signal cpu_reg_en : std_logic;
signal was_miss : std_logic;
signal data_write : std_logic;
signal cpu_hit_we : std_logic;
signal instant_raw : std_logic;
begin
cpu_hit_we <= cpu_we2 and cache_hit;
cpu_index_register:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if RST_I = '1' then
cache_index_reg <= (others => '0');
tag_index_reg <= (others => '0');
elsif cpu_reg_en = '1' and en = '1' and instant_raw = '0' then
word_index_reg <= cpu_word_index;
cache_index_reg <= cpu_cache_index;
tag_index_reg <= cpu_tag;
end if;
end if;
end process;
cpu_data_register:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if RST_I = '1' then
cpu_we_reg <= '0';
elsif cpu_reg_en = '1' and en = '1' then
cpu_data_reg <= cpu_din;
cpu_be_reg <= cpu_be;
cpu_we_reg <= cpu_we;
end if;
end if;
end process;
cpu_was_wr_register:
process(CLK_I)
begin
if rising_edge(CLK_I) then
cpu_en2 <= '0';
cpu_we2 <= '0';
if cpu_en = '1' and en = '1' then
cpu_we2 <= cpu_we;
cpu_en2 <= '1';
cpu_dram_din <= cpu_din;
end if;
end if;
end process;
instant_raw_logic:
process(CLK_I)
begin
if rising_edge(CLK_I) then
instant_raw <= cpu_hit_we and cpu_en and en and not cpu_we;
end if;
end process;
inst_tag_ram : dpram_1w1r
GENERIC MAP (
addr_width => tram_addr_width,
data_width => tram_data_width
)
PORT MAP (
clka => CLK_I,
clkb => CLK_I,
en_a => '1',
en_b => tram_re,
we_a => tram_we,
addr_a => tram_addr_wr,
addr_b => tram_addr_rd,
din_a => tram_din,
dout_b => tram_dout
);
gen_data_ram:
for i in 0 to 3 generate
begin
inst_data_ram : dpram_2w2r
GENERIC MAP (
addr_width => lg2(cache_size),
data_width => word_t'length/4
)
PORT MAP (
clk_a => CLK_I,
clk_b => CLK_I,
en_a => ctrl_dram_en,
en_b => '1',
we_a => ctrl_dram_we(i),
we_b => cpu_dram_we(i),
addr_a => ctrl_dram_addr,
addr_b => cpu_dram_addr,
din_a => ctrl_dram_din(8*(i+1)-1 downto 8*i),
din_b => cpu_dram_din(8*(i+1)-1 downto 8*i),
dout_a => open,
dout_b => cpu_dram_dout(8*(i+1)-1 downto 8*i)
);
end generate;
cache_state_next:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if RST_I = '1' then
s <= init;
else
s <= sn;
end if;
end if;
end process;
cpu_busy <= cache_busy or instant_raw;
cpu_dout <= cpu_dram_dout;
tag_match <= '1' when tag_index_reg = cache_entry_out.tag else '0';
cache_hit <= tag_match and cache_entry_out.valid;
tram_din <= to_tram_data(cache_entry_in);
tram_addr_rd <= cpu_cache_index when was_miss = '0' else cache_index_reg;
cache_entry_out <= to_dcache_entry(tram_dout);
cpu_dram_addr <= (cpu_cache_index & cpu_word_index) when (was_miss = '0' and cpu_hit_we = '0' and instant_raw = '0') else (cache_index_reg & word_index_reg);
ADDR_O <= tag_index_reg & cache_index_reg & to_unsigned(mem_index_count, word_index_width) & "00";
ctrl_dram_addr <= cache_index_reg & to_unsigned(ram_index_count, word_index_width);
ctrl_dram_din <= DAT_I;
ctrl_dram_we <= (others => '1');
ctrl_dram_en <= data_write and ACK_I;
cpu_dram_we <= cpu_be_reg when (cpu_hit_we = '1') else (others => '0');
cache_state:
process(s, instant_raw, cache_hit, cache_index_count, ram_index_count, mem_index_count, cache_index_reg, ACK_I, tag_index_reg, cpu_en, SRDY_I, cpu_en2, cpu_we_reg)
begin
cpu_reg_en <= '0';
cache_busy <= '1';
tram_we <= '0';
cache_index_count_en <= '0';
ram_index_count_rst <= '0';
mem_index_count_en <= '0';
mem_index_count_rst <= '0';
CYC_O <= '0';
STB_O <= '0';
tram_re <= '0';
was_miss <= '0';
data_write <= '0';
tram_addr_wr <= to_unsigned(cache_index_count, cache_index_width);
cache_entry_in.tv_p <= (others => '0');
cache_entry_in.tag <= tag_index_reg;
cache_entry_in.valid <= '0';
sn <= s;
case s is
when init =>
sn <= flush;
when ready =>
cache_busy <= '0';
cpu_reg_en <= '1';
tram_re <= cpu_en;
if cpu_en2 = '1' then
if cache_hit = '0' and cpu_we_reg = '0' then
sn <= mem_request;
cpu_reg_en <= '0';
cache_busy <= '1';
CYC_O <= '1';
end if;
end if;
when flush =>
cache_index_count_en <= '1';
tram_addr_wr <= to_unsigned(cache_index_count, cache_index_width);
tram_we <= '1';
cache_entry_in.valid <= '0';
cache_entry_in.tag <= (others => '0');
if cache_index_count = 0 then
sn <= ready;
if cpu_en = '1' then
cpu_reg_en <= '1';
tram_re <= '1';
end if;
end if;
when mem_request =>
ram_index_count_rst <= '1';
mem_index_count_rst <= '1';
CYC_O <= '1';
if SRDY_I = '1' then
sn <= mem_access;
end if;
when mem_access =>
data_write <= '1';
mem_index_count_en <= '1';
CYC_O <= '1';
STB_O <= '1';
if mem_index_count = 2**word_index_width-1 then
if SRDY_I = '1' then
sn <= mem_data;
end if;
end if;
when mem_data =>
CYC_O <= '1';
data_write <= '1';
if ram_index_count = 2**word_index_width-1 then
if ACK_I = '1' then
sn <= upd_cache;
end if;
end if;
when upd_cache =>
tram_addr_wr <= cache_index_reg;
tram_we <= '1';
cache_entry_in.valid <= '1';
sn <= rd_cache;
when rd_cache =>
tram_re <= '1';
was_miss <= '1';
sn <= ready;
when others =>
sn <= ready;
end case;
end process;
cache_index_counter:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if cache_index_count_en = '0' then
cache_index_count <= 2**cache_index_width-1;
elsif cache_index_count /= 0 then
cache_index_count <= cache_index_count - 1;
end if;
end if;
end process;
ram_index_counter:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if ram_index_count_rst = '1' then
ram_index_count <= 0;
elsif data_write = '1' and ACK_I = '1' then
if ram_index_count /= 2**word_index_width-1 then
ram_index_count <= ram_index_count + 1;
end if;
end if;
end if;
end process;
mem_index_counter:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if mem_index_count_rst = '1' then
mem_index_count <= 0;
elsif mem_index_count_en = '1' and SRDY_I = '1' then
if mem_index_count /= 2**word_index_width-1 then
mem_index_count <= mem_index_count + 1;
end if;
end if;
end if;
end process;
end behavior;
+354
View File
@@ -0,0 +1,354 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
library work;
use work.mips_types.all;
ENTITY icache IS
Generic
(
cache_size : natural := 2048; -- words
line_size : natural := 8 -- words
);
Port
(
RST_I : in STD_LOGIC;
CLK_I : in STD_LOGIC;
ACK_I : in STD_LOGIC;
SRDY_I : in STD_LOGIC;
ADDR_O : out word_t;
DAT_I : in word_t;
STB_O : out STD_LOGIC;
CYC_O : out STD_LOGIC;
en : in STD_LOGIC;
cpu_en : in STD_LOGIC;
cpu_addr : in word_t;
cpu_dout : out word_t;
cpu_busy : out STD_LOGIC
);
END icache;
ARCHITECTURE behavior OF icache IS
COMPONENT dpram_1w1r
GENERIC
(
addr_width : integer := 3;
data_width : integer := 8
);
PORT (
clka : in STD_LOGIC;
clkb : in STD_LOGIC;
en_a : in STD_LOGIC;
en_b : in STD_LOGIC;
we_a : in STD_LOGIC;
addr_a : in unsigned (addr_width-1 downto 0);
addr_b : in unsigned (addr_width-1 downto 0);
din_a : in unsigned (data_width-1 downto 0);
dout_b : out unsigned (data_width-1 downto 0)
);
END COMPONENT;
function lg2(x : natural) return natural is
begin
return natural(ceil(log2(real(x))));
end lg2;
function po2(x : natural) return natural is
begin
return 2**lg2(x);
end po2;
constant word_index_width : natural := lg2(line_size);
constant cache_index_width : natural := lg2(cache_size) - word_index_width;
constant tag_width : natural := 32 - word_index_width - cache_index_width - 2;
constant tag_parity_width : natural := 3;
constant tag_ram_data_width : natural := 1 + tag_parity_width + tag_width;
constant tag_ram_addr_width : natural := cache_index_width;
subtype tag_ram_data_t is unsigned (tag_ram_data_width-1 downto 0);
type icache_entry_t is record
valid : std_logic;
tv_p : unsigned(tag_parity_width-1 downto 0);
tag : unsigned(tag_width-1 downto 0);
end record;
alias cpu_word_index is cpu_addr(word_index_width+1 downto 2);
alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
function to_icache_entry(x : tag_ram_data_t) return icache_entry_t is
variable result : icache_entry_t;
begin
result.valid := x(0);
result.tv_p := x(3 downto 1);
result.tag := x(tag_width+3 downto 4);
return result;
end to_icache_entry;
function to_tag_ram_data(x : icache_entry_t) return tag_ram_data_t is
variable result : tag_ram_data_t;
begin
result(0) := x.valid;
result(3 downto 1) := x.tv_p;
result(tag_width+3 downto 4) := x.tag;
return result;
end to_tag_ram_data;
type cache_state_t is (init, ready, flush, mem_request, mem_access, mem_wait, mem_data, upd_cache, rd_cache);
signal s, sn : cache_state_t;
signal cache_busy : std_logic;
signal cache_miss : std_logic;
signal tag_match : std_logic;
signal word_index_reg : unsigned(word_index_width-1 downto 0);
signal cache_index_reg : unsigned(cache_index_width-1 downto 0);
signal tag_index_reg : unsigned(tag_width-1 downto 0);
signal cache_entry_in : icache_entry_t;
signal cache_entry_out : icache_entry_t;
signal data_ram_addr_rd : unsigned(lg2(cache_size)-1 downto 0);
signal data_ram_data_rd : word_t;
signal data_ram_addr_wr : unsigned(lg2(cache_size)-1 downto 0);
signal data_ram_data_wr : word_t;
signal data_ram_we : std_logic;
signal data_ram_re : std_logic;
signal tag_ram_addr_rd : unsigned(cache_index_width-1 downto 0);
signal tag_ram_data_rd : tag_ram_data_t;
signal tag_ram_addr_wr : unsigned(cache_index_width-1 downto 0);
signal tag_ram_data_wr : tag_ram_data_t;
signal tag_ram_re : std_logic;
signal tag_ram_we : std_logic;
signal ram_index_count : natural range 0 to 2**word_index_width-1;
signal ram_index_count_rst : std_logic;
signal cache_index_count : natural range 0 to 2**cache_index_width-1;
signal cache_index_count_en : std_logic;
signal mem_index_count : natural range 0 to 2**word_index_width-1;
signal mem_index_count_en : std_logic;
signal mem_index_count_rst : std_logic;
signal cpu_reg_en : std_logic;
signal was_miss : std_logic;
signal data_write : std_logic;
begin
cpu_index_reg:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if RST_I = '1' then
cache_index_reg <= (others => '0');
tag_index_reg <= (others => '0');
elsif cpu_reg_en = '1' then
word_index_reg <= cpu_word_index;
cache_index_reg <= cpu_cache_index;
tag_index_reg <= cpu_tag;
end if;
end if;
end process;
inst_tag_ram : dpram_1w1r
GENERIC MAP (
addr_width => tag_ram_addr_width,
data_width => tag_ram_data_width
)
PORT MAP (
clka => CLK_I,
clkb => CLK_I,
en_a => '1',
en_b => tag_ram_re,
we_a => tag_ram_we,
addr_a => tag_ram_addr_wr,
addr_b => tag_ram_addr_rd,
din_a => tag_ram_data_wr,
dout_b => tag_ram_data_rd
);
inst_data_ram : dpram_1w1r
GENERIC MAP (
addr_width => lg2(cache_size),
data_width => word_t'length
)
PORT MAP (
clka => CLK_I,
clkb => CLK_I,
en_a => '1',
en_b => data_ram_re,
we_a => data_ram_we,
addr_a => data_ram_addr_wr,
addr_b => data_ram_addr_rd,
din_a => data_ram_data_wr,
dout_b => data_ram_data_rd
);
cache_state_next:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if RST_I = '1' then
s <= init;
else
s <= sn;
end if;
end if;
end process;
cpu_busy <= cache_busy;
cpu_dout <= data_ram_data_rd;
tag_match <= '1' when tag_index_reg = cache_entry_out.tag else '0';
cache_miss <= not (tag_match and cache_entry_out.valid);
tag_ram_data_wr <= to_tag_ram_data(cache_entry_in);
tag_ram_addr_rd <= cpu_cache_index when was_miss = '0' else cache_index_reg;
cache_entry_out <= to_icache_entry(tag_ram_data_rd);
data_ram_addr_rd <= (cpu_cache_index & cpu_word_index) when was_miss = '0' else (cache_index_reg & word_index_reg);
ADDR_O <= tag_index_reg & cache_index_reg & to_unsigned(mem_index_count, word_index_width) & "00";
data_ram_addr_wr <= cache_index_reg & to_unsigned(ram_index_count, word_index_width);
data_ram_data_wr <= DAT_I;
data_ram_we <= data_write and ACK_I;
cache_state:
process(s, cache_miss, cache_index_count, ram_index_count, mem_index_count, cache_index_reg, ACK_I, tag_index_reg, cpu_en, SRDY_I, en)
begin
cpu_reg_en <= '0';
cache_busy <= '1';
tag_ram_we <= '0';
cache_index_count_en <= '0';
ram_index_count_rst <= '0';
mem_index_count_en <= '0';
mem_index_count_rst <= '0';
CYC_O <= '0';
STB_O <= '0';
data_ram_re <= '0';
tag_ram_re <= '0';
was_miss <= '0';
data_write <= '0';
tag_ram_addr_wr <= to_unsigned(cache_index_count, cache_index_width);
cache_entry_in.tv_p <= (others => '0');
cache_entry_in.tag <= tag_index_reg;
cache_entry_in.valid <= '0';
sn <= s;
case s is
when init =>
sn <= flush;
when ready =>
if en = '1' then
cache_busy <= '0';
if cache_miss = '1' then
sn <= mem_request;
cpu_reg_en <= '0';
cache_busy <= '1';
CYC_O <= '1';
elsif cpu_en = '1' then
cpu_reg_en <= '1';
data_ram_re <= '1';
tag_ram_re <= '1';
end if;
end if;
when flush =>
cache_index_count_en <= '1';
tag_ram_addr_wr <= to_unsigned(cache_index_count, cache_index_width);
tag_ram_we <= '1';
cache_entry_in.valid <= '0';
cache_entry_in.tag <= (others => '0');
if cache_index_count = 0 then
sn <= ready;
if cpu_en = '1' then
cpu_reg_en <= '1';
data_ram_re <= '1';
tag_ram_re <= '1';
end if;
end if;
when mem_request =>
ram_index_count_rst <= '1';
mem_index_count_rst <= '1';
CYC_O <= '1';
if SRDY_I = '1' then
sn <= mem_access;
end if;
when mem_access =>
mem_index_count_en <= '1';
data_write <= '1';
CYC_O <= '1';
STB_O <= '1';
if mem_index_count = 2**word_index_width-1 then
if SRDY_I = '1' then
sn <= mem_data;
end if;
end if;
when mem_data =>
CYC_O <= '1';
data_write <= '1';
if ram_index_count = 2**word_index_width-1 then
if ACK_I = '1' then
sn <= upd_cache;
end if;
end if;
when upd_cache =>
tag_ram_addr_wr <= cache_index_reg;
tag_ram_we <= '1';
cache_entry_in.valid <= '1';
sn <= rd_cache;
when rd_cache =>
tag_ram_re <= '1';
data_ram_re <= '1';
was_miss <= '1';
sn <= ready;
when others =>
sn <= ready;
end case;
end process;
cache_index_counter:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if cache_index_count_en = '0' then
cache_index_count <= 2**cache_index_width-1;
elsif cache_index_count /= 0 then
cache_index_count <= cache_index_count - 1;
end if;
end if;
end process;
ram_index_counter:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if ram_index_count_rst = '1' then
ram_index_count <= 0;
elsif data_write = '1' and ACK_I = '1' then
if ram_index_count /= 2**word_index_width-1 then
ram_index_count <= ram_index_count + 1;
end if;
end if;
end if;
end process;
mem_index_counter:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if mem_index_count_rst = '1' then
mem_index_count <= 0;
elsif mem_index_count_en = '1' and SRDY_I = '1' then
if mem_index_count /= 2**word_index_width-1 then
mem_index_count <= mem_index_count + 1;
end if;
end if;
end if;
end process;
end behavior;
+184
View File
@@ -0,0 +1,184 @@
--------------------------------------------------------------------------
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
-- This file: The arithmetic logic unit
--
-- Copyright (C) 2008 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
use work.mips_types.all;
entity alu is
Generic
(
data_width : integer := 8
);
Port
(
op1_in : in unsigned (data_width-1 downto 0);
op2_in : in unsigned (data_width-1 downto 0);
op2_shifted : in unsigned (data_width-1 downto 0);
ctrl : in alu_ctrl_t;
result : out unsigned (data_width-1 downto 0);
flags : out alu_flags_t
);
end alu;
architecture Behavioral of alu is
signal sum_res : unsigned (data_width-1 downto 0);
signal and_res : unsigned (data_width-1 downto 0);
signal xor_res : unsigned (data_width-1 downto 0);
signal nor_res : unsigned (data_width-1 downto 0);
signal or_res : unsigned (data_width-1 downto 0);
signal eq, sa, sb, sr, c, z : STD_LOGIC;
signal lts, ltu : STD_LOGIC;
--------------------------------------------------------------------------
begin
eq <= '1' when op1_in = op2_in else '0' after 3 ns;
sa <= op1_in(op1_in'left);
sb <= op2_in(op2_in'left);
sr <= sum_res(sum_res'left);
z <= '1' when op1_in = (data_width-1 downto 0 => '0') else '0' after 2 ns;
flags.uvf <= (not ctrl.add) and ((sa and (not sb) and (not sr)) or ((not sa) and sb and sr));
flags.ovf <= ctrl.add and ((sa and sb and (not sr)) or ((not sa) and (not sb) and sr));
-- lts <= (not eq) and (((not c) and sa and sb) or (((not sr) and sa) or (sa and (not sb)) or (sr and (not sb))));
lts <= not eq and ((not c and sa) or (not sb and sa) or (not sb and sr));
ltu <= (not eq) and (not c);
flags.lts <= lts;
flags.ltu <= ltu;
flags.c <= c;
--------------------------------------------------------------------------
proc_op_and:
process(op1_in, op2_in)
variable x1, x2 : unsigned (data_width-1 downto 0);
begin
x1 := op1_in;
x2 := op2_in;
and_res <= (x1 and x2) after 1 ns;
end process;
--------------------------------------------------------------------------
proc_proc_xor:
process(op1_in, op2_in)
variable x1, x2 : unsigned (data_width-1 downto 0);
begin
x1 := op1_in;
x2 := op2_in;
xor_res <= (x1 xor x2) after 2 ns;
end process;
--------------------------------------------------------------------------
proc_proc_nor:
process(op1_in, op2_in)
variable x1, x2 : unsigned (data_width-1 downto 0);
begin
x1 := op1_in;
x2 := op2_in;
nor_res <= (x1 nor x2) after 1 ns;
end process;
--------------------------------------------------------------------------
proc_proc_or:
process(op1_in, op2_in)
variable x1, x2 : unsigned (data_width-1 downto 0);
begin
x1 := op1_in;
x2 := op2_in;
or_res <= (x1 or x2) after 1 ns;
end process;
--------------------------------------------------------------------------
proc_alu_out:
process(ctrl, sum_res, and_res, xor_res, nor_res, or_res, op2_shifted, lts, ltu)
begin
result <= sum_res;
case ctrl.outsel is
when alu_adder =>
result <= sum_res;
when alu_and =>
result <= and_res;
when alu_xor =>
result <= xor_res;
when alu_nor =>
result <= nor_res;
when alu_or =>
result <= or_res;
when alu_shift2 =>
result <= op2_shifted;
when alu_ltu =>
result <= (data_width-1 downto 1 => '0') & ltu;
when alu_lts =>
result <= (data_width-1 downto 1 => '0') & lts;
when others => null;
end case;
end process;
--------------------------------------------------------------------------
alu_addsub:
process(op1_in, op2_in, ctrl)
variable sum : unsigned(data_width+1 downto 0);
variable op1, op2 : unsigned(data_width+1 downto 0);
begin
op1 := '0' & op1_in & not ctrl.add;
if (ctrl.add = '1') then
op2 := '0' & op2_in & '0';
else
op2 := '0' & not op2_in & '1';
end if;
sum := op1 + op2;
-- Form sum + carry
sum_res <= unsigned(sum(data_width downto 1)) after 4 ns;
c <= sum(sum'left) after 4 ns;
end process;
--------------------------------------------------------------------------
end Behavioral;
+52
View File
@@ -0,0 +1,52 @@
--------------------------------------------------------------------------
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
-- This file: The arithmetic logic unit
--
-- Copyright (C) 2008 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
use work.mips_types.all;
entity bcu is
Generic
(
data_width : integer := 8
);
Port
(
op1_in : in unsigned (data_width-1 downto 0);
op2_in : in unsigned (data_width-1 downto 0);
flags : out bcu_flags_t
);
end bcu;
architecture Behavioral of bcu is
--------------------------------------------------------------------------
begin
flags.eq <= '1' when op1_in = op2_in else '0' after 3 ns;
flags.ltz <= op1_in(op1_in'left) after 1 ns;
--------------------------------------------------------------------------
end Behavioral;
+496
View File
@@ -0,0 +1,496 @@
--------------------------------------------------------------------------
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
-- This file: JIPS top file
--
-- Copyright (C) 2008 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
library work;
use work.mips_types.all;
entity biu is
Generic
(
icache_size : natural := 2048; -- words
dcache_size : natural := 2048 -- words
);
Port
(
RST_I : in STD_LOGIC;
CLK_I : in STD_LOGIC;
ACK_I : in STD_LOGIC;
SRDY_I : in STD_LOGIC;
ADDR_O : out word_t;
DAT_I : in word_t;
DAT_O : out word_t;
WE_O : out STD_LOGIC;
SEL_O : out unsigned(3 downto 0);
CYC_O : out STD_LOGIC;
STB_O : out STD_LOGIC;
MRDY_O : out STD_LOGIC;
cpu_imem_err : out STD_LOGIC;
cpu_imem_rdy : out STD_LOGIC;
cpu_imem_en : in STD_LOGIC;
cpu_imem_addr : in word_t;
cpu_imem_din : out word_t;
cpu_dmem_err : out STD_LOGIC;
cpu_dmem_rdy : out STD_LOGIC;
cpu_dmem_en : in STD_LOGIC;
cpu_dmem_we : in STD_LOGIC;
cpu_dmem_be : in unsigned(3 downto 0);
cpu_dmem_dout : in word_t;
cpu_dmem_din : out word_t;
cpu_dmem_addr : in word_t
);
end biu;
architecture behavior of biu is
COMPONENT icache
GENERIC
(
cache_size : natural; -- words
line_size : natural -- words
);
PORT
(
RST_I : in STD_LOGIC;
CLK_I : in STD_LOGIC;
ACK_I : in STD_LOGIC;
SRDY_I : in STD_LOGIC;
ADDR_O : out word_t;
DAT_I : in word_t;
STB_O : out STD_LOGIC;
CYC_O : out STD_LOGIC;
en : in STD_LOGIC;
cpu_en : in STD_LOGIC;
cpu_addr : in word_t;
cpu_dout : out word_t;
cpu_busy : out STD_LOGIC
);
END COMPONENT;
COMPONENT dcache
GENERIC
(
cache_size : natural; -- words
line_size : natural -- words
);
PORT
(
RST_I : in STD_LOGIC;
CLK_I : in STD_LOGIC;
ACK_I : in STD_LOGIC;
SRDY_I : in STD_LOGIC;
ADDR_O : out word_t;
DAT_I : in word_t;
STB_O : out STD_LOGIC;
CYC_O : out STD_LOGIC;
en : in STD_LOGIC;
cpu_en : in STD_LOGIC;
cpu_we : in STD_LOGIC;
cpu_be : in unsigned(3 downto 0);
cpu_addr : in word_t;
cpu_din : in word_t;
cpu_dout : out word_t;
cpu_busy : out STD_LOGIC
);
END COMPONENT;
type bus_state_t is (init, ready, icache_bus_access, dcache_bus_access, write_bus, read_bus, read_finish);
signal s, sn : bus_state_t;
signal bus_idle : std_logic;
signal busy : std_logic;
signal dmem_be : unsigned(3 downto 0);
signal dcache_dout : word_t;
signal dcache_mem_gnt : std_logic;
signal icache_mem_gnt : std_logic;
signal dmem_mem_wr_gnt : std_logic;
signal dmem_mem_rd_gnt : std_logic;
signal dcache_busy : std_logic;
signal icache_busy : std_logic;
signal CYC_O_icache : std_logic;
signal CYC_O_dcache : std_logic;
signal CYC_O_dmem_rd : std_logic;
signal CYC_O_dmem_wr : std_logic;
signal SRDY_I_icache : std_logic;
signal SRDY_I_dcache : std_logic;
signal ADDR_O_icache : word_t;
signal ADDR_O_dcache : word_t;
signal ADDR_O_dmem_rd : word_t;
signal ADDR_O_dmem_wr : word_t;
signal STB_O_icache : std_logic;
signal STB_O_dcache : std_logic;
signal STB_O_dmem_rd : std_logic;
signal STB_O_dmem_wr : std_logic;
signal DAT_I_dmem_rd : word_t;
signal DAT_O_dmem_wr : word_t;
signal SEL_O_dmem_wr : unsigned(3 downto 0);
signal dcached : std_logic;
signal dcache_en : std_logic;
signal uncached_access : std_logic;
type timeout_cnt_t is range 0 to 1E5-1;
signal bus_timeout_cnt : timeout_cnt_t;
signal bus_timeout : std_logic;
signal bout_fifo_din : unsigned(68 downto 0);
signal bout_fifo_dout : unsigned(68 downto 0);
signal bout_fifo_re : std_logic;
signal bout_fifo_we : std_logic;
signal bout_fifo_full : std_logic;
signal bout_fifo_empty : std_logic;
signal bout_rdy : std_logic;
alias bout_fifo_addr_in is bout_fifo_din(31 downto 0);
alias bout_fifo_data_in is bout_fifo_din(63 downto 32);
alias bout_fifo_sel_in is bout_fifo_din(67 downto 64);
alias bout_fifo_we_in is bout_fifo_din(68);
alias bout_fifo_addr_out is bout_fifo_dout(31 downto 0);
alias bout_fifo_data_out is bout_fifo_dout(63 downto 32);
alias bout_fifo_sel_out is bout_fifo_dout(67 downto 64);
alias bout_fifo_we_out is bout_fifo_dout(68);
signal write_fifo_din : unsigned(67 downto 0);
signal write_fifo_dout : unsigned(67 downto 0);
signal write_fifo_re : std_logic;
signal write_fifo_we : std_logic;
signal write_fifo_full : std_logic;
signal write_fifo_empty : std_logic;
signal write_busy : std_logic;
alias write_fifo_addr_in is write_fifo_din(31 downto 0);
alias write_fifo_data_in is write_fifo_din(63 downto 32);
alias write_fifo_sel_in is write_fifo_din(67 downto 64);
alias write_fifo_addr_out is write_fifo_dout(31 downto 0);
alias write_fifo_data_out is write_fifo_dout(63 downto 32);
alias write_fifo_sel_out is write_fifo_dout(67 downto 64);
signal read_cycle : std_logic;
begin
MRDY_O <= '1';
read_cyc_register:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if RST_I = '1' then
read_cycle <= '0';
else
read_cycle <= (dmem_mem_rd_gnt and CYC_O_dmem_rd)
or (dcache_mem_gnt and CYC_O_dcache)
or (icache_mem_gnt and CYC_O_icache);
end if;
end if;
end process;
CYC_O <= not bout_fifo_empty or read_cycle;
STB_O <= not bout_fifo_empty;
ADDR_O <= bout_fifo_addr_out;
DAT_O <= bout_fifo_data_out;
SEL_O <= bout_fifo_sel_out;
WE_O <= bout_fifo_we_out;
cpu_imem_rdy <= not icache_busy after 4.5 ns;
busy <= CYC_O_dmem_rd or dcache_busy or (write_busy);
cpu_dmem_rdy <= not busy after 4.5 ns;
inst_icache : icache
GENERIC MAP
(
cache_size => icache_size, -- words
line_size => 8
)
PORT MAP
(
CLK_I => CLK_I,
RST_I => RST_I,
STB_O => STB_O_icache,
CYC_O => CYC_O_icache,
ADDR_O => ADDR_O_icache,
DAT_I => DAT_I,
ACK_I => ACK_I,
SRDY_I => SRDY_I_icache,
en => '1',
cpu_en => cpu_imem_en,
cpu_addr => cpu_imem_addr,
cpu_dout => cpu_imem_din,
cpu_busy => icache_busy
);
SRDY_I_icache <= bout_rdy and icache_mem_gnt;
inst_dcache : dcache
GENERIC MAP
(
cache_size => dcache_size, -- words
line_size => 8
)
PORT MAP
(
CLK_I => CLK_I,
RST_I => RST_I,
CYC_O => CYC_O_dcache,
STB_O => STB_O_dcache,
ADDR_O => ADDR_O_dcache,
DAT_I => DAT_I,
ACK_I => ACK_I,
SRDY_I => SRDY_I_dcache,
en => dcached,
cpu_en => dcache_en,
cpu_we => cpu_dmem_we,
cpu_be => cpu_dmem_be,
cpu_addr => cpu_dmem_addr,
cpu_din => cpu_dmem_dout,
cpu_dout => dcache_dout,
cpu_busy => dcache_busy
);
SRDY_I_dcache <= bout_rdy and dcache_mem_gnt;
dcached <= '1' when cpu_dmem_addr(31 downto 28) /= X"A" else '0';
cpu_dmem_din <= dcache_dout when uncached_access = '0' else DAT_I_dmem_rd;
dcache_en <= cpu_dmem_en and not busy;
-- Instantiate synchronous FIFO
inst_bout_fifo: entity work.fifo_sync_dist
GENERIC MAP
(
addr_width => 4,
data_width => 69
)
PORT MAP
(
rst => RST_I,
clk => CLK_I,
we => bout_fifo_we,
re => bout_fifo_re,
fifo_full => bout_fifo_full,
fifo_empty => bout_fifo_empty,
fifo_afull => open,
fifo_aempty => open,
data_w => bout_fifo_din,
data_r => bout_fifo_dout
);
bout_rdy <= not bout_fifo_full;
bout_fifo_re <= not bout_fifo_empty and SRDY_I;
bout_fifo_we <= STB_O_dmem_wr or STB_O_dmem_rd or STB_O_dcache or STB_O_icache;
bout_fifo_data_in <= DAT_O_dmem_wr when dmem_mem_wr_gnt = '1' else (others => '-');
bout_fifo_addr_in <= ADDR_O_dmem_wr when dmem_mem_wr_gnt = '1' else
ADDR_O_dmem_rd when dmem_mem_rd_gnt = '1' else
ADDR_O_dcache when dcache_mem_gnt = '1' else
ADDR_O_icache when icache_mem_gnt = '1' else (others => '-');
bout_fifo_sel_in <= SEL_O_dmem_wr when dmem_mem_wr_gnt = '1' else (others => '0');
bout_fifo_we_in <= '1' when dmem_mem_wr_gnt = '1' else '0';
-- Instantiate synchronous FIFO
inst_write_fifo: entity work.fifo_sync_dist
GENERIC MAP
(
addr_width => 4,
data_width => 68
)
PORT MAP
(
rst => RST_I,
clk => CLK_I,
we => write_fifo_we,
re => write_fifo_re,
fifo_full => write_busy,
fifo_empty => write_fifo_empty,
fifo_afull => open,
fifo_aempty => open,
data_w => write_fifo_din,
data_r => write_fifo_dout
);
CYC_O_dmem_wr <= not write_fifo_empty;
DAT_O_dmem_wr <= write_fifo_data_out;
ADDR_O_dmem_wr <= write_fifo_addr_out;
SEL_O_dmem_wr <= write_fifo_sel_out;
write_fifo_data_in <= cpu_dmem_dout;
write_fifo_addr_in <= cpu_dmem_addr;
write_fifo_sel_in <= cpu_dmem_be;
write_fifo_re <= STB_O_dmem_wr;
write_fifo_we <= cpu_dmem_en and not busy and cpu_dmem_we;
dmem_rd_flags:
process(CLK_I)
begin
if rising_edge(CLK_I) then
uncached_access <= '0';
if RST_I = '1' then
CYC_O_dmem_rd <= '0';
else
if ACK_I = '1' and dmem_mem_rd_gnt = '1' then
uncached_access <= '1';
CYC_O_dmem_rd <= '0';
end if;
if cpu_dmem_en = '1' and busy = '0' and cpu_dmem_we = '0' then
if dcached = '0' then
CYC_O_dmem_rd <= '1';
end if;
end if;
end if;
end if;
end process;
dmem_rd_data:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if RST_I = '1' then
DAT_I_dmem_rd <= (others => '0');
elsif ACK_I = '1' and CYC_O_dmem_rd = '1' then
DAT_I_dmem_rd <= DAT_I;
end if;
end if;
end process;
dmem_rd_regs:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if cpu_dmem_en = '1' and busy = '0' then
ADDR_O_dmem_rd <= cpu_dmem_addr;
end if;
end if;
end process;
bus_state_next:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if RST_I = '1' then
s <= init;
else
s <= sn;
end if;
end if;
end process;
bus_state:
process(s, CYC_O_icache, CYC_O_dcache, CYC_O_dmem_wr, CYC_O_dmem_rd, bout_rdy, ACK_I)
begin
icache_mem_gnt <= '0';
dcache_mem_gnt <= '0';
dmem_mem_rd_gnt <= '0';
dmem_mem_wr_gnt <= '0';
STB_O_dmem_rd <= '0';
STB_O_dmem_wr <= '0';
bus_idle <= '0';
sn <= s;
case s is
when init =>
sn <= ready;
when ready =>
bus_idle <= '1';
if CYC_O_dmem_wr = '1' then
sn <= write_bus;
elsif CYC_O_dmem_rd = '1' then
sn <= read_bus;
elsif CYC_O_icache = '1' then
sn <= icache_bus_access;
elsif CYC_O_dcache = '1' then
sn <= dcache_bus_access;
end if;
when icache_bus_access =>
icache_mem_gnt <= '1';
if CYC_O_icache = '0' then
sn <= ready;
end if;
when dcache_bus_access =>
dcache_mem_gnt <= '1';
if CYC_O_dcache = '0' then
sn <= ready;
end if;
when write_bus =>
dmem_mem_wr_gnt <= '1';
if CYC_O_dmem_wr = '1' then
if bout_rdy = '1' then
STB_O_dmem_wr <= '1';
end if;
else
sn <= ready;
end if;
when read_bus =>
dmem_mem_rd_gnt <= '1';
if bout_rdy = '1' then
STB_O_dmem_rd <= '1';
sn <= read_finish;
end if;
when read_finish =>
dmem_mem_rd_gnt <= '1';
if ACK_I = '1' then
sn <= ready;
end if;
when others =>
sn <= ready;
end case;
end process;
bus_timeout_counter:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if bus_idle = '0' then
if bus_timeout_cnt /= 0 then
bus_timeout_cnt <= bus_timeout_cnt - 1;
else
bus_timeout <= '1';
end if;
else
bus_timeout_cnt <= timeout_cnt_t'high;
bus_timeout <= '0';
end if;
end if;
end process;
bus_err:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if RST_I = '1' then
cpu_imem_err <= '0';
cpu_dmem_err <= '0';
elsif bus_timeout = '1' then
cpu_imem_err <= icache_mem_gnt;
cpu_dmem_err <= dcache_mem_gnt or dmem_mem_wr_gnt or dmem_mem_rd_gnt;
end if;
end if;
end process;
-------------------------------------------------------------------
end behavior;
+415
View File
@@ -0,0 +1,415 @@
--------------------------------------------------------------------------
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
-- This file: The arithmetic logic unit
--
-- Copyright (C) 2008 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
use work.mips_types.all;
use work.mips_instr.all;
entity cop is
Port
(
rst : in STD_LOGIC;
clk : in STD_LOGIC;
sdu : in sdu_t;
IR_valid : in STD_LOGIC;
IR : in word_t;
events : in event_t;
ctrl_in : in cop_ctrl_in_t;
ctrl_out : out cop_ctrl_out_t;
din : in word_t;
dout : out word_t
);
end cop;
architecture Behavioral of cop is
signal epc : word_t;
signal cause : word_t;
signal status : word_t;
signal BadVAddr : word_t;
signal exc_code : unsigned(4 downto 0);
signal test_reg : word_t;
signal test_reg_we : STD_LOGIC;
signal stat_reg_we : STD_LOGIC;
signal eflags_reg_we : STD_LOGIC;
signal epc_reg_we : STD_LOGIC;
signal code_reg_we : STD_LOGIC;
signal ip_reg_we : STD_LOGIC;
signal bd : STD_LOGIC;
signal ip : unsigned(7 downto 0);
signal im : unsigned(7 downto 0);
signal status_save : STD_LOGIC;
signal status_rest : STD_LOGIC;
signal exception : STD_LOGIC;
signal exception_end : STD_LOGIC;
signal eflags : exc_flags_t;
signal exc_enable : STD_LOGIC;
signal cop_EX_en : STD_LOGIC;
type cop_pipe_t is record
din : word_t;
rs : reg_ptr_t;
rd : reg_ptr_t;
func : func_t;
we : std_logic;
re : std_logic;
cs : std_logic;
end record;
signal cop_pipe_ID : cop_pipe_t;
signal cop_pipe_EX : cop_pipe_t;
function eval_int(ip : unsigned) return STD_LOGIC is
variable result : STD_LOGIC;
begin
result := '0';
for i in ip'range loop
result := result or ip(i);
end loop;
return result;
end eval_int;
type exc_state_t is (exc_init, exc_idle, exc_commit_ID, exc_commit_EX, exc_commit_MEM);
signal exc_state, exc_staten : exc_state_t;
--------------------------------------------------------------------------
begin
cop_pipe_ID.din <= din;
cop_pipe_ID.cs <= IR_valid;
cop_pipe_ID.rs <= extract_rs(IR);
cop_pipe_ID.rd <= extract_rd(IR);
cop_pipe_ID.func <= extract_func(IR);
cop_pipe_ID.re <= cop_pipe_ID.cs when cop_pipe_ID.rs = "00000" else '0';
cop_pipe_ID.we <= cop_pipe_ID.cs when cop_pipe_ID.rs = "00100" else '0';
cop_EX_en <= exc_enable and not status_save;
ctrl_out.ee <= exc_enable;
ctrl_out.ec <= status_save;
ctrl_out.RE <= status(25);
ctrl_out.user_mode <= status(1);
ctrl_out.int <= eflags.Int;
ctrl_out.cop_read <= cop_pipe_EX.cs and cop_pipe_EX.re after 1 ns;
ctrl_out.reg_write <= cop_pipe_ID.re after 1 ns;
im <= status(15 downto 8);
cause <= bd & (30 downto 16 => '0') & ip & '0' & exc_code & "00";
eflags.Ov <= events.alu_ovf or events.alu_uvf;
eflags.DAdEL <= events.data_load_err;
eflags.DAdES <= events.data_store_err;
eflags.IAdEL <= events.inst_load_err;
eflags.IAdEK <= events.inst_priv_addr and status(1);
eflags.Sys <= events.syscall;
eflags.Bp <= events.break;
eflags.RI <= events.illegal;
eflags.Int <= eval_int(ip) and status(0);
exception <= eflags.Ov or eflags.Sys or eflags.Bp or eflags.RI or eflags.IAdEL or eflags.IAdEK or eflags.DAdEL or eflags.DAdES or eflags.Int after 1 ns;
exception_state:
process(exc_state, ctrl_in, exception, sdu)
begin
exc_enable <= '0';
ctrl_out.exc_commit <= '0';
ctrl_out.exc_pending <= '0';
epc_reg_we <= '0';
code_reg_we <= '0';
status_save <= '0';
eflags_reg_we <= '0';
exc_staten <= exc_state;
case exc_state is
when exc_init =>
exc_staten <= exc_idle;
when exc_idle =>
exc_enable <= '1';
if exception = '1' then
status_save <= '1';
eflags_reg_we <= '1';
code_reg_we <= '1';
exc_staten <= exc_commit_ID;
end if;
when exc_commit_ID =>
ctrl_out.exc_pending <= '1';
ctrl_out.exc_commit <= '1';
if sdu.ID_stall = '0' then
exc_staten <= exc_commit_EX;
end if;
when exc_commit_EX =>
ctrl_out.exc_pending <= '1';
ctrl_out.exc_commit <= '1';
if sdu.EX_stall = '0' then
exc_staten <= exc_commit_MEM;
end if;
when exc_commit_MEM =>
ctrl_out.exc_pending <= '1';
if sdu.MEM_stall = '0' then
epc_reg_we <= '1';
exc_staten <= exc_idle;
end if;
when others =>
exc_staten <= exc_idle;
end case;
end process;
exception_state_next:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
exc_state <= exc_init;
else
exc_state <= exc_staten;
end if;
end if;
end process;
cop_exception_epc_write:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
bd <= '0';
epc <= (others => '0');
elsif epc_reg_we = '1' then
bd <= '0';
epc <= ctrl_in.epc_mem;
if ctrl_in.bd_wb = '1' then
bd <= '1';
epc <= ctrl_in.epc_wb;
end if;
end if;
end if;
end process;
cop_exception_map:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
exc_code <= (others => '0');
BadVAddr <= (others => '0');
elsif code_reg_we = '1' then
if eflags.Ov = '1' then
exc_code <= "01100";
elsif eflags.Sys = '1' then
exc_code <= "01000";
elsif eflags.Bp = '1' then
exc_code <= "01001";
elsif eflags.RI = '1' then
exc_code <= "01010";
elsif eflags.IAdEL = '1' then
exc_code <= "00100";
BadVAddr <= ctrl_in.imem_addr;
elsif eflags.IAdEK = '1' then
exc_code <= "00100";
BadVAddr <= ctrl_in.imem_addr;
elsif eflags.DAdEL = '1' then
exc_code <= "00100";
BadVAddr <= ctrl_in.dmem_addr;
elsif eflags.DAdES = '1' then
exc_code <= "00101";
BadVAddr <= ctrl_in.dmem_addr;
elsif eflags.Int = '1' then
exc_code <= "00000";
end if;
end if;
end if;
end process;
status_rest <= exception_end and ctrl_in.exc_left;
cop_status_restore:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
exception_end <= '0';
ctrl_out.exc_exit <= '0';
else
if cop_pipe_ID.func = "10000" and exception_end = '0' then -- RFE
exception_end <= cop_pipe_ID.cs;
ctrl_out.exc_exit <= cop_pipe_ID.cs;
elsif exception_end = '1' and ctrl_in.exc_left = '1' then
exception_end <= '0';
ctrl_out.exc_exit <= '0';
end if;
end if;
end if;
end process;
cop_ip_reg_write:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
ip(1 downto 0) <= (others => '0');
elsif ip_reg_we = '1' then
ip(1 downto 0) <= cop_pipe_EX.din(9 downto 8) and im(1 downto 0);
end if;
ip(7 downto 2) <= events.Int and im(7 downto 2);
end if;
end process;
cop_exc_vector:
process(clk)
begin
if rising_edge(clk) then
ctrl_out.exc_vec <= X"80000180";
if status(22) = '1' then
ctrl_out.exc_vec <= X"BFC00180";
end if;
end if;
end process;
cop_pipe:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
cop_pipe_EX.cs <= '0';
cop_pipe_EX.we <= '0';
cop_pipe_EX.re <= '0';
else
if sdu.EX_stall = '0' then
cop_pipe_EX <= cop_pipe_ID;
end if;
end if;
end if;
end process;
cop_register_read:
process(clk)
variable reg : word_t;
begin
if rising_edge(clk) and cop_pipe_ID.re = '1' and sdu.ID_stall = '0' then
case cop_pipe_ID.rd is
when "01000" => -- BadVAddr
reg := BadVAddr;
when "01100" => -- Status
reg := status;
when "01101" => -- Cause
reg := cause;
when "01110" => -- EPC (Exception Program Counter)
reg := epc;
when "01111" => -- PRId (Processor Revision Register)
reg := X"000002" & to_unsigned(REVISION ,8);
when "11111" => -- test_reg
reg := test_reg;
when others =>
reg := (others => '-');
end case;
dout <= reg after 1 ns;
end if;
end process;
cop_we_gen:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
test_reg_we <= '0';
stat_reg_we <= '0';
ip_reg_we <= '0';
else
test_reg_we <= '0';
stat_reg_we <= '0';
ip_reg_we <= '0';
if (cop_EX_en and cop_pipe_EX.we) = '1' then
case cop_pipe_EX.rd is
when "01100" =>
stat_reg_we <= not status(1) or status(28);
when "01101" =>
ip_reg_we <= not status(1) or status(28);
when "11111" =>
test_reg_we <= not status(1) or status(28);
when others => null;
end case;
end if;
end if;
end if;
end process;
cop_test_reg_write:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
test_reg <= (others => '0');
else --if ce = '1' then
if test_reg_we = '1' then
test_reg <= cop_pipe_EX.din;
end if;
end if;
end if;
end process;
cop_status_reg_write:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
status <= X"00400000";
else
if status_save = '1' then
status(5 downto 4) <= status(3 downto 2);
status(3 downto 2) <= status(1 downto 0);
status(1 downto 0) <= "00";
elsif status_rest = '1' then
status(1 downto 0) <= status(3 downto 2);
status(3 downto 2) <= status(5 downto 4);
elsif stat_reg_we = '1' then
status <= cop_pipe_EX.din;
end if;
end if;
end if;
end process;
--------------------------------------------------------------------------
end Behavioral;
+101
View File
@@ -0,0 +1,101 @@
--------------------------------------------------------------------------
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
-- This file: The datapath controller
--
-- Copyright (C) 2008 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
library work;
use work.mips_types.all;
use work.mips_instr.all;
entity idecode_rom is
Port
(
nop : in std_logic;
inst_in : in word_t;
ctrl_out : out ctrl_lines_t
);
end idecode_rom;
architecture Behavioral of idecode_rom is
signal ctrl_special : ctrl_lines_t;
signal ctrl_regimm : ctrl_lines_t;
signal ctrl_opcode : ctrl_lines_t;
signal rom_special : rom_special_t := gen_rom_special;
signal rom_regimm : rom_regimm_t := gen_rom_regimm;
signal rom_opcode : rom_opcode_t := gen_rom_opcode;
attribute rom_style : string;
attribute rom_style of rom_special: signal is "distributed";
attribute rom_style of rom_regimm: signal is "distributed";
attribute rom_style of rom_opcode: signal is "distributed";
begin
i_dec_special:
process(inst_in, rom_special)
variable func : func_t;
begin
func := extract_func(inst_in);
ctrl_special <= rom_special(to_integer(func));
end process;
i_dec_regimm:
process(inst_in, rom_regimm)
variable rt : reg_ptr_t;
begin
rt := extract_rt(inst_in);
ctrl_regimm <= rom_regimm(to_integer(rt));
end process;
i_dec_opcode:
process(inst_in, rom_opcode)
variable opc : opcode_t;
begin
opc := extract_opc(inst_in);
ctrl_opcode <= rom_opcode(to_integer(opc));
end process;
proc_decode:
process(inst_in, ctrl_special, ctrl_regimm, ctrl_opcode, nop)
variable opclass : opcode_t;
begin
opclass := extract_opc(inst_in);
ctrl_out <= ctrl_lines_default after 2 ns;
if nop = '0' then
case opclass is
when "000000" =>
ctrl_out <= ctrl_special after 2 ns;
when "000001" =>
ctrl_out <= ctrl_regimm after 2 ns;
when others =>
ctrl_out <= ctrl_opcode after 2 ns;
end case;
end if;
end process;
end Behavioral;
+997
View File
@@ -0,0 +1,997 @@
--------------------------------------------------------------------------
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
-- This file: Types, constants and functions for JCPU
--
-- Copyright (C) 2008 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
library work;
use work.mips_types.all;
--------------------------------------------------------------------------
package mips_instr is
function extract_opc(instr : word_t) return opcode_t;
function extract_rs(instr : word_t) return reg_ptr_t;
function extract_rt(instr : word_t) return reg_ptr_t;
function extract_rd(instr : word_t) return reg_ptr_t;
function extract_shamt(instr : word_t) return shamt_t;
function extract_func(instr : word_t) return func_t;
function extract_simm32(instr : word_t) return word_t;
function extract_uimm16(instr : word_t) return word_t;
function extract_jimm32(instr, pc : word_t) return word_t;
function extract_bimm18(instr, pc : word_t) return word_t;
function decode_op(instr : word_t) return op_t;
function ctrl_lines_default return ctrl_lines_t;
function special_ctrl_lines(func : func_t) return ctrl_lines_t;
function regimm_ctrl_lines(rt : reg_ptr_t) return ctrl_lines_t;
function opcode_ctrl_lines(opc : opcode_t) return ctrl_lines_t;
function gen_rom_opcode return rom_opcode_t;
function gen_rom_regimm return rom_regimm_t;
function gen_rom_special return rom_special_t;
end mips_instr;
--------------------------------------------------------------------------
library work;
use work.mips_types.all;
package body mips_instr is
function extract_opc(instr : word_t) return opcode_t is
variable result : opcode_t;
begin
result := instr(31 downto 26);
return result;
end extract_opc;
function extract_rs(instr : word_t) return reg_ptr_t is
variable result : reg_ptr_t;
begin
result := instr(25 downto 21);
return result;
end extract_rs;
function extract_rt(instr : word_t) return reg_ptr_t is
variable result : reg_ptr_t;
begin
result := instr(20 downto 16);
return result;
end extract_rt;
function extract_rd(instr : word_t) return reg_ptr_t is
variable result : reg_ptr_t;
begin
result := instr(15 downto 11);
return result;
end extract_rd;
function extract_shamt(instr : word_t) return shamt_t is
variable result : shamt_t;
begin
result := instr(10 downto 6);
return result;
end extract_shamt;
function extract_func(instr : word_t) return func_t is
variable result : func_t;
begin
result := instr(5 downto 0);
return result;
end extract_func;
function extract_simm32(instr : word_t) return word_t is
variable result : word_t;
begin
result := (31 downto 16 => instr(15)) & instr(15 downto 0);
return result;
end extract_simm32;
function extract_uimm16(instr : word_t) return word_t is
variable result : word_t;
begin
result := (31 downto 16 => '0') & instr(15 downto 0);
return result;
end extract_uimm16;
function extract_jimm32(instr, pc : word_t) return word_t is
variable result : word_t;
begin
result := pc(31 downto 28) & instr(25 downto 0) & "00";
return result;
end extract_jimm32;
function extract_bimm18(instr, pc : word_t) return word_t is
variable result : word_t;
begin
result := (31 downto 18 => instr(15)) & instr(15 downto 0) & "00";
return result;
end extract_bimm18;
function decode_op(instr : word_t) return op_t is
variable result : op_t;
variable opc : natural range 0 to 63;
variable func : natural range 0 to 63;
variable rt : natural range 0 to 31;
begin
opc := to_integer(extract_opc(instr));
func := to_integer(extract_func(instr));
rt := to_integer(extract_rt(instr));
result := op_sll;
case opc is
when 0 =>
case func is
when 0 =>
result := op_sll;
when 2 =>
result := op_srl;
when 3 =>
result := op_sra;
when 4 =>
result := op_sllv;
when 6 =>
result := op_srlv;
when 7 =>
result := op_srav;
when 8 =>
result := op_jr;
when 9 =>
result := op_jalr;
when 12 =>
result := op_syscall;
when 13 =>
result := op_break;
when 16 =>
result := op_mfhi;
when 17 =>
result := op_mthi;
when 18 =>
result := op_mflo;
when 19 =>
result := op_mtlo;
when 24 =>
result := op_mult;
when 25 =>
result := op_multu;
when 26 =>
result := op_div;
when 27 =>
result := op_divu;
when 32 =>
result := op_add;
when 33 =>
result := op_addu;
when 34 =>
result := op_sub;
when 35 =>
result := op_subu;
when 36 =>
result := op_and;
when 37 =>
result := op_or;
when 38 =>
result := op_xor;
when 39 =>
result := op_nor;
when 42 =>
result := op_slt;
when 43 =>
result := op_sltu;
when others => null; -- undef
end case;
when 1 =>
case rt is
when 0 =>
result := op_bltz;
when 1 =>
result := op_bgez;
when 16 =>
result := op_bltzal;
when 17 =>
result := op_bgezal;
when others => null; -- undef
end case;
when 2 =>
result := op_j;
when 3 =>
result := op_jal;
when 4 =>
result := op_beq;
when 5 =>
result := op_bne;
when 6 =>
result := op_blez;
when 7 =>
result := op_bgtz;
when 8 =>
result := op_addi;
when 9 =>
result := op_addiu;
when 10 =>
result := op_slti;
when 11 =>
result := op_sltiu;
when 12 =>
result := op_andi;
when 13 =>
result := op_ori;
when 14 =>
result := op_xori;
when 15 =>
result := op_lui;
when 16 =>
result := op_cop0;
when 17 =>
result := op_cop1;
when 18 =>
result := op_cop2;
when 19 =>
result := op_cop3;
when 32 =>
result := op_lb;
when 33 =>
result := op_lh;
when 34 =>
result := op_lwl;
when 35 =>
result := op_lw;
when 36 =>
result := op_lbu;
when 37 =>
result := op_lhu;
when 38 =>
result := op_lwr;
when 40 =>
result := op_sb;
when 41 =>
result := op_sh;
when 42 =>
result := op_swl;
when 43 =>
result := op_sw;
when 46 =>
result := op_swr;
when 49 =>
result := op_lwc1;
when 50 =>
result := op_lwc2;
when 51 =>
result := op_lwc3;
when 57 =>
result := op_swc1;
when 58 =>
result := op_swc2;
when 59 =>
result := op_swc3;
when others => null; -- undef
end case;
return result;
end decode_op;
function ctrl_lines_default return ctrl_lines_t is
variable result : ctrl_lines_t;
begin
result.cop_instr_en := '0';
result.jump := '0';
result.jump_long := '0';
result.branch := '0';
result.bc_src := bc_eq_ne;
result.bc_not := '0';
result.alu.outsel := alu_adder;
result.alu.add := '1';
result.alu.shift_right := '0';
result.alu.shift_arith := '0';
result.shamt2_srcsel := sa_src_imm;
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_reg;
result.imm_src := src_imm16;
result.reg_write := '0';
result.dmem_we := '0';
result.dmem_en := '0';
result.wptr_srcsel := wptr_src_imm;
result.reg_link := '0';
result.shift_offset := "00";
result.shift_byp := '1';
result.byte_en_byp := '1';
result.sign_ext_byp := '1';
result.word4_en := '0';
result.word2_en := '0';
result.align_left := '0';
result.load_signed := '0';
result.mul_access := '0';
result.mul_hilo_we := '0';
result.mul_start := '0';
result.mul_s_un := '0';
result.mul_mul_divn := '0';
result.mul_hilo_sel := '1';
result.exc_break := '0';
result.exc_syscall := '0';
result.exc_illegal := '0';
result.except_en := '0';
result.alu_exc_en := '0';
return result;
end ctrl_lines_default;
function special_ctrl_lines(func : func_t) return ctrl_lines_t is
variable result : ctrl_lines_t;
variable op : integer range 0 to 2**func_t'length-1;
begin
result := ctrl_lines_default;
op := to_integer(func);
case op is
-- when op_add =>
when 32 =>
result.alu.outsel := alu_adder;
result.alu.add := '1';
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_reg;
result.reg_write := '1';
result.alu_exc_en := '1';
-- when op_addu =>
when 33 =>
result.alu.outsel := alu_adder;
result.alu.add := '1';
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_reg;
result.reg_write := '1';
-- when op_and =>
when 36 =>
result.alu.outsel := alu_and;
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_reg;
result.reg_write := '1';
-- when op_break =>
when 13 =>
result.exc_break := '1';
result.except_en := '1';
-- when op_div =>
when 26 =>
result.mul_access := '1';
result.mul_start := '1';
result.mul_s_un := '1';
result.mul_mul_divn := '0';
-- when op_divu =>
when 27 =>
result.mul_access := '1';
result.mul_start := '1';
result.mul_s_un := '0';
result.mul_mul_divn := '0';
-- when op_jalr =>
when 9 =>
result.jump_long := '1';
result.wptr_srcsel := wptr_src_imm;
result.reg_write := '1';
result.reg_link := '1';
-- when op_jr =>
when 8 =>
result.jump_long := '1';
-- when op_mfhi =>
when 16 =>
result.reg_write := '1';
result.mul_access := '1';
result.mul_hilo_sel := '1';
-- when op_mflo =>
when 18 =>
result.reg_write := '1';
result.mul_access := '1';
result.mul_hilo_sel := '0';
-- when op_mthi =>
when 17 =>
result.mul_hilo_we := '1';
result.mul_hilo_sel := '1';
-- when op_mtlo =>
when 19 =>
result.mul_hilo_we := '1';
result.mul_hilo_sel := '0';
-- when op_mult =>
when 24 =>
result.mul_access := '1';
result.mul_start := '1';
result.mul_s_un := '1';
result.mul_mul_divn := '1';
-- when op_multu =>
when 25 =>
result.mul_access := '1';
result.mul_start := '1';
result.mul_s_un := '0';
result.mul_mul_divn := '1';
-- when op_or =>
when 37 =>
result.alu.outsel := alu_or;
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_reg;
result.reg_write := '1';
-- when op_nor =>
when 39 =>
result.alu.outsel := alu_nor;
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_reg;
result.reg_write := '1';
-- when op_sll =>
when 0 =>
result.alu.op2_src := alu_src_reg;
result.alu.outsel := alu_shift2;
result.alu.shift_right := '0';
result.shamt2_srcsel := sa_src_imm;
result.reg_write := '1';
-- when op_sllv =>
when 4 =>
result.alu.op2_src := alu_src_reg;
result.alu.outsel := alu_shift2;
result.alu.shift_right := '0';
result.shamt2_srcsel := sa_src_reg;
result.reg_write := '1';
-- when op_slt =>
when 42 =>
result.alu.outsel := alu_lts;
result.alu.add := '0';
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_reg;
result.reg_write := '1';
-- when op_sltu =>
when 43 =>
result.alu.outsel := alu_ltu;
result.alu.add := '0';
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_reg;
result.reg_write := '1';
-- when op_sra =>
when 3 =>
result.alu.op2_src := alu_src_reg;
result.alu.outsel := alu_shift2;
result.alu.shift_right := '1';
result.alu.shift_arith := '1';
result.shamt2_srcsel := sa_src_imm;
result.reg_write := '1';
-- when op_srav =>
when 7 =>
result.alu.op2_src := alu_src_reg;
result.alu.outsel := alu_shift2;
result.alu.shift_right := '1';
result.alu.shift_arith := '1';
result.shamt2_srcsel := sa_src_reg;
result.reg_write := '1';
-- when op_srl =>
when 2 =>
result.alu.op2_src := alu_src_reg;
result.alu.outsel := alu_shift2;
result.alu.shift_right := '1';
result.alu.shift_arith := '0';
result.shamt2_srcsel := sa_src_imm;
result.reg_write := '1';
-- when op_srlv =>
when 6 =>
result.alu.op2_src := alu_src_reg;
result.alu.outsel := alu_shift2;
result.alu.shift_right := '1';
result.alu.shift_arith := '0';
result.shamt2_srcsel := sa_src_reg;
result.reg_write := '1';
-- when op_sub =>
when 34 =>
result.alu.outsel := alu_adder;
result.alu.add := '0';
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_reg;
result.reg_write := '1';
result.alu_exc_en := '1';
-- when op_subu =>
when 35 =>
result.alu.outsel := alu_adder;
result.alu.add := '0';
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_reg;
result.reg_write := '1';
-- when op_syscall =>
when 12 =>
result.exc_syscall := '1';
result.except_en := '1';
-- when op_xor =>
when 38 =>
result.alu.outsel := alu_xor;
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_reg;
result.reg_write := '1';
when others =>
result.exc_illegal := '1';
end case;
return result;
end special_ctrl_lines;
function gen_rom_special return rom_special_t is
variable result : rom_special_t;
variable func : func_t;
begin
for i in 0 to 2**func_t'length-1 loop
func := to_unsigned(i, func_t'length);
result(i) := special_ctrl_lines(func);
end loop;
return result;
end gen_rom_special;
function regimm_ctrl_lines(rt : reg_ptr_t) return ctrl_lines_t is
variable result : ctrl_lines_t;
variable op : integer range 0 to 2**reg_ptr_t'length-1;
begin
result := ctrl_lines_default;
op := to_integer(rt);
case op is
-- when op_bgez =>
when 1 =>
result.branch := '1';
result.bc_src := bc_ltz_gez;
result.bc_not := '1';
-- when op_bgezal =>
when 17 =>
result.branch := '1';
result.bc_src := bc_ltz_gez;
result.bc_not := '1';
result.wptr_srcsel := wptr_src_const;
result.reg_write := '1';
result.reg_link := '1';
-- when op_bltz =>
when 0 =>
result.branch := '1';
result.bc_src := bc_ltz_gez;
result.bc_not := '0';
-- when op_bltzal =>
when 16 =>
result.branch := '1';
result.bc_src := bc_ltz_gez;
result.bc_not := '0';
result.wptr_srcsel := wptr_src_const;
result.reg_write := '1';
result.reg_link := '1';
when others =>
result.exc_illegal := '1';
end case;
return result;
end regimm_ctrl_lines;
function gen_rom_regimm return rom_regimm_t is
variable result : rom_regimm_t;
variable rt : reg_ptr_t;
begin
for i in 0 to 2**reg_ptr_t'length-1 loop
rt := to_unsigned(i, reg_ptr_t'length);
result(i) := regimm_ctrl_lines(rt);
end loop;
return result;
end gen_rom_regimm;
function opcode_ctrl_lines(opc : opcode_t) return ctrl_lines_t is
variable result : ctrl_lines_t;
variable op : integer range 0 to 2**opcode_t'length-1;
begin
result := ctrl_lines_default;
op := to_integer(opc);
case op is
-- when op_addi =>
when 8 =>
result.imm_src := src_imm32;
result.alu.outsel := alu_adder;
result.alu.add := '1';
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_imm;
result.reg_write := '1';
result.alu_exc_en := '1';
-- when op_addiu =>
when 9 =>
result.imm_src := src_imm32;
result.alu.outsel := alu_adder;
result.alu.add := '1';
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_imm;
result.reg_write := '1';
-- when op_andi =>
when 12 =>
result.imm_src := src_imm16;
result.alu.outsel := alu_and;
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_imm;
result.reg_write := '1';
-- when op_beq =>
when 4 =>
result.branch := '1';
result.bc_src := bc_eq_ne;
result.bc_not := '0';
-- when op_bgtz =>
when 7 =>
result.branch := '1';
result.bc_src := bc_lez_gtz;
result.bc_not := '1';
-- when op_blez =>
when 6 =>
result.branch := '1';
result.bc_src := bc_lez_gtz;
result.bc_not := '0';
-- when op_bne =>
when 5 =>
result.branch := '1';
result.bc_src := bc_eq_ne;
result.bc_not := '1';
-- when op_cop =>
when 16 | 17 | 18 | 19 =>
result.cop_instr_en := '1';
-- when op_j =>
when 2 =>
result.jump := '1';
-- when op_jal =>
when 3 =>
result.jump := '1';
result.wptr_srcsel := wptr_src_const;
result.reg_write := '1';
result.reg_link := '1';
-- when op_lb =>
when 32 =>
result.imm_src := src_imm32;
result.dmem_en := '1';
result.reg_write := '1';
result.shift_byp := '0';
result.byte_en_byp := '1';
result.sign_ext_byp := '0';
result.load_signed := '1';
result.word4_en := '1';
-- when op_lbu =>
when 36 =>
result.imm_src := src_imm32;
result.dmem_en := '1';
result.reg_write := '1';
result.shift_byp := '0';
result.byte_en_byp := '1';
result.sign_ext_byp := '0';
result.load_signed := '0';
result.word4_en := '1';
-- when op_lh =>
when 33 =>
result.imm_src := src_imm32;
result.dmem_en := '1';
result.reg_write := '1';
result.shift_byp := '0';
result.sign_ext_byp := '0';
result.byte_en_byp := '1';
result.load_signed := '1';
result.word2_en := '1';
result.except_en := '1';
-- when op_lhu =>
when 37 =>
result.imm_src := src_imm32;
result.dmem_en := '1';
result.reg_write := '1';
result.shift_byp := '0';
result.sign_ext_byp := '0';
result.byte_en_byp := '1';
result.load_signed := '0';
result.word2_en := '1';
result.except_en := '1';
-- when op_lui =>
when 15 =>
result.imm_src := src_imm16_high;
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_imm;
result.alu.outsel := alu_adder;
result.reg_write := '1';
result.alu.add := '1';
-- when op_lw =>
when 35 =>
-- result.imm_src := src_imm32;
result.dmem_en := '1';
result.reg_write := '1';
result.except_en := '1';
-- when op_lwl =>
when 34 =>
-- result.imm_src := src_imm32;
result.dmem_en := '1';
result.reg_write := '1';
result.shift_byp := '0';
result.byte_en_byp := '0';
result.shift_offset := "01";
result.align_left := '1';
-- when op_lwr =>
when 38 =>
-- result.imm_src := src_imm32;
result.dmem_en := '1';
result.reg_write := '1';
result.shift_byp := '0';
result.byte_en_byp := '0';
result.shift_offset := "00";
result.align_left := '0';
-- when op_ori =>
when 13 =>
result.imm_src := src_imm16;
result.alu.outsel := alu_or;
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_imm;
result.reg_write := '1';
-- when op_sb =>
when 40 =>
result.dmem_en := '1';
result.dmem_we := '1';
-- result.imm_src := src_imm32;
result.shift_byp := '0';
result.byte_en_byp := '0';
result.word4_en := '1';
-- when op_sh =>
when 41 =>
result.dmem_en := '1';
result.dmem_we := '1';
-- result.imm_src := src_imm32;
result.shift_byp := '0';
result.byte_en_byp := '0';
result.word2_en := '1';
result.except_en := '1';
-- when op_slti =>
when 10 =>
result.alu.outsel := alu_lts;
result.alu.add := '0';
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_imm;
result.imm_src := src_imm32;
result.reg_write := '1';
-- when op_sltiu =>
when 11 =>
result.alu.outsel := alu_ltu;
result.alu.add := '0';
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_imm;
result.imm_src := src_imm32;
result.reg_write := '1';
-- when op_sw =>
when 43 =>
result.dmem_en := '1';
result.dmem_we := '1';
-- result.imm_src := src_imm32;
result.except_en := '1';
-- when op_swl =>
when 42 =>
result.dmem_en := '1';
result.dmem_we := '1';
-- result.imm_src := src_imm32;
result.shift_byp := '0';
result.byte_en_byp := '0';
result.shift_offset := "01";
-- when op_swr =>
when 46 =>
result.dmem_en := '1';
result.dmem_we := '1';
-- result.imm_src := src_imm32;
result.shift_byp := '0';
result.byte_en_byp := '0';
result.align_left := '1';
-- when op_xori =>
when 14 =>
result.imm_src := src_imm16;
result.alu.outsel := alu_xor;
result.alu.op1_src := alu_src_reg;
result.alu.op2_src := alu_src_imm;
result.reg_write := '1';
when others =>
result.exc_illegal := '1';
end case;
return result;
end opcode_ctrl_lines;
function gen_rom_opcode return rom_opcode_t is
variable result : rom_opcode_t;
variable opc : opcode_t;
begin
for i in 0 to 2**opcode_t'length-1 loop
opc := to_unsigned(i, opcode_t'length);
result(i) := opcode_ctrl_lines(opc);
end loop;
return result;
end gen_rom_opcode;
end mips_instr;
--------------------------------------------------------------------------
--------------------------------------------------------------------------
+454
View File
@@ -0,0 +1,454 @@
--------------------------------------------------------------------------
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
-- This file: The arithmetic logic unit
--
-- Copyright (C) 2007 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
use work.mips_types.all;
entity muldiv is
Port
(
rst : in std_logic;
clk : in std_logic;
hilo_we : in std_logic;
din_hi : in word_t;
din_lo : in word_t;
mul_divn : in std_logic;
start : in std_logic;
s_un : in std_logic;
hilo_sel : in std_logic;
busy : out std_logic;
dout : out word_t
);
end muldiv;
architecture Behavioral of muldiv is
subtype pprod_t is unsigned (39 downto 0);
subtype prod_t is unsigned (63 downto 0);
subtype byte_t is unsigned (7 downto 0);
type pprod_array_t is array (natural range <>) of pprod_t;
type word_array_t is array (natural range <>) of word_t;
type byte_array_t is array (natural range <>) of byte_t;
signal pprod : pprod_array_t(0 to 3);
signal sign1 : std_logic;
signal sign2 : std_logic;
signal s1_r : std_logic;
signal s2_r : std_logic;
signal sr_r : std_logic;
signal cy : unsigned (3 downto 0);
signal mul_start : std_logic;
signal mul_en : std_logic;
signal sum_en : std_logic;
signal pre_sum_vld : std_logic;
signal pp_reg : unsigned (63 downto 8);
signal pre_const : word_array_t(0 to 1);
signal result : prod_t;
signal add_op1 : unsigned (39 downto 0);
signal add_op2 : unsigned (39 downto 0);
signal add_res : unsigned (39 downto 0);
signal ppadd_op1 : word_array_t(0 to 3);
signal ppadd_op2 : word_array_t(0 to 3);
signal ppadd_res : word_array_t(0 to 3);
signal ppadd_cyi : unsigned (3 downto 0);
signal ppadd_cyo : unsigned (3 downto 0);
signal pp_op1_r : word_t;
signal pp_op1 : word_t;
signal pp_op2 : word_t;
signal pp_op2_r : byte_array_t(0 to 3);
signal bsy : std_logic;
signal div_add_res : unsigned (32 downto 0);
signal div_add_op1 : unsigned (32 downto 0);
signal div_add_op2 : unsigned (32 downto 0);
signal div_add_cyi : std_logic;
signal div_qbit : std_logic;
signal div_start : std_logic;
signal div_en : std_logic;
signal div_A : unsigned (32 downto 0);
signal div_M : unsigned (32 downto 0);
signal div_M_n : unsigned (32 downto 0);
signal div_Q : word_t;
type md_state_t is (md_rdy, mul_pre1, mul_pre2, mul_pp, mul_sum, div_process, div_post1, div_post2, div_post3);
signal s, sn : md_state_t;
signal cycle_cnt : natural range 0 to 31;
signal cycle_cnt_preset : natural range 0 to 31;
signal cycle_cnt_load : std_logic;
signal div_fin_en : unsigned (2 downto 0);
--------------------------------------------------------------------------
begin
-- 9A0CD0570B88D78
busy <= bsy;
sign1 <= din_hi(din_hi'left) and s_un;
sign2 <= din_lo(din_lo'left) and s_un;
pp_op1 <= not din_hi when sign1 = '1' else din_hi;
pp_op2 <= not din_lo when sign2 = '1' else din_lo;
--------------------------------------------------------------------------
md_state:
process(s, start, mul_divn, cycle_cnt)
begin
bsy <= '1';
cycle_cnt_load <= '0';
cycle_cnt_preset <= 7;
mul_en <= '0';
div_en <= '0';
sum_en <= '0';
pre_sum_vld <= '0';
mul_start <= '0';
div_start <= '0';
div_fin_en <= "000";
sn <= s;
case s is
when md_rdy =>
bsy <= '0';
if start = '1' then
if mul_divn = '1' then
sn <= mul_pre1;
cycle_cnt_load <= '1';
cycle_cnt_preset <= 7;
mul_start <= '1';
else
sn <= div_process;
cycle_cnt_load <= '1';
cycle_cnt_preset <= 31;
div_start <= '1';
end if;
end if;
when mul_pre1 =>
pre_sum_vld <= '1';
mul_en <= '1';
sn <= mul_pre2;
when mul_pre2 =>
pre_sum_vld <= '1';
mul_en <= '1';
sn <= mul_pp;
when mul_pp =>
mul_en <= '1';
if cycle_cnt = 0 then
cycle_cnt_load <= '1';
cycle_cnt_preset <= 3;
sn <= mul_sum;
end if;
when mul_sum =>
sum_en <= '1';
if cycle_cnt = 0 then
bsy <= '0';
sn <= md_rdy;
end if;
when div_process =>
div_en <= '1';
if cycle_cnt = 0 then
sn <= div_post1;
end if;
when div_post1 =>
div_fin_en <= "001";
sn <= div_post2;
when div_post2 =>
div_fin_en <= "010";
sn <= div_post3;
when div_post3 =>
div_fin_en <= "100";
sn <= md_rdy;
bsy <= '0';
when others =>
sn <= md_rdy;
end case;
end process;
md_state_next:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
s <= md_rdy;
else
s <= sn;
end if;
end if;
end process;
md_cycle_cnt:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
cycle_cnt <= 0;
elsif cycle_cnt_load = '1' then
cycle_cnt <= cycle_cnt_preset;
elsif cycle_cnt /= 0 then
cycle_cnt <= cycle_cnt - 1;
end if;
end if;
end process;
proc_out_reg:
process(hilo_sel, result)
begin
if hilo_sel = '1' then
dout <= result(63 downto 32);
else
dout <= result(31 downto 0);
end if;
end process;
proc_in_reg:
process(clk)
variable pre_cond : unsigned(1 downto 0);
begin
if rising_edge(clk) then
if mul_start = '1' or div_start = '1' then
pp_op1_r <= pp_op1;
pre_const(0) <= (others => '0');
pre_const(1) <= (others => '0');
pre_cond := (din_hi(din_hi'left) and s_un) & (din_lo(din_lo'left) and s_un);
s1_r <= pre_cond(1);
s2_r <= pre_cond(0);
sr_r <= pre_cond(0) xor pre_cond(1);
case pre_cond is
when "01" =>
pre_const(0) <= din_hi;
pre_const(1) <= X"FFFF_FFFF";
when "10" =>
pre_const(0) <= X"0000_0000";
pre_const(1) <= X"FFFF_FFFF";
when "11" =>
pre_const(0) <= not din_hi;
pre_const(1) <= X"0000_0001";
when others => null;
end case;
elsif pre_sum_vld = '1' then
pre_const(0) <= pre_const(1);
end if;
end if;
end process;
proc_mul_sr:
process(clk)
begin
if rising_edge(clk) then
if mul_start = '1' then
for i in 0 to 3 loop
cy(i) <= '0';
pprod(i) <= ppadd_res(i) & X"00";
end loop;
elsif mul_en = '1' then
for i in 0 to 3 loop
cy(i) <= ppadd_cyo(i);
pprod(i) <= ppadd_res(i) & pprod(i)(8 downto 1);
end loop;
elsif sum_en = '1' then
for i in 1 to 3 loop
pprod(i-1) <= pprod(i);
end loop;
end if;
end if;
end process;
gen_mul32x8pp:
for i in 0 to 3 generate
begin
pp_adder_mux:
process(mul_start, pp_op1, pp_op2, pp_op1_r, pp_op2_r(i), s1_r, sign1, pprod(i), cy(i))
variable v2 : unsigned(7 downto 0);
begin
ppadd_cyi(i) <= '0';
ppadd_op1(i) <= (others => '0');
if mul_start = '1' then
ppadd_op2(i) <= (others => '0');
v2 := pp_op2(8*(i+1)-1 downto 8*i);
if v2(0) = '1' then
ppadd_cyi(i) <= sign1;
ppadd_op1(i) <= pp_op1;
end if;
else
ppadd_op2(i) <= cy(i) & pprod(i)(39 downto 9);
v2 := pp_op2_r(i);
if v2(0) = '1' then
ppadd_cyi(i) <= s1_r;
ppadd_op1(i) <= pp_op1_r;
end if;
end if;
end process;
pp_adder:
process(ppadd_op1(i), ppadd_op2(i), ppadd_cyi(i))
variable sum_pp : unsigned(33 downto 0);
begin
sum_pp := ('0' & ppadd_op1(i) & ppadd_cyi(i)) + ('0' & ppadd_op2(i) & ppadd_cyi(i));
ppadd_res(i) <= sum_pp(sum_pp'left-1 downto 1);
ppadd_cyo(i) <= sum_pp(sum_pp'left);
end process;
proc_mul_ctrl:
process(clk)
begin
if rising_edge(clk) then
if mul_start = '1' then
pp_op2_r(i) <= '0' & pp_op2(8*(i+1)-1 downto 8*i+1);
elsif mul_en = '1' then
pp_op2_r(i) <= '0' & pp_op2_r(i)(7 downto 1);
end if;
end if;
end process;
end generate;
comb_mul_adder:
process(add_op1, add_op2)
variable sum_mul : unsigned(39 downto 0);
begin
sum_mul := (add_op1) + (add_op2);
add_res <= sum_mul(sum_mul'left downto 0);
end process;
comb_mul_adder_mux:
process(pre_const, pre_sum_vld, pp_reg, pprod, sr_r)
variable s_ext : std_logic;
begin
if pre_sum_vld = '1' then
add_op1 <= pp_reg(63 downto 24);
add_op2 <= pre_const(0) & X"00";
else
s_ext := pp_reg(63) and sr_r;
add_op1 <= (7 downto 0 => s_ext) & pp_reg(63 downto 32);
add_op2 <= pprod(0);
end if;
end process;
comb_mul:
process(clk)
variable tmp : prod_t;
begin
if rising_edge(clk) then
if mul_start = '1' then
pp_reg <= (others => '0');
elsif pre_sum_vld = '1' then
pp_reg <= add_res & X"0000";
elsif sum_en = '1' then
tmp := add_res & pp_reg(31 downto 8);
pp_reg <= tmp(63 downto 8);
result <= tmp;
if sr_r = '1' then
result <= not tmp;
end if;
elsif div_fin_en(1) = '1' then
result(63 downto 32) <= div_A(31 downto 0);
if s1_r = '1' then
result(63 downto 32) <= div_add_res(31 downto 0);
end if;
elsif div_fin_en(2) = '1' then
result(31 downto 0) <= div_Q;
if sr_r = '1' then
result(31 downto 0) <= div_add_res(31 downto 0);
end if;
elsif hilo_we = '1' then
if hilo_sel = '1' then
result(63 downto 32) <= din_hi;
else
result(31 downto 0) <= din_hi;
end if;
end if;
end if;
end process;
div_adder:
process(div_add_op1, div_add_op2, div_add_cyi)
variable sum_div : unsigned(33 downto 0);
begin
sum_div := (div_add_op1 & div_add_cyi) + (div_add_op2 & div_add_cyi);
div_add_res <= sum_div(sum_div'left downto 1);
end process;
div_adder_mux:
process(div_start, div_en, div_fin_en, div_A, div_Q, pp_op1, sign1, s1_r, s2_r, sr_r, div_qbit, div_M, div_M_n)
begin
div_add_cyi <= s2_r xor div_qbit;
div_add_op1 <= div_A(31 downto 0) & div_Q(31);
div_add_op2 <= (others => '0');
if div_start = '1' then
div_add_op1 <= '0' & pp_op1;
div_add_cyi <= sign1;
elsif div_en = '1' then
div_add_op2 <= div_M;
if div_qbit = '1' then
div_add_op2 <= div_M_n;
end if;
elsif div_fin_en(0) = '1' then
div_add_op2 <= div_M;
div_add_cyi <= s2_r;
div_add_op1 <= '0' & div_A(31 downto 0);
elsif div_fin_en(1) = '1' then
div_add_cyi <= s1_r;
div_add_op1 <= '0' & not div_A(31 downto 0);
elsif div_fin_en(2) = '1' then
div_add_cyi <= sr_r;
div_add_op1 <= '0' & not div_Q;
end if;
end process;
divide:
process(clk)
variable quo : std_logic;
begin
if rising_edge(clk) then
if div_start = '1' then
div_qbit <= '1';
div_Q <= div_add_res(31 downto 0);
div_A <= (others => '0');
if sign2 = '1' then
div_M_n <= '1' & din_lo;
div_M <= '0' & not din_lo;
else
div_M_n <= '1' & not din_lo;
div_M <= '0' & din_lo;
end if;
elsif div_en = '1' then
div_qbit <= not div_add_res(32);
div_A <= div_add_res(32 downto 0);
div_Q <= div_Q(30 downto 0) & not div_add_res(32);
elsif div_fin_en(0) = '1' then
if div_A(32) = '1' then
div_A <= '0' & div_add_res(31 downto 0);
end if;
end if;
end if;
end process;
--------------------------------------------------------------------------
end Behavioral;
+889
View File
@@ -0,0 +1,889 @@
--------------------------------------------------------------------------
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
-- This file: The pipeline
--
-- Copyright (C) 2008 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
library work;
use work.mips_types.all;
use work.mips_instr.all;
entity pipeline is
Port
(
rst : in STD_LOGIC;
clk : in STD_LOGIC;
halt : in STD_LOGIC;
int : in unsigned(5 downto 0);
imem_err : in STD_LOGIC;
imem_rdy : in STD_LOGIC;
imem_en : out STD_LOGIC;
imem_addr : out word_t;
imem_data : in word_t;
dmem_err : in STD_LOGIC;
dmem_rdy : in STD_LOGIC;
dmem_en : out STD_LOGIC;
dmem_we : out STD_LOGIC;
dmem_be : out unsigned(3 downto 0);
dmem_addr : out word_t;
dmem_din : in word_t;
dmem_dout : out word_t
);
end pipeline;
architecture Behavioral of pipeline is
--------------------------------------------------------------------------
COMPONENT reg_dual is
Generic
(
addr_width : integer := 3;
data_width : integer := 8
);
Port
(
clk_w : in STD_LOGIC;
en : in STD_LOGIC;
we : in STD_LOGIC;
wptr : in unsigned (addr_width-1 downto 0);
din : in unsigned (data_width-1 downto 0);
rptr_a : in unsigned (addr_width-1 downto 0);
rptr_b : in unsigned (addr_width-1 downto 0);
dout_a : out unsigned (data_width-1 downto 0);
dout_b : out unsigned (data_width-1 downto 0)
);
END COMPONENT;
--------------------------------------------------------------------------
COMPONENT idecode_rom is
Port
(
nop : in std_logic;
inst_in : in word_t;
ctrl_out : out ctrl_lines_t
);
END COMPONENT;
--------------------------------------------------------------------------
COMPONENT shifter is
Generic
(
data_width : integer
);
Port
(
shift_ctrl : in shift_ctrl_t;
din : in unsigned (data_width-1 downto 0);
dout : out unsigned (data_width-1 downto 0)
);
END COMPONENT;
--------------------------------------------------------------------------
COMPONENT alu is
Generic
(
data_width : integer
);
Port
(
op1_in : in unsigned (data_width-1 downto 0);
op2_in : in unsigned (data_width-1 downto 0);
op2_shifted : in unsigned (data_width-1 downto 0);
ctrl : in alu_ctrl_t;
result : out unsigned (data_width-1 downto 0);
flags : out alu_flags_t
);
END COMPONENT;
--------------------------------------------------------------------------
COMPONENT bcu is
Generic
(
data_width : integer
);
Port
(
op1_in : in unsigned (data_width-1 downto 0);
op2_in : in unsigned (data_width-1 downto 0);
flags : out bcu_flags_t
);
END COMPONENT;
--------------------------------------------------------------------------
COMPONENT cop is
Port
(
rst : in STD_LOGIC;
clk : in STD_LOGIC;
sdu : in sdu_t;
IR_valid : in STD_LOGIC;
IR : in word_t;
events : in event_t;
ctrl_in : in cop_ctrl_in_t;
ctrl_out : out cop_ctrl_out_t;
din : in word_t;
dout : out word_t
);
END COMPONENT;
--------------------------------------------------------------------------
COMPONENT muldiv is
Port
(
rst : in std_logic;
clk : in std_logic;
hilo_we : in std_logic;
din_hi : in word_t;
din_lo : in word_t;
mul_divn : in std_logic;
start : in std_logic;
s_un : in std_logic;
hilo_sel : in std_logic;
busy : out std_logic;
dout : out word_t
);
END COMPONENT;
--------------------------------------------------------------------------
constant RESET_VECTOR : word_t := X"BFC00000";
signal ID_stage : ID_t;
signal EX_stage : EX_t;
signal MEM_stage : MEM_t;
signal WB_stage : WB_t;
signal clk_2, clk_1 : STD_LOGIC;
signal hdu : hdu_t;
signal sdu : sdu_t;
signal cpu_rst : STD_LOGIC;
signal reg_a : word_t;
signal reg_b : word_t;
signal ctrl_lines : ctrl_lines_t;
signal cpu_run : STD_LOGIC;
signal branch_ce : STD_LOGIC;
signal run_en : STD_LOGIC;
signal mul_dep : STD_LOGIC;
signal imem_dep : STD_LOGIC;
signal dmem_dep : STD_LOGIC;
signal cop_ctrl : cop_ctrl_in_t;
signal cop_stat : cop_ctrl_out_t;
signal cop_din : word_t;
signal cop_dout : word_t;
signal alu_result : word_t;
signal mul_result : word_t;
signal mul_busy : STD_LOGIC;
signal EX_events_instr : event_t;
signal EX_events_alu : event_t;
signal EX_events_mem : event_t;
signal EX_events : event_t;
signal MEM_events : event_t;
signal bcu_op_a : word_t;
signal bcu_op_b : word_t;
signal bcu_flags : bcu_flags_t;
signal vaddr : word_t;
attribute ram_style : string;
attribute ram_style of reg_a: signal is "distributed";
attribute ram_style of reg_b: signal is "distributed";
signal pc : pc_t;
--------------------------------------------------------------------------
begin
clk_1 <= clk;
clk_2 <= not clk;
cpu_run <= run_en;
-- Stall Detection Unit ---------------------------------------------------
sdu.ID_nop <= imem_dep or cop_stat.exc_pending or EX_stage.exc or MEM_stage.exc;
sdu.EX_nop <= mul_dep or ID_stage.nop or ID_stage.exc;
sdu.MEM_nop <= EX_stage.nop or EX_stage.exc;
sdu.WB_nop <= dmem_dep or MEM_stage.nop;
sdu.ID_stall <= dmem_dep or imem_dep or mul_dep or ID_stage.exc;
sdu.EX_stall <= dmem_dep;
sdu.MEM_stall <= dmem_dep;
sdu.WB_stall <= '0';
mul_dep <= ID_stage.ctrl.mul_access and (EX_stage.ctrl.mul_start or mul_busy);
imem_dep <= not imem_rdy;
dmem_dep <= not dmem_rdy and MEM_stage.ctrl.dmem_en;
---------------------------------------------------------------------------
imem_en <= cpu_run and not (mul_dep or dmem_dep or cop_stat.exc_commit);
--------------------------------------------------------------------------
-- Muldiv
--------------------------------------------------------------------------
inst_muldiv: muldiv
PORT MAP
(
rst => cpu_rst,
clk => clk,
hilo_we => EX_stage.ctrl.mul_hilo_we,
din_hi => EX_stage.reg_a,
din_lo => EX_stage.reg_b,
mul_divn => EX_stage.ctrl.mul_mul_divn,
start => EX_stage.ctrl.mul_start,
s_un => EX_stage.ctrl.mul_s_un,
hilo_sel => EX_stage.ctrl.mul_hilo_sel,
busy => mul_busy,
dout => mul_result
);
--------------------------------------------------------------------------
-- Coprocessor
--------------------------------------------------------------------------
inst_cop: cop
PORT MAP
(
rst => cpu_rst,
clk => clk,
sdu => sdu,
events => MEM_stage.events,
IR_valid => ID_stage.ctrl.cop_instr_en,
IR => ID_stage.IR,
ctrl_in => cop_ctrl,
ctrl_out => cop_stat,
dout => cop_dout,
din => cop_din
);
cop_ctrl.bd_wb <= WB_stage.bd;
cop_ctrl.epc_mem <= MEM_stage.pcn;
cop_ctrl.epc_wb <= MEM_stage.epc;
cop_ctrl.imem_addr <= pc.nxt;
cop_ctrl.dmem_addr <= MEM_stage.va;
--------------------------------------------------------------------------
-- IF stage
--------------------------------------------------------------------------
imem_addr <= pc.curr;
proc_stage_pc:
process(pc, rst, cop_stat)
begin
if rst = '1' then
pc.curr <= RESET_VECTOR after 2 ns;
else
if pc.is_branch and cop_stat.exc_pending = '0' then
pc.curr <= pc.pc_branch after 2 ns;
else
pc.curr <= pc.nxt after 2 ns;
end if;
end if;
end process;
proc_stage_pc_branch:
process(clk_1)
begin
if rising_edge(clk_1) then
if sdu.ID_stall = '0' then
pc.pc_branch <= pc.curr + ID_stage.bimm18;
end if;
end if;
end process;
proc_stage_pc_next:
process(clk_1)
begin
if rising_edge(clk_1) then
branch_ce <= '0';
cop_ctrl.exc_left <= '0';
if rst = '1' then
pc.nxt <= pc.curr;
pc.last <= pc.curr;
else
if cop_stat.exc_commit = '1' then
pc.nxt <= cop_stat.exc_vec;
elsif sdu.ID_stall = '0' then
cop_ctrl.exc_left <= cop_stat.exc_exit;
branch_ce <= '1';
pc.last <= pc.curr;
if ID_stage.ctrl.jump = '1' then
pc.nxt <= ID_stage.jimm32;
elsif ID_stage.ctrl.jump_long = '1' then
pc.nxt <= ID_stage.reg_a;
else
pc.nxt <= pc.curr + 4;
end if;
end if;
end if;
end if;
end process;
proc_stage_branch:
process(clk_2)
begin
if rising_edge(clk_2) and branch_ce = '1' then
pc.is_branch <= false;
if EX_stage.ctrl.branch = '1' then
case EX_stage.ctrl.bc_src is
when bc_eq_ne =>
if (EX_stage.ctrl.bc_not xor bcu_flags.eq) = '1' then
pc.is_branch <= true;
end if;
when bc_lez_gtz =>
if (EX_stage.ctrl.bc_not xor (bcu_flags.eq or bcu_flags.ltz)) = '1' then
pc.is_branch <= true;
end if;
when bc_ltz_gez =>
if (EX_stage.ctrl.bc_not xor bcu_flags.ltz) = '1' then
pc.is_branch <= true;
end if;
when others => null;
end case;
end if;
end if;
end process;
process(rst, clk_1)
variable reset_delay : unsigned (5 downto 0);
begin
if rising_edge(clk_1) then
if rst = '1' then
reset_delay := (others => '1');
cpu_rst <= '1';
run_en <= '0';
elsif reset_delay /= (5 downto 0 => '0') then
reset_delay := reset_delay - 1;
else
cpu_rst <= '0';
end if;
if reset_delay(reset_delay'left-1) = '0' then
run_en <= '1';
end if;
end if;
end process;
--------------------------------------------------------------------------
-- ID stage
--------------------------------------------------------------------------
ID_stage.IR <= to_01(imem_data);
ID_stage.pcn <= pc.curr;
ID_stage.op <= decode_op(ID_stage.IR);
ID_stage.jimm32 <= extract_jimm32(ID_stage.IR, ID_stage.pcn);
ID_stage.bimm18 <= extract_bimm18(ID_stage.IR, ID_stage.pcn);
ID_stage.shamt <= extract_shamt(ID_stage.IR);
ID_stage.reg_a_rptr <= extract_rs(ID_stage.IR);
ID_stage.reg_b_rptr <= extract_rt(ID_stage.IR);
ID_stage.ctrl <= ctrl_lines;
ID_stage.reg_write <= ID_stage.ctrl.reg_write or cop_stat.reg_write;
ID_stage.epc <= pc.last;
ID_stage.exc <= event_is_active(ID_stage.events); -- Todo: works
ID_stage.nop <= sdu.ID_nop;
proc_ID_except:
process(ID_stage, cop_stat, pc)
begin
ID_stage.events <= events_clr;
ID_stage.events.inst_load_err <= pc.nxt(1) or pc.nxt(0);
ID_stage.events.inst_priv_addr <= pc.nxt(word_t'left) and cop_stat.user_mode;
end process;
proc_stage_hdu:
process(ID_stage, EX_stage, MEM_stage, WB_stage)
variable read_a, read_b : boolean;
variable raw_a_EX, raw_a_MEM, raw_a_WB : boolean;
variable raw_b_EX, raw_b_MEM, raw_b_WB : boolean;
variable reg_ptr_a : reg_ptr_t;
variable reg_ptr_b : reg_ptr_t;
begin
reg_ptr_a := ID_stage.reg_a_rptr;
reg_ptr_b := ID_stage.reg_b_rptr;
raw_a_EX := reg_ptr_a = EX_stage.reg_wptr and EX_stage.wreg_we = '1';
raw_a_MEM := reg_ptr_a = MEM_stage.reg_wptr and MEM_stage.wreg_we = '1';
raw_a_WB := reg_ptr_a = WB_stage.reg_wptr and WB_stage.wreg_we = '1';
raw_b_EX := reg_ptr_b = EX_stage.reg_wptr and EX_stage.wreg_we = '1';
raw_b_MEM := reg_ptr_b = MEM_stage.reg_wptr and MEM_stage.wreg_we = '1';
raw_b_WB := reg_ptr_b = WB_stage.reg_wptr and WB_stage.wreg_we = '1';
hdu.alu_fwd_a_ex <= raw_a_EX after 1 ns;
hdu.alu_fwd_a_mem <= raw_a_MEM after 1 ns;
hdu.alu_fwd_a_wb <= raw_a_WB after 1 ns;
hdu.alu_fwd_b_ex <= raw_b_EX after 1 ns;
hdu.alu_fwd_b_mem <= raw_b_MEM after 1 ns;
hdu.alu_fwd_b_wb <= raw_b_WB after 1 ns;
end process;
proc_stage_fwd_a:
process(reg_a, hdu, EX_stage, MEM_stage, WB_stage)
variable data : word_t;
begin
data := reg_a;
if hdu.alu_fwd_a_ex then
data := EX_stage.result;
elsif hdu.alu_fwd_a_mem then
data := MEM_stage.data;
elsif hdu.alu_fwd_a_wb then
data := WB_stage.data;
end if;
ID_stage.reg_a <= to_01(data) after 2 ns;
end process;
proc_stage_fwd_b:
process(reg_b, hdu, EX_stage, MEM_stage, WB_stage)
variable data : word_t;
begin
data := reg_b;
if hdu.alu_fwd_b_ex then
data := EX_stage.result;
elsif hdu.alu_fwd_b_mem then
data := MEM_stage.data;
elsif hdu.alu_fwd_b_wb then
data := WB_stage.data;
end if;
ID_stage.reg_b <= to_01(data) after 2 ns;
end process;
proc_imm_mux:
process(ID_stage)
variable data : word_t;
begin
data := extract_uimm16(ID_stage.IR);
case ID_stage.ctrl.imm_src is
when src_imm32 =>
data := extract_simm32(ID_stage.IR);
when src_imm16 =>
data := extract_uimm16(ID_stage.IR);
when src_imm16_high =>
data := ID_stage.IR(word_t'length/2-1 downto 0) & (word_t'length/2-1 downto 0 => '0');
when others => null;
end case;
ID_stage.imm <= data after 2 ns;
end process;
--------------------------------------------------------------------------
inst_idecode_rom: idecode_rom
PORT MAP
(
nop => sdu.ID_nop,
inst_in => ID_stage.IR,
ctrl_out => ctrl_lines
);
inst_reg_dual: reg_dual
GENERIC MAP
(
addr_width => reg_ptr_t'length,
data_width => word_t'length
)
PORT MAP
(
clk_w => clk_1,
we => WB_stage.wreg_we,
en => '1',
wptr => WB_stage.reg_wptr,
din => WB_stage.data,
rptr_a => ID_stage.reg_a_rptr,
rptr_b => ID_stage.reg_b_rptr,
dout_a => reg_a,
dout_b => reg_b
);
--------------------------------------------------------------------------
-- EX stage
--------------------------------------------------------------------------
EX_stage.reg_a_rptr <= extract_rs(EX_stage.IR);
EX_stage.reg_b_rptr <= extract_rt(EX_stage.IR);
EX_stage.result <= alu_result when EX_stage.ctrl.mul_access = '0' else mul_result;
proc_stage_ID_EX_1:
process(clk_1)
begin
if rising_edge(clk_1) then
if rst = '1' then
EX_stage.op <= NOP;
EX_stage.IR <= (others => '0');
EX_stage.ctrl <= ctrl_lines_default;
EX_stage.reg_write <= '0';
EX_stage.epc <= (others => '0');
EX_stage.pcn <= (others => '0');
EX_stage.events_in <= events_clr;
elsif sdu.EX_stall = '0' then
EX_stage.reg_a <= ID_stage.reg_a;
EX_stage.reg_b <= ID_stage.reg_b;
EX_stage.events_in <= ID_stage.events;
EX_stage.op <= ID_stage.op;
EX_stage.ctrl <= ID_stage.ctrl;
EX_stage.reg_write <= ID_stage.reg_write;
EX_stage.nop <= sdu.EX_nop;
EX_stage.IR <= ID_stage.IR;
EX_stage.pcn <= ID_stage.pcn;
if sdu.EX_nop = '1' then
EX_stage.op <= NOP;
EX_stage.IR <= (others => '0');
EX_stage.ctrl <= ctrl_lines_default;
EX_stage.reg_write <= '0';
else
EX_stage.epc <= ID_stage.epc;
end if;
end if;
end if;
end process;
proc_stage_EX_instr_except:
process(EX_stage)
begin
EX_events_instr <= events_clr;
EX_events_instr.illegal <= EX_stage.ctrl.exc_illegal;
EX_events_instr.break <= EX_stage.ctrl.exc_break;
EX_events_instr.syscall <= EX_stage.ctrl.exc_syscall;
end process;
proc_stage_EX_alu_except:
process(EX_stage)
begin
EX_events_alu <= events_clr;
if EX_stage.ctrl.alu_exc_en = '1' then
if EX_stage.alu_flags.ovf = '1' then
EX_events_alu.alu_ovf <= '1';
end if;
if EX_stage.alu_flags.uvf = '1' then
EX_events_alu.alu_uvf <= '1';
end if;
end if;
end process;
vaddr <= ID_stage.reg_a + extract_simm32(ID_stage.IR);
proc_stage_EX_mem_except:
process(clk_1)
begin
if rising_edge(clk_1) then
if rst = '1' then
dmem_en <= '0';
elsif sdu.EX_stall = '0' then
EX_events_mem <= events_clr;
dmem_en <= '0';
if ID_stage.ctrl.dmem_en = '1' then
dmem_en <= '1';
if ID_stage.ctrl.except_en = '1' then
if ID_stage.ctrl.word2_en = '1' then
if vaddr(0) = '1' then
EX_events_mem.data_load_err <= not ID_stage.ctrl.dmem_we;
EX_events_mem.data_store_err <= ID_stage.ctrl.dmem_we;
dmem_en <= '0';
end if;
elsif vaddr(1 downto 0) /= "00" then
EX_events_mem.data_load_err <= not ID_stage.ctrl.dmem_we;
EX_events_mem.data_store_err <= ID_stage.ctrl.dmem_we;
dmem_en <= '0';
end if;
end if;
end if;
end if;
end if;
end process;
proc_stage_DMEM_ADDR:
process(clk_1)
begin
if rising_edge(clk_1) then
if sdu.EX_stall = '0' then
EX_stage.va <= vaddr;
if cop_stat.RE = '1' then
EX_stage.pa_off <= not vaddr(1 downto 0);
else
EX_stage.pa_off <= vaddr(1 downto 0);
end if;
end if;
end if;
end process;
dmem_be <= store_be(EX_stage.pa_off, EX_stage.ctrl.dmem_we, EX_stage.ctrl.word2_en, EX_stage.ctrl.word4_en, EX_stage.ctrl.align_left, EX_stage.ctrl.byte_en_byp) after 1 ns;
dmem_we <= EX_stage.ctrl.dmem_we;
dmem_dout <= store_shift(EX_stage.reg_b, EX_stage.pa_off, EX_stage.ctrl.shift_offset, EX_stage.ctrl.shift_byp) after 1ns;
dmem_addr <= EX_stage.va;
cop_din <= EX_stage.reg_b;
EX_stage.events <= EX_events_instr or EX_events_mem or EX_events_alu or EX_stage.events_in;
EX_stage.exc <= event_is_active(EX_stage.events);
--------------------------------------------------------------------------
proc_wptr_mux:
process(EX_stage)
variable opclass : opcode_t;
variable reg_wptr : reg_ptr_t;
begin
opclass := extract_opc(EX_stage.IR);
case opclass is
when "000000" =>
reg_wptr := extract_rd(EX_stage.IR);
when others =>
reg_wptr := extract_rt(EX_stage.IR);
end case;
EX_stage.wreg_we <= EX_stage.reg_write after 1 ns;
if reg_wptr = "00000" then
EX_stage.wreg_we <= '0' after 1 ns;
end if;
EX_stage.reg_wptr <= reg_wptr after 1 ns;
case EX_stage.ctrl.wptr_srcsel is
when wptr_src_imm =>
EX_stage.reg_wptr <= reg_wptr after 1 ns;
when wptr_src_const =>
EX_stage.reg_wptr <= to_unsigned(31, reg_ptr_t'length) after 1 ns;
EX_stage.wreg_we <= '1' after 1 ns;
when others => null;
end case;
end process;
--------------------------------------------------------------------------
proc_stage_bcu_op:
process(clk_1)
begin
if rising_edge(clk_1) and sdu.EX_stall = '0' then
bcu_op_a <= ID_stage.reg_a;
bcu_op_b <= ID_stage.reg_b;
end if;
end process;
EX_stage.alu_op1 <= EX_stage.reg_a;
alu_op2_mux:
process(clk_1)
variable data : word_t;
begin
if rising_edge(clk_1) and sdu.EX_stall = '0' then
data := ID_stage.reg_b;
case ID_stage.ctrl.alu.op2_src is
when alu_src_reg =>
data := ID_stage.reg_b;
when alu_src_imm =>
data := ID_stage.imm;
when others => null;
end case;
EX_stage.alu_op2 <= data;
end if;
end process;
shifter_sa_mux:
process(clk_1)
variable data : shamt_t;
variable data_inv : shamt_t;
begin
if rising_edge(clk_1) and sdu.EX_stall = '0' then
data := ID_stage.reg_a(4 downto 0);
case ID_stage.ctrl.shamt2_srcsel is
when sa_src_reg =>
data := ID_stage.reg_a(4 downto 0);
when sa_src_imm =>
data := ID_stage.shamt;
when others => null;
end case;
data_inv := not data + 1;
if ID_stage.ctrl.alu.shift_right = '0' then
EX_stage.shift_ctrl.shamt_rnd <= data_inv after 2 ns;
else
EX_stage.shift_ctrl.shamt_rnd <= data after 2 ns;
end if;
EX_stage.shift_ctrl.shamt_nrm <= data after 1 ns;
EX_stage.shift_ctrl.shift_right <= ID_stage.ctrl.alu.shift_right;
EX_stage.shift_ctrl.shift_arith <= ID_stage.ctrl.alu.shift_arith;
end if;
end process;
--------------------------------------------------------------------------
inst_shifter: shifter
GENERIC MAP
(
data_width => word_t'length
)
PORT MAP
(
shift_ctrl => EX_stage.shift_ctrl,
din => EX_stage.reg_b,
dout => EX_stage.alu_op2_s
);
inst_alu: alu
GENERIC MAP
(
data_width => word_t'length
)
PORT MAP
(
op1_in => EX_stage.alu_op1,
op2_in => EX_stage.alu_op2,
op2_shifted => EX_stage.alu_op2_s,
ctrl => EX_stage.ctrl.alu,
result => alu_result,
flags => EX_stage.alu_flags
);
inst_bcu: bcu
GENERIC MAP
(
data_width => word_t'length
)
PORT MAP
(
op1_in => bcu_op_a,
op2_in => bcu_op_b,
flags => bcu_flags
);
--------------------------------------------------------------------------
-- MEM stage
--------------------------------------------------------------------------
proc_stage_MEM_n:
process(clk_1)
begin
if rising_edge(clk_1) then
if rst = '1' then
MEM_stage.op <= NOP;
MEM_stage.wreg_we <= '0';
MEM_stage.ctrl <= ctrl_lines_default;
MEM_stage.pa_off <= (others => '0');
MEM_stage.events_in <= events_clr;
elsif sdu.MEM_stall = '0' then
MEM_stage.events_in <= EX_stage.events;
MEM_stage.op <= EX_stage.op;
MEM_stage.wreg_we <= EX_stage.wreg_we;
MEM_stage.ctrl <= EX_stage.ctrl;
MEM_stage.va <= EX_stage.va;
MEM_stage.pa_off <= EX_stage.pa_off;
MEM_stage.reg_wptr <= EX_stage.reg_wptr;
MEM_stage.nop <= sdu.MEM_nop;
if EX_stage.ctrl.dmem_en = '1' then
MEM_stage.ex_result <= EX_stage.reg_b;
else
MEM_stage.ex_result <= EX_stage.result;
if cop_stat.cop_read = '1' then
MEM_stage.ex_result <= cop_dout;
end if;
end if;
if sdu.MEM_nop = '1' then
MEM_stage.op <= NOP;
MEM_stage.wreg_we <= '0';
MEM_stage.ctrl <= ctrl_lines_default;
else
MEM_stage.pcn <= EX_stage.pcn;
MEM_stage.epc <= EX_stage.epc;
end if;
end if;
end if;
end process;
proc_stage_MEM_mux:
process(MEM_stage, dmem_din)
variable temp1 : word_t;
variable temp2 : word_t;
variable data : word_t;
variable be : unsigned(3 downto 0);
begin
data := MEM_stage.ex_result;
be := load_be(MEM_stage.pa_off, MEM_stage.ctrl.align_left, MEM_stage.ctrl.byte_en_byp);
if MEM_stage.ctrl.reg_link = '1' then
data := MEM_stage.pcn + 4;
elsif MEM_stage.ctrl.dmem_en = '1' then
temp1 := load_shift(dmem_din, MEM_stage.pa_off, MEM_stage.ctrl.shift_offset, MEM_stage.ctrl.shift_byp);
temp2 := load_sign_ext(temp1, MEM_stage.ctrl.sign_ext_byp, MEM_stage.ctrl.load_signed, MEM_stage.ctrl.word2_en, MEM_stage.ctrl.word4_en);
if be(0) = '1' then
data(7 downto 0) := temp2(7 downto 0);
end if;
if be(1) = '1' then
data(15 downto 8) := temp2(15 downto 8);
end if;
if be(2) = '1' then
data(23 downto 16) := temp2(23 downto 16);
end if;
if be(3) = '1' then
data(31 downto 24) := temp2(31 downto 24);
end if;
end if;
MEM_stage.data <= data after 1 ns;
end process;
proc_stage_MEM_except:
process(MEM_stage, int)
begin
MEM_stage.events <= MEM_stage.events_in;
MEM_stage.events.Int <= int;
end process;
MEM_stage.exc <= cop_stat.int or event_is_active(MEM_stage.events_in);
--------------------------------------------------------------------------
-- WB stage
--------------------------------------------------------------------------
proc_stage_WB_p:
process(clk_1)
begin
if rising_edge(clk_1) then
if rst = '1' then
WB_stage.op <= NOP;
WB_stage.wreg_we <= '0';
elsif sdu.WB_stall = '0' then
WB_stage.op <= MEM_stage.op;
WB_stage.wreg_we <= MEM_stage.wreg_we;
WB_stage.reg_wptr <= MEM_stage.reg_wptr;
WB_stage.data <= MEM_stage.data;
WB_stage.nop <= sdu.WB_nop;
if sdu.WB_nop = '1' then
WB_stage.op <= NOP;
WB_stage.wreg_we <= '0';
else
WB_stage.epc <= MEM_stage.epc;
WB_stage.bd <= MEM_stage.ctrl.branch or MEM_stage.ctrl.jump or MEM_stage.ctrl.jump_long; -- Todo: works
end if;
end if;
end if;
end process;
--------------------------------------------------------------------------
end Behavioral;
+81
View File
@@ -0,0 +1,81 @@
--------------------------------------------------------------------------
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
-- This file: On-Chip work registers
--
-- Copyright (C) 2008 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
use work.mips_types.all;
entity reg_dual is
Generic
(
addr_width : integer := 3;
data_width : integer := 8
);
Port (
clk_w : in STD_LOGIC;
we : in STD_LOGIC;
en : in STD_LOGIC;
wptr : in unsigned (addr_width-1 downto 0);
din : in unsigned (data_width-1 downto 0);
rptr_a : in unsigned (addr_width-1 downto 0);
rptr_b : in unsigned (addr_width-1 downto 0);
dout_a : out unsigned (data_width-1 downto 0);
dout_b : out unsigned (data_width-1 downto 0)
);
end reg_dual;
architecture Behavioral of reg_dual is
constant depth : integer := 2**addr_width;
type mem_t is array (0 to depth-1) of unsigned (data_width-1 downto 0);
function mem_clear(depth : natural) return mem_t is
variable result : mem_t;
begin
for i in 0 to depth-1 loop
result(i) := (others => '0');
end loop;
return result;
end mem_clear;
signal reg_mem : mem_t := mem_clear(depth);
begin
reg_in:
process(clk_w)
begin
if rising_edge(clk_w) then
if we = '1' and en = '1' then
reg_mem(to_integer(wptr)) <= din;
end if;
end if;
end process;
dout_a <= reg_mem(to_integer(rptr_a)) after 2 ns;
dout_b <= reg_mem(to_integer(rptr_b)) after 2 ns;
end Behavioral;
+114
View File
@@ -0,0 +1,114 @@
--------------------------------------------------------------------------
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
-- This file: The shifter unit
--
-- Copyright (C) 2008 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
use work.mips_types.all;
entity shifter is
Generic
(
data_width : integer := 8
);
Port
(
shift_ctrl : in shift_ctrl_t;
din : in unsigned (data_width-1 downto 0);
dout : out unsigned (data_width-1 downto 0)
);
end shifter;
architecture Behavioral of shifter is
subtype word_t is unsigned(data_width-1 downto 0);
type word_array_t is array (0 to 5) of word_t;
signal rot_data : word_array_t;
signal sa_rnd : unsigned (4 downto 0);
signal fill : std_logic;
--------------------------------------------------------------------------
function rot_stage(x : unsigned; en : std_logic; stage_num : natural) return unsigned is
variable result : unsigned(x'range);
constant sa : natural := 2**stage_num;
begin
if en = '1' then
result := x(sa-1 downto 0) & x(x'left downto sa);
else
result := x;
end if;
return result;
end rot_stage;
function rot_fill(x : unsigned; fill : std_logic; shift_right : std_logic; sa : natural) return unsigned is
variable result : unsigned(x'range) := (others => '0');
variable j : integer;
begin
if shift_right = '0' then
for i in 0 to x'left loop
if i >= sa then
result(i) := x(i);
else
result(i) := fill;
end if;
end loop;
else
j := x'left;
for i in 0 to x'left loop
if i < sa then
result(j) := fill;
else
result(j) := x(j);
end if;
j := j - 1;
end loop;
end if;
return result;
end rot_fill;
--------------------------------------------------------------------------
begin
rot_data(0) <= din;
gen_rotate_right:
for stage in 0 to 4 generate
begin
rot_data(stage+1) <= rot_stage(rot_data(stage), sa_rnd(stage), stage);
end generate;
sa_rnd <= shift_ctrl.shamt_rnd;
fill <= shift_ctrl.shift_arith and din(data_width-1);
dout <= rot_fill(rot_data(5), fill, shift_ctrl.shift_right, to_integer(shift_ctrl.shamt_nrm)) after 5 ns;
-- dout <= rot_data(5);
--------------------------------------------------------------------------
end Behavioral;
+190
View File
@@ -0,0 +1,190 @@
--------------------------------------------------------------------------
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
-- This file: JIPS top file
--
-- Copyright (C) 2008 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
library work;
use work.mips_types.all;
entity mips_top is
Port
(
debug : out unsigned(1 downto 0);
RST_I : in STD_LOGIC;
CLK_I : in STD_LOGIC;
ACK_I : in STD_LOGIC;
SRDY_I : in STD_LOGIC;
ADDR_O : out word_t;
DAT_I : in word_t;
DAT_O : out word_t;
WE_O : out STD_LOGIC;
SEL_O : out unsigned(3 downto 0);
CYC_O : out STD_LOGIC;
STB_O : out STD_LOGIC;
MRDY_O : out STD_LOGIC;
INT : in unsigned (5 downto 0)
);
end mips_top;
architecture rtl of mips_top is
COMPONENT pipeline is
Port
(
rst : in STD_LOGIC;
clk : in STD_LOGIC;
halt : in STD_LOGIC;
int : in unsigned (5 downto 0);
imem_err : in STD_LOGIC;
imem_rdy : in STD_LOGIC;
imem_en : out STD_LOGIC;
imem_addr : out word_t;
imem_data : in word_t;
dmem_err : in STD_LOGIC;
dmem_rdy : in STD_LOGIC;
dmem_en : out STD_LOGIC;
dmem_we : out STD_LOGIC;
dmem_be : out unsigned(3 downto 0);
dmem_addr : out word_t;
dmem_din : in word_t;
dmem_dout : out word_t
);
END COMPONENT;
signal imem_err : std_logic;
signal imem_rdy : std_logic;
signal imem_en : std_logic;
signal imem_addr : word_t;
signal imem_din : word_t;
signal dmem_err : std_logic;
signal dmem_rdy : std_logic;
signal dmem_en : std_logic;
signal dmem_we : std_logic;
signal dmem_addr : word_t;
signal dmem_dout : word_t;
signal dmem_din : word_t;
signal dmem_be : unsigned(3 downto 0);
COMPONENT biu
GENERIC
(
icache_size : natural;
dcache_size : natural
);
PORT
(
RST_I : in STD_LOGIC;
CLK_I : in STD_LOGIC;
ACK_I : in STD_LOGIC;
SRDY_I : in STD_LOGIC;
ADDR_O : out word_t;
DAT_I : in word_t;
DAT_O : out word_t;
WE_O : out STD_LOGIC;
SEL_O : out unsigned(3 downto 0);
CYC_O : out STD_LOGIC;
STB_O : out STD_LOGIC;
MRDY_O : out STD_LOGIC;
cpu_imem_err : out STD_LOGIC;
cpu_imem_rdy : out STD_LOGIC;
cpu_imem_en : in STD_LOGIC;
cpu_imem_addr : in word_t;
cpu_imem_din : out word_t;
cpu_dmem_err : out STD_LOGIC;
cpu_dmem_rdy : out STD_LOGIC;
cpu_dmem_en : in STD_LOGIC;
cpu_dmem_we : in STD_LOGIC;
cpu_dmem_be : in unsigned(3 downto 0);
cpu_dmem_dout : in word_t;
cpu_dmem_din : out word_t;
cpu_dmem_addr : in word_t
);
END COMPONENT;
begin
-------------------------------------------------------------------
debug(0) <= imem_err;
debug(1) <= dmem_err;
inst_pipeline: pipeline
PORT MAP
(
rst => RST_I,
clk => CLK_I,
halt => '0',
int => INT,
imem_err => imem_err,
imem_rdy => imem_rdy,
imem_en => imem_en,
imem_addr => imem_addr,
imem_data => imem_din,
dmem_err => dmem_err,
dmem_rdy => dmem_rdy,
dmem_en => dmem_en,
dmem_we => dmem_we,
dmem_be => dmem_be,
dmem_addr => dmem_addr,
dmem_din => dmem_din,
dmem_dout => dmem_dout
);
inst_biu: biu
GENERIC MAP
(
icache_size => 4096, -- words
dcache_size => 4096 -- words
)
PORT MAP
(
RST_I => RST_I,
CLK_I => CLK_I,
ACK_I => ACK_I,
SRDY_I => SRDY_I,
ADDR_O => ADDR_O,
DAT_I => DAT_I,
DAT_O => DAT_O,
WE_O => WE_O,
SEL_O => SEL_O,
CYC_O => CYC_O,
STB_O => STB_O,
MRDY_O => MRDY_O,
cpu_imem_err => imem_err,
cpu_imem_rdy => imem_rdy,
cpu_imem_en => imem_en,
cpu_imem_addr => imem_addr,
cpu_imem_din => imem_din,
cpu_dmem_err => dmem_err,
cpu_dmem_rdy => dmem_rdy,
cpu_dmem_en => dmem_en,
cpu_dmem_we => dmem_we,
cpu_dmem_be => dmem_be,
cpu_dmem_addr => dmem_addr,
cpu_dmem_din => dmem_din,
cpu_dmem_dout => dmem_dout
);
end rtl;
+619
View File
@@ -0,0 +1,619 @@
--------------------------------------------------------------------------
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
-- This file: Types, constants and functions for JIPS
--
-- Copyright (C) 2008 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
--------------------------------------------------------------------------
package mips_types is
-- Revision of the CPU
constant REVISION : integer := 9;
constant WORD_WIDTH : integer := 32;
--Types
subtype instr_name_t is string(1 to 12);
type instr_name_array_t is array (0 to 63) of instr_name_t;
subtype opcode_t is unsigned (5 downto 0);
subtype word_t is unsigned (WORD_WIDTH-1 downto 0);
subtype reg_ptr_t is unsigned (4 downto 0);
subtype shamt_t is unsigned(4 downto 0);
subtype sa_t is natural range 0 to 63;
subtype func_t is unsigned(5 downto 0);
type opclass_t is (special, regimm, opcode);
type op_t is
(
nop,
op_sll,
op_srl,
op_sra,
op_sllv,
op_srlv,
op_srav,
op_jr,
op_jalr,
op_syscall,
op_break,
op_mfhi,
op_mthi,
op_mflo,
op_mtlo,
op_mult,
op_multu,
op_div,
op_divu,
op_add,
op_addu,
op_sub,
op_subu,
op_and,
op_or,
op_xor,
op_nor,
op_slt,
op_sltu,
op_bltz,
op_bgez,
op_bltzal,
op_bgezal,
op_j,
op_jal,
op_beq,
op_bne,
op_blez,
op_bgtz,
op_addi,
op_addiu,
op_slti,
op_sltiu,
op_andi,
op_ori,
op_xori,
op_lui,
op_lb,
op_lh,
op_lwl,
op_lw,
op_lbu,
op_lhu,
op_lwr,
op_sb,
op_sh,
op_swl,
op_sw,
op_swr,
op_cop0,
op_cop1,
op_cop2,
op_cop3,
op_lwc1,
op_lwc2,
op_lwc3,
op_swc1,
op_swc2,
op_swc3
);
attribute ENUM_ENCODING : string;
type imm_src_t is (src_imm32, src_imm16, src_imm16_high);
type sa_src_t is (sa_src_reg, sa_src_imm);
type alu_src1_t is (alu_src_reg);
type alu_src2_t is (alu_src_reg, alu_src_imm);
type bc_src_t is (bc_eq_ne, bc_lez_gtz, bc_ltz_gez);
type shift_opsel_t is (shift_sll, shift_srl, shift_sra);
type wptr_src_t is (wptr_src_imm, wptr_src_const);
-- attribute ENUM_ENCODING of itype_t: type is "ONE-HOT";
type pc_t is record
curr : word_t;
last : word_t;
nxt : word_t;
pc_branch : word_t;
is_branch : boolean;
end record;
type alu_outsel_t is
(
alu_adder,
alu_shift2,
alu_and,
alu_or,
alu_xor,
alu_nor,
alu_ltu,
alu_lts
);
type alu_flags_t is record
c : STD_LOGIC;
uvf : STD_LOGIC;
ovf : STD_LOGIC;
ltu : STD_LOGIC;
lts : STD_LOGIC;
end record;
type bcu_flags_t is record
eq : STD_LOGIC;
ltz : STD_LOGIC;
end record;
type event_t is record
Int : unsigned(5 downto 0);
data_load_err : STD_LOGIC;
data_store_err : STD_LOGIC;
inst_load_err : STD_LOGIC;
inst_priv_addr : STD_LOGIC;
alu_ovf : STD_LOGIC;
alu_uvf : STD_LOGIC;
syscall : STD_LOGIC;
break : STD_LOGIC;
illegal : STD_LOGIC;
end record;
type exc_flags_t is record
Int : STD_LOGIC;
DAdEL : STD_LOGIC;
DAdES : STD_LOGIC;
IAdEL : STD_LOGIC;
IAdEK : STD_LOGIC;
Ov : STD_LOGIC;
Sys : STD_LOGIC;
Bp : STD_LOGIC;
RI : STD_LOGIC;
IBE : STD_LOGIC;
DBE : STD_LOGIC;
end record;
type except_t is record
act : STD_LOGIC;
epc : word_t;
cause : word_t;
end record;
type cop_ctrl_in_t is record
bd_wb : STD_LOGIC;
epc_mem : word_t;
epc_wb : word_t;
imem_addr : word_t;
dmem_addr : word_t;
exc_left : STD_LOGIC;
end record;
type cop_ctrl_out_t is record
RE : STD_LOGIC;
ee : STD_LOGIC;
ec : STD_LOGIC;
exc_commit : STD_LOGIC;
exc_pending : STD_LOGIC;
exc_exit : STD_LOGIC;
reg_write : STD_LOGIC;
cop_read : STD_LOGIC;
user_mode : STD_LOGIC;
int : STD_LOGIC;
exc_vec : word_t;
end record;
type sdu_t is record
ID_nop : STD_LOGIC;
EX_nop : STD_LOGIC;
MEM_nop : STD_LOGIC;
WB_nop : STD_LOGIC;
ID_stall : STD_LOGIC;
EX_stall : STD_LOGIC;
MEM_stall : STD_LOGIC;
WB_stall : STD_LOGIC;
end record;
type hdu_t is record
alu_fwd_a_ex : boolean;
alu_fwd_a_mem : boolean;
alu_fwd_a_wb : boolean;
alu_fwd_b_ex : boolean;
alu_fwd_b_mem : boolean;
alu_fwd_b_wb : boolean;
end record;
type alu_ctrl_t is record
outsel : alu_outsel_t;
add : STD_LOGIC;
shift_right : STD_LOGIC;
shift_arith : STD_LOGIC;
op1_src : alu_src1_t;
op2_src : alu_src2_t;
end record;
type shift_ctrl_t is record
shamt_nrm : shamt_t;
shamt_rnd : shamt_t;
shift_right : STD_LOGIC;
shift_arith : STD_LOGIC;
end record;
type ctrl_lines_t is record
branch : STD_LOGIC;
jump_long : STD_LOGIC;
jump : STD_LOGIC;
bc_not : STD_LOGIC;
bc_src : bc_src_t;
imm_src : imm_src_t;
alu : alu_ctrl_t;
reg_write : STD_LOGIC;
reg_link : STD_LOGIC;
dmem_we : STD_LOGIC;
dmem_en : STD_LOGIC;
shamt2_srcsel : sa_src_t;
wptr_srcsel : wptr_src_t;
cop_instr_en : STD_LOGIC;
shift_offset : unsigned(1 downto 0);
shift_byp : STD_LOGIC;
byte_en_byp : STD_LOGIC;
sign_ext_byp : STD_LOGIC;
word4_en : STD_LOGIC;
word2_en : STD_LOGIC;
align_left : STD_LOGIC;
load_signed : STD_LOGIC;
mul_access : STD_LOGIC;
mul_hilo_we : STD_LOGIC;
mul_mul_divn : STD_LOGIC;
mul_start : STD_LOGIC;
mul_s_un : STD_LOGIC;
mul_hilo_sel : STD_LOGIC;
exc_break : STD_LOGIC;
exc_syscall : STD_LOGIC;
exc_illegal : STD_LOGIC;
except_en : STD_LOGIC;
alu_exc_en : STD_LOGIC;
end record;
type ID_t is record
nop : STD_LOGIC;
exc : std_logic;
IR : word_t;
op : op_t;
pcn : word_t;
epc : word_t;
jimm32 : word_t;
bimm18 : word_t;
imm : word_t;
shamt : shamt_t;
ctrl : ctrl_lines_t;
reg_write : STD_LOGIC;
reg_a_rptr : reg_ptr_t;
reg_b_rptr : reg_ptr_t;
reg_a : word_t;
reg_b : word_t;
events : event_t;
end record;
type EX_t is record
nop : STD_LOGIC;
exc : std_logic;
IR : word_t;
op : op_t;
pcn : word_t;
epc : word_t;
reg_a : word_t;
reg_b : word_t;
ctrl : ctrl_lines_t;
shift_ctrl : shift_ctrl_t;
alu_op1 : word_t;
alu_op2 : word_t;
alu_op2_s : word_t;
alu_flags : alu_flags_t;
result : word_t;
reg_write : STD_LOGIC;
wreg_we : STD_LOGIC;
reg_wptr : reg_ptr_t;
reg_a_rptr : reg_ptr_t;
reg_b_rptr : reg_ptr_t;
va : word_t;
pa_off : unsigned(1 downto 0);
events_in : event_t;
events : event_t;
end record;
type MEM_t is record
nop : STD_LOGIC;
exc : std_logic;
op : op_t;
pcn : word_t;
epc : word_t;
ctrl : ctrl_lines_t;
ex_result : word_t;
reg_wptr : reg_ptr_t;
wreg_we : STD_LOGIC;
data : word_t;
va : word_t;
pa_off : unsigned(1 downto 0);
events_in : event_t;
events : event_t;
end record;
type WB_t is record
nop : STD_LOGIC;
op : op_t;
epc : word_t;
reg_wptr : reg_ptr_t;
wreg_we : STD_LOGIC;
data : word_t;
bd : STD_LOGIC;
end record;
type rom_special_t is array (0 to 2**func_t'length-1) of ctrl_lines_t;
type rom_regimm_t is array (0 to 2**reg_ptr_t'length-1) of ctrl_lines_t;
type rom_opcode_t is array (0 to 2**opcode_t'length-1) of ctrl_lines_t;
function store_shift(x : word_t; va, shift_off : unsigned(1 downto 0); bypass : std_logic) return word_t;
function store_be(va : unsigned(1 downto 0); be_src, word2_en, word4_en, align_left, bypass : std_logic) return unsigned;
function load_shift(x : word_t; va, shift_off : unsigned(1 downto 0); bypass : std_logic) return word_t;
function load_be(va : unsigned(1 downto 0); align_left, bypass : std_logic) return unsigned;
function load_sign_ext(x : word_t; bypass, signed, word2_en, word4_en : std_logic) return word_t;
function events_clr return event_t;
function event_is_active(e : event_t) return std_logic;
function "or" (a, b : event_t) return event_t;
end mips_types;
--------------------------------------------------------------------------
package body mips_types is
function store_shift(x : word_t; va, shift_off : unsigned(1 downto 0); bypass : std_logic) return word_t is
variable stage1 : word_t;
variable result : word_t;
variable sa : unsigned(1 downto 0);
begin
if bypass = '1' then
sa := "00";
else
sa := va + shift_off;
end if;
stage1 := x;
if sa(0) = '1' then
stage1 := x(23 downto 0) & x(31 downto 24);
end if;
result := stage1;
if sa(1) = '1' then
result := stage1(15 downto 0) & stage1(31 downto 16);
end if;
return result;
end store_shift;
--------------------------------------------------------------------------
function store_be(va : unsigned(1 downto 0); be_src, word2_en, word4_en, align_left, bypass : std_logic) return unsigned is
variable result : unsigned(3 downto 0);
begin
if bypass = '1' then
result := (3 downto 0 => be_src);
elsif word2_en = '1' then
case va is
when "00" | "01" =>
result := "00" & be_src & be_src;
when "10" | "11" =>
result := be_src & be_src & "00";
when others =>
result := "0000";
end case;
elsif word4_en = '1' then
case va is
when "00" =>
result := "000" & be_src;
when "01" =>
result := "00" & be_src & '0';
when "10" =>
result := '0' & be_src & "00";
when "11" =>
result := be_src & "000";
when others =>
result := "0000";
end case;
elsif align_left = '1' then
case va is
when "00" =>
result := be_src & be_src & be_src & be_src;
when "01" =>
result := be_src & be_src & be_src & '0';
when "10" =>
result := be_src & be_src & "00";
when "11" =>
result := be_src & "000";
when others =>
result := "0000";
end case;
else
case va is
when "00" =>
result := "000" & be_src;
when "01" =>
result := "00" & be_src & be_src;
when "10" =>
result := '0' & be_src & be_src & be_src;
when "11" =>
result := be_src & be_src & be_src & be_src;
when others =>
result := "0000";
end case;
end if;
return result;
end store_be;
--------------------------------------------------------------------------
function load_shift(x : word_t; va, shift_off : unsigned(1 downto 0); bypass : std_logic) return word_t is
variable stage1 : word_t;
variable result : word_t;
variable sa : unsigned(1 downto 0);
begin
if bypass = '1' then
sa := "00";
else
sa := va + shift_off;
end if;
stage1 := x;
if sa(0) = '1' then
stage1 := x(7 downto 0) & x(31 downto 8);
end if;
result := stage1;
if sa(1) = '1' then
result := stage1(15 downto 0) & stage1(31 downto 16);
end if;
return result;
end load_shift;
--------------------------------------------------------------------------
function load_be(va : unsigned(1 downto 0); align_left, bypass : std_logic) return unsigned is
variable result : unsigned(3 downto 0);
begin
if bypass = '1' then
result := (3 downto 0 => '1');
elsif align_left = '1' then
case va is
when "00" =>
result := "1000";
when "01" =>
result := "1100";
when "10" =>
result := "1110";
when "11" =>
result := "1111";
when others =>
result := "0000";
end case;
else
case va is
when "00" =>
result := "1111";
when "01" =>
result := "0111";
when "10" =>
result := "0011";
when "11" =>
result := "0001";
when others =>
result := "0000";
end case;
end if;
return result;
end load_be;
--------------------------------------------------------------------------
function load_sign_ext(x : word_t; bypass, signed, word2_en, word4_en : std_logic) return word_t is
variable result : word_t;
variable sign : std_logic;
begin
if bypass = '1' then
result := x;
elsif word2_en = '1' then
sign := signed and x(15);
result := (31 downto 16 => sign) & x(15 downto 0);
else
sign := signed and x(7);
result := (31 downto 8 => sign) & x(7 downto 0);
end if;
return result;
end load_sign_ext;
--------------------------------------------------------------------------
function events_clr return event_t is
variable result : event_t;
begin
result.Int := (others => '0');
result.data_load_err := '0';
result.data_store_err := '0';
result.inst_load_err := '0';
result.inst_priv_addr := '0';
result.alu_ovf := '0';
result.alu_uvf := '0';
result.syscall := '0';
result.break := '0';
result.illegal := '0';
return result;
end events_clr;
function event_is_active(e : event_t) return std_logic is
variable result : std_logic;
begin
result := '0';
for i in e.Int'range loop
result := result or e.Int(i);
end loop;
result := result or e.data_load_err;
result := result or e.data_store_err;
result := result or e.inst_load_err;
result := result or e.inst_priv_addr;
result := result or e.alu_ovf;
result := result or e.alu_uvf;
result := result or e.syscall;
result := result or e.break;
result := result or e.illegal;
return result;
end event_is_active;
function "or" (a, b : event_t) return event_t is
variable result : event_t;
begin
for i in a.Int'range loop
result.Int(i) := a.Int(i) or b.Int(i);
end loop;
result.data_load_err := a.data_load_err or b.data_load_err;
result.data_store_err := a.data_store_err or b.data_store_err;
result.inst_load_err := a.inst_load_err or b.inst_load_err;
result.inst_priv_addr := a.inst_priv_addr or b.inst_priv_addr;
result.alu_ovf := a.alu_ovf or b.alu_ovf;
result.alu_uvf := a.alu_uvf or b.alu_uvf;
result.syscall := a.syscall or b.syscall;
result.break := a.break or b.break;
result.illegal := a.illegal or b.illegal;
return result;
end "or";
--------------------------------------------------------------------------
end mips_types;
--------------------------------------------------------------------------
--------------------------------------------------------------------------
+332
View File
@@ -0,0 +1,332 @@
-------------------------------------------------------------------------
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
-- This file: Testbench for JCPU
-- also writes 'opc.lst' for JASM-assembler
--
-- Copyright (C) 2007 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
LIBRARY ieee;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.numeric_std.ALL;
library work;
use work.mips_types.all;
use work.mips_instr.all;
ENTITY tb_mips_muldiv IS
END tb_mips_muldiv;
ARCHITECTURE behavior OF tb_mips_muldiv IS
COMPONENT muldiv is
Port
(
rst : in std_logic;
clk : in std_logic;
hilo_we : in std_logic;
din_hi : in word_t;
din_lo : in word_t;
mul_divn : in std_logic;
s_un : in std_logic;
start : in std_logic;
hilo_sel : in std_logic;
busy : out std_logic;
dout : out word_t
);
END COMPONENT;
constant CLK_PERIOD : time := 10 ns;
signal ENABLE_FAIL_REPORT : boolean := true;
signal rst : std_logic := '1';
signal clk : std_logic := '1';
signal busy : std_logic;
signal mul_divn : std_logic := '0';
signal s_un : std_logic := '1';
signal hilo_we : std_logic := '0';
signal start : std_logic := '0';
signal din_hi : word_t := (others => '-');
signal din_lo : word_t := (others => '-');
signal dout : word_t;
signal hilo_sel : std_logic := '0';
signal md_result : unsigned (2*word_t'length-1 downto 0) := (others => '0');
signal ref_result : unsigned (2*word_t'length-1 downto 0);
signal ref_hi : unsigned (word_t'length-1 downto 0);
signal rtmp : unsigned (2*word_t'length-1 downto 0);
signal tmp2 : unsigned (word_t'length-1 downto 0);
signal check : std_logic;
type word_array_t is array (natural range <>) of word_t;
constant operands : word_array_t(0 to 63) :=
(
X"00000000",
X"00000001",
X"00000010",
X"00000100",
X"00001000",
X"00010000",
X"00100000",
X"01000000",
X"10000000",
X"0000000F",
X"000000FF",
X"00000FFF",
X"0000FFFF",
X"000FFFFF",
X"00FFFFFF",
X"0FFFFFFF",
X"12345678",
X"23456789",
X"7FFFFFFF",
X"80000000",
X"A541B3B9",
X"80000001",
X"80000010",
X"80000100",
X"80001000",
X"80010000",
X"80100000",
X"81000000",
X"87654321",
X"98765432",
X"FFFFFFFF",
X"FFFFFFFE",
X"FFFFFFFD",
X"FFFFFFFB",
X"FFFFFFF7",
X"FFFFFFEF",
X"FFFFFFDF",
X"FFFFFFBF",
X"FFFFFF7F",
X"FFFFFEFF",
X"FFFFFDFF",
X"FFFFFBFF",
X"FFFFF7FF",
X"FFFFEFFF",
X"FFFFDFFF",
X"FFFFBFFF",
X"FFFF7FFF",
X"FFFEFFFF",
X"FFFDFFFF",
X"FFFBFFFF",
X"FFF7FFFF",
X"FFEFFFFF",
X"FFDFFFFF",
X"FFBFFFFF",
X"FF7FFFFF",
X"FEFFFFFF",
X"FDFFFFFF",
X"FBFFFFFF",
X"F7FFFFFF",
X"EFFFFFFF",
X"DFFFFFFF",
X"BFFFFFFF",
X"CFFFFFFF",
X"7FFFFFFF"
);
BEGIN
uut: muldiv
PORT MAP(
rst => rst,
clk => clk,
hilo_we => hilo_we,
din_hi => din_hi,
din_lo => din_lo,
mul_divn => mul_divn,
s_un => s_un,
start => start,
hilo_sel => hilo_sel,
busy => busy,
dout => dout
);
CLK_GEN: process
begin
wait for CLK_PERIOD/2;
clk <= not clk;
end process;
REF_GEN: process
begin
if mul_divn = '0' then
wait until rising_edge(clk) and check = '1';
if s_un = '1' then
rtmp <= unsigned(signed(md_result(31 downto 0)) * signed(din_lo));
wait until rising_edge(clk);
tmp2 <= unsigned(signed(rtmp(31 downto 0)) + signed(md_result(63 downto 32)));
wait until rising_edge(clk);
ref_hi <= tmp2(31 downto 0);
else
rtmp <= md_result(31 downto 0) * din_lo;
wait until rising_edge(clk);
tmp2 <= rtmp(31 downto 0) + md_result(63 downto 32);
wait until rising_edge(clk);
ref_hi <= tmp2(31 downto 0);
end if;
wait until rising_edge(clk);
if din_lo /= X"00000000" then
if ENABLE_FAIL_REPORT then
assert din_hi = ref_hi report "Error on divison" severity failure;
end if;
end if;
else
wait until rising_edge(clk) and check = '1';
if s_un = '1' then
ref_result <= unsigned(signed(din_hi) * signed(din_lo));
else
ref_result <= unsigned(din_hi) * unsigned(din_lo);
end if;
wait until rising_edge(clk);
wait until rising_edge(clk);
wait until rising_edge(clk);
if ENABLE_FAIL_REPORT then
assert ref_result = md_result report "Error on multiplication" severity failure;
end if;
end if;
end process;
STIMULUS: process
begin
wait for 3*CLK_PERIOD;
wait until rising_edge(clk);
rst <= '0';
wait for 2*CLK_PERIOD;
mul_divn <= '0';
s_un <= '0';
for i in 0 to operands'length-1 loop
for j in 0 to operands'length-1 loop
check <= '0';
wait until rising_edge(clk) and busy = '0';
din_hi <= operands(i);
din_lo <= operands(j);
start <= '1';
wait until rising_edge(clk);
start <= '0';
hilo_sel <= '0';
-- Read result
wait until rising_edge(clk) and busy = '0';
wait until rising_edge(clk);
md_result(31 downto 0) <= dout;
wait until rising_edge(clk);
hilo_sel <= '1';
wait until rising_edge(clk);
md_result(63 downto 32) <= dout;
check <= '1';
wait until rising_edge(clk);
check <= '0';
wait for 8*CLK_PERIOD;
end loop;
end loop;
s_un <= '1';
for i in 0 to operands'length-1 loop
for j in 0 to operands'length-1 loop
check <= '0';
wait until rising_edge(clk) and busy = '0';
din_hi <= operands(i);
din_lo <= operands(j);
start <= '1';
wait until rising_edge(clk);
start <= '0';
hilo_sel <= '0';
-- Read result
wait until rising_edge(clk) and busy = '0';
wait until rising_edge(clk);
md_result(31 downto 0) <= dout;
wait until rising_edge(clk);
hilo_sel <= '1';
wait until rising_edge(clk);
md_result(63 downto 32) <= dout;
check <= '1';
wait until rising_edge(clk);
check <= '0';
wait for 8*CLK_PERIOD;
end loop;
end loop;
mul_divn <= '1';
s_un <= '0';
for i in 0 to operands'length-1 loop
for j in 0 to operands'length-1 loop
check <= '0';
wait until rising_edge(clk) and busy = '0';
din_hi <= operands(i);
din_lo <= operands(j);
start <= '1';
wait until rising_edge(clk);
start <= '0';
hilo_sel <= '0';
-- Read result
wait until rising_edge(clk) and busy = '0';
wait until rising_edge(clk);
md_result(31 downto 0) <= dout;
wait until rising_edge(clk);
hilo_sel <= '1';
wait until rising_edge(clk);
md_result(63 downto 32) <= dout;
check <= '1';
wait until rising_edge(clk);
check <= '0';
wait for 8*CLK_PERIOD;
end loop;
end loop;
s_un <= '1';
for i in 0 to operands'length-1 loop
for j in 0 to operands'length-1 loop
check <= '0';
wait until rising_edge(clk) and busy = '0';
din_hi <= operands(i);
din_lo <= operands(j);
start <= '1';
wait until rising_edge(clk);
start <= '0';
hilo_sel <= '0';
-- Read result
wait until rising_edge(clk) and busy = '0';
wait until rising_edge(clk);
md_result(31 downto 0) <= dout;
wait until rising_edge(clk);
hilo_sel <= '1';
wait until rising_edge(clk);
md_result(63 downto 32) <= dout;
check <= '1';
wait until rising_edge(clk);
check <= '0';
wait for 8*CLK_PERIOD;
end loop;
end loop;
wait;
end process;
END;
+405
View File
@@ -0,0 +1,405 @@
-------------------------------------------------------------------------
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
-- This file: Testbench for JCPU
-- also writes 'opc.lst' for JASM-assembler
--
-- Copyright (C) 2007 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------
LIBRARY ieee;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.numeric_std.ALL;
library work;
use work.mips_types.all;
use work.mips_instr.all;
use work.async_types.all;
use work.async_defs.all;
ENTITY tb_mips_top IS
END tb_mips_top;
ARCHITECTURE behavior OF tb_mips_top IS
constant CLK_PERIOD : time := 10 ns;
constant SRAM_ADDR_WIDTH : integer := 14; -- bits
constant FLASH_ADDR_WIDTH : integer := 14; -- bits
signal debug : unsigned(1 downto 0);
-- Master
signal rst : STD_LOGIC := '1';
signal clk : STD_LOGIC := '0';
signal ACK_I : STD_LOGIC := '0';
signal SRDY_I : STD_LOGIC := '0';
signal ADDR_O : word_t;
signal DAT_I : word_t := (others => '0');
signal DAT_O : word_t;
signal WE_O : STD_LOGIC;
signal SEL_O : unsigned(3 downto 0);
signal CYC_O : STD_LOGIC;
signal STB_O : STD_LOGIC;
signal MRDY_O : STD_LOGIC;
signal INT : unsigned (5 downto 0) := (others => '0');
-- Slaves
signal CYC_I_rom : std_logic;
signal ACK_O_rom : std_logic;
signal SRDY_O_rom : std_logic;
signal DAT_O_rom : unsigned(31 downto 0);
signal CYC_I_flash : std_logic;
signal ACK_O_flash : std_logic;
signal SRDY_O_flash : std_logic;
signal DAT_O_flash : unsigned(31 downto 0);
signal CYC_I_sram : std_logic;
signal ACK_O_sram : std_logic;
signal SRDY_O_sram : std_logic;
signal DAT_O_sram : unsigned(31 downto 0);
signal CYC_I_gpio : std_logic;
signal ACK_O_gpio : std_logic;
signal SRDY_O_gpio : std_logic;
signal DAT_O_gpio : unsigned(31 downto 0);
signal CYC_I_uart : std_logic;
signal ACK_O_uart : std_logic;
signal SRDY_O_uart : std_logic;
signal DAT_O_uart : unsigned(31 downto 0);
signal flash_cs_n : std_logic;
signal flash_oe_n : std_logic;
signal sram_cs_n : std_logic;
signal sram_wr_n : unsigned(3 downto 0);
signal sram_oe_n : std_logic;
signal sram_a : unsigned(SRAM_ADDR_WIDTH-1 downto 0);
signal sram_d : unsigned(31 downto 0);
signal flash_a : unsigned(FLASH_ADDR_WIDTH-1 downto 0);
signal flash_d : unsigned(31 downto 0);
signal gpo0 : unsigned(31 downto 0);
signal gpo1 : unsigned(31 downto 0);
signal gpi0 : unsigned(31 downto 0) := (others => '0');
signal gpi1 : unsigned(31 downto 0) := (others => '0');
signal int_uart_rx : std_logic;
signal rx : std_logic := '1';
signal tx : std_logic;
type mem_area_t is (mem_dead, mem_flash, mem_sram, mem_rom, mem_gpio, mem_uart);
signal mem_area : mem_area_t;
type word_array_t is array (natural range <>) of word_t;
signal sram_data : word_array_t(0 to 2**SRAM_ADDR_WIDTH-1);
signal flash_data : word_array_t(0 to 2**FLASH_ADDR_WIDTH-1);
BEGIN
------------------------------------------------------------------
CLK_GEN: process
begin
wait for CLK_PERIOD/2;
clk <= not clk;
end process;
------------------------------------------------------------------
-- Memory mux
------------------------------------------------------------------
mem_mux:
process(ADDR_O)
begin
mem_area <= mem_dead;
if ADDR_O(31 downto 28) = X"0" then
mem_area <= mem_flash;
elsif ADDR_O(31 downto 28) = X"A" then
if ADDR_O(27 downto 26) = "00" then
if ADDR_O(18 downto 16) = "000" then
mem_area <= mem_gpio;
elsif ADDR_O(18 downto 16) = "001" then
mem_area <= mem_uart;
end if;
elsif ADDR_O(27 downto 26) = "01" then
mem_area <= mem_flash;
end if;
elsif (ADDR_O(31 downto 28) = X"B" and ADDR_O(15) = '0') then
mem_area <= mem_rom;
elsif (ADDR_O(31 downto 28) = X"8" or ADDR_O(30) = '1') then
mem_area <= mem_sram;
end if;
end process;
signal_mux:
process(mem_area, CYC_O)
begin
CYC_I_uart <= '0';
CYC_I_gpio <= '0';
CYC_I_flash <= '0';
CYC_I_rom <= '0';
CYC_I_sram <= '0';
case mem_area is
when mem_gpio =>
CYC_I_gpio <= CYC_O;
when mem_uart =>
CYC_I_uart <= CYC_O;
when mem_flash =>
CYC_I_flash <= CYC_O;
when mem_rom =>
CYC_I_rom <= CYC_O;
when mem_sram =>
CYC_I_sram <= CYC_O;
when others => null;
end case;
end process;
SRDY_I <= SRDY_O_flash or SRDY_O_sram or SRDY_O_rom or SRDY_O_uart or SRDY_O_gpio;
ACK_I <= ACK_O_flash or ACK_O_sram or ACK_O_rom or ACK_O_uart or ACK_O_gpio;
DAT_I <= DAT_O_sram when CYC_I_sram = '1' else
DAT_O_rom when CYC_I_rom = '1' else
DAT_O_flash when CYC_I_flash = '1' else
DAT_O_uart when CYC_I_uart = '1' else
DAT_O_gpio when CYC_I_gpio = '1' else X"DEADBEEF";
------------------------------------------------------------------
uut: entity work.mips_top
PORT MAP
(
debug => debug,
RST_I => rst,
CLK_I => clk,
ACK_I => ACK_I,
SRDY_I => SRDY_I,
ADDR_O => ADDR_O,
DAT_I => DAT_I,
DAT_O => DAT_O,
WE_O => WE_O,
SEL_O => SEL_O,
CYC_O => CYC_O,
STB_O => STB_O,
MRDY_O => MRDY_O,
INT => INT
);
INT(1) <= int_uart_rx;
inst_rom : entity work.rom_wb
PORT MAP
(
CLK_I => clk,
RST_I => rst,
CYC_I => CYC_I_rom,
STB_I => STB_O,
ACK_O => ACK_O_rom,
MRDY_I => MRDY_O,
SRDY_O => SRDY_O_rom,
ADDR_I => ADDR_O,
DAT_O => DAT_O_rom
);
inst_gpio : entity work.gpio_wb
PORT MAP
(
CLK_I => clk,
RST_I => rst,
CYC_I => CYC_I_gpio,
STB_I => STB_O,
SEL_I => SEL_O,
WE_I => WE_O,
ACK_O => ACK_O_gpio,
SRDY_O => SRDY_O_gpio,
MRDY_I => MRDY_O,
ADDR_I => ADDR_O,
DAT_I => DAT_O,
DAT_O => DAT_O_gpio,
sys_gpo0 => gpo0,
sys_gpo1 => gpo1,
sys_gpi0 => gpi0,
sys_gpi1 => gpi1
);
inst_flash_port : entity work.async_port_wb
GENERIC MAP
(
addr_width => FLASH_ADDR_WIDTH,
data_width => 32,
byte_sel_width => 1,
async_timespec => ts_flash
)
PORT MAP
(
CLK_I => clk,
RST_I => rst,
CYC_I => CYC_I_flash,
STB_I => STB_O,
WE_I => WE_O,
ACK_O => ACK_O_flash,
SRDY_O => SRDY_O_flash,
MRDY_I => MRDY_O,
SEL_I => SEL_O,
ADDR_I => ADDR_O,
DAT_I => DAT_O,
DAT_O => DAT_O_flash,
async_a => flash_a,
async_d => flash_d,
async_cs => flash_cs_n,
async_wr => open,
async_rd => flash_oe_n,
async_rst => open
);
inst_sram_port : entity work.async_port_wb
GENERIC MAP
(
addr_width => SRAM_ADDR_WIDTH,
data_width => 32,
byte_sel_width => 4,
async_timespec => ts_sram
)
PORT MAP
(
CLK_I => clk,
RST_I => rst,
CYC_I => CYC_I_sram,
STB_I => STB_O,
WE_I => WE_O,
ACK_O => ACK_O_sram,
SRDY_O => SRDY_O_sram,
MRDY_I => MRDY_O,
SEL_I => SEL_O,
ADDR_I => ADDR_O,
DAT_I => DAT_O,
DAT_O => DAT_O_sram,
async_a => sram_a,
async_d => sram_d,
async_cs => sram_cs_n,
async_wr => sram_wr_n,
async_rd => sram_oe_n,
async_rst => open
);
inst_uart : entity work.uart_wb
PORT MAP
(
CLK_I => clk,
RST_I => rst,
CYC_I => CYC_I_uart,
STB_I => STB_O,
SEL_I => SEL_O,
WE_I => WE_O,
ACK_O => ACK_O_uart,
SRDY_O => SRDY_O_uart,
MRDY_I => MRDY_O,
ADDR_I => ADDR_O,
DAT_I => DAT_O,
DAT_O => DAT_O_uart,
INT_RX_O => int_uart_rx,
INT_TX_O => open,
ser_rx => rx,
ser_tx => tx
);
------------------------------------------------------------------
SRAM_READ:
process(sram_a, sram_cs_n, sram_oe_n)
begin
sram_d <= (others => 'Z');
if sram_oe_n = '0' then
if sram_cs_n = '0' then
sram_d <= sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)));
end if;
end if;
end process;
SRAM_WRITE:
process(sram_a, sram_cs_n, sram_wr_n)
begin
if rising_edge(sram_wr_n(0)) then
if sram_cs_n = '0' then
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(7 downto 0) <= sram_d(7 downto 0);
end if;
end if;
if rising_edge(sram_wr_n(1)) then
if sram_cs_n = '0' then
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(15 downto 8) <= sram_d(15 downto 8);
end if;
end if;
if rising_edge(sram_wr_n(2)) then
if sram_cs_n = '0' then
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(23 downto 16) <= sram_d(23 downto 16);
end if;
end if;
if rising_edge(sram_wr_n(3)) then
if sram_cs_n = '0' then
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(31 downto 24) <= sram_d(31 downto 24);
end if;
end if;
end process;
------------------------------------------------------------------
FLASH_READ:
process(rst, flash_cs_n, flash_oe_n, flash_a)
type file_t is file of integer;
file load_flash : file_t open read_mode is "hello.flash.bin";
variable instr : integer;
variable index : natural;
variable temp : signed(31 downto 0);
begin
if rst = '1' then
index := 0;
while not endfile(load_flash) loop
read(load_flash, instr);
temp := to_signed(instr, word_t'length);
flash_data(index) <= unsigned(temp);
index := index + 1;
end loop;
else
flash_d <= (others => 'Z') after 10 ns;
if flash_oe_n = '0' and flash_cs_n = '0' then
index := to_integer(flash_a(FLASH_ADDR_WIDTH-1 downto 2));
flash_d <= flash_data(index) after 10 ns;
end if;
end if;
end process;
------------------------------------------------------------------
STIMULUS: process
begin
wait for 3*CLK_PERIOD;
wait until rising_edge(clk);
rst <= '0';
wait;
end process;
END;
+20
View File
@@ -0,0 +1,20 @@
vhdl work "../../src/core/mips_types.vhd"
vhdl work "../../../../misc/dpram_2w2r.vhd"
vhdl work "../../../../misc/dpram_1w1r_dist.vhd"
vhdl work "../../../../misc/dpram_1w1r.vhd"
vhdl work "../../../../FIFO/src/sync_fifo_ctrl.vhd"
vhdl work "../../../../FIFO/src/fifo_ctrl_pkg.vhd"
vhdl work "../../src/core/mips_instr.vhd"
vhdl work "../../../../FIFO/src/fifo_sync_dist.vhd"
vhdl work "../../src/core/mips_shifter.vhd"
vhdl work "../../src/core/mips_reg.vhd"
vhdl work "../../src/core/mips_muldiv.vhd"
vhdl work "../../src/core/mips_idecode_rom.vhd"
vhdl work "../../src/core/mips_icache.vhd"
vhdl work "../../src/core/mips_dcache.vhd"
vhdl work "../../src/core/mips_cop.vhd"
vhdl work "../../src/core/mips_bcu.vhd"
vhdl work "../../src/core/mips_alu.vhd"
vhdl work "../../src/core/mips_pipeline.vhd"
vhdl work "../../src/core/mips_biu.vhd"
vhdl work "../../src/core/mips_top.vhd"
@@ -0,0 +1,20 @@
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_types.vhd"
vhdl work "W:\vhdl\lib\misc\dpram_2w2r.vhd"
vhdl work "W:\vhdl\lib\misc\dpram_1w1r_dist.vhd"
vhdl work "W:\vhdl\lib\misc\dpram_1w1r.vhd"
vhdl work "W:\vhdl\lib\FIFO\src\sync_fifo_ctrl.vhd"
vhdl work "W:\vhdl\lib\FIFO\src\fifo_ctrl_pkg.vhd"
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_instr.vhd"
vhdl work "W:\vhdl\lib\FIFO\src\fifo_sync_dist.vhd"
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_shifter.vhd"
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_reg.vhd"
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_muldiv.vhd"
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_idecode_rom.vhd"
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_icache.vhd"
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_dcache.vhd"
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_cop.vhd"
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_bcu.vhd"
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_alu.vhd"
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_pipeline.vhd"
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_biu.vhd"
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_top.vhd"
+5
View File
@@ -0,0 +1,5 @@
2008-10-26
- Optimierung: MUL32x32 primitive für Virtex-4
- External COP 1..3 interface
- FPU (COP1)
- MMU
+17
View File
@@ -0,0 +1,17 @@
CFLAGS=-O2
CC=gcc
all: romgen ramgen flashgen
romgen: ./src/romgen.c
$(CC) $(CFLAGS) ./src/romgen.c -o ./romgen
ramgen: ./src/ramgen.c
$(CC) $(CFLAGS) ./src/ramgen.c -o ./ramgen
flashgen: ./src/flashgen.c
$(CC) $(CFLAGS) ./src/flashgen.c -o ./flashgen
clean:
rm -rf romgen* ramgen* flashgen*
+117
View File
@@ -0,0 +1,117 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define INT8 char
#define INT16 short
#define INT32 long
#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned long
#define INT int
#define UINT unsigned int
#define FLOAT32 float
#define FLOAT64 double
#define SDRAM_BASE 0x40000000
#define FLASH_OFFSET 0x00000000
// --------------------------------------------------------------
typedef struct _sflash_img_hdr_t
{
UINT8 magic[4];
UINT32 target_addr;
UINT32 img_offset;
UINT32 img_size;
UINT32 hdr_next;
UINT8 img_name[128];
UINT8 res[108];
} flash_img_hdr_t;
// --------------------------------------------------------------
void basename(char *pSrc, char *pDst)
{
int i, size;
size = strlen(pSrc);
while(pSrc[size] != '.')
size--;
for (i=0; i < size; i++)
pDst[i] = pSrc[i];
pDst[i] = 0;
}
// --------------------------------------------------------------
int main(int argc, char *argv[])
{
char *pFilenameIn;
char name_flash[1024];
char name_prj[1024];
char *pBuf;
flash_img_hdr_t img_hdr = {0};
FILE *pFile;
int filesize;
long start, end;
int i;
if (argc < 2)
{
fprintf(stderr, "Usage: flashgen <input file>\n");
return 1;
}
pFilenameIn = argv[1];
pFile = fopen(pFilenameIn, "rb");
if (!pFile)
{
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
return 1;
}
basename(pFilenameIn, name_prj);
sprintf(name_flash, "%s.flash.bin", name_prj);
// determine filesize
fseek(pFile, 0, SEEK_SET);
start = ftell(pFile);
fseek(pFile, 0, SEEK_END);
end = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
filesize = (end-start);
pBuf = (char*)malloc(filesize);
fread(pBuf, 1, filesize, pFile);
fclose(pFile);
pFile = fopen(name_flash, "wb");
if (!pFile)
{
fprintf(stderr, "Error opening file %s\n", name_flash);
return 1;
}
img_hdr.magic[0] = 'J';
img_hdr.magic[1] = 'F';
img_hdr.magic[2] = 'I';
img_hdr.magic[3] = '1';
img_hdr.target_addr = SDRAM_BASE;
img_hdr.img_size = filesize;
img_hdr.img_offset = FLASH_OFFSET + sizeof(flash_img_hdr_t);
img_hdr.hdr_next = FLASH_OFFSET;
fwrite(&img_hdr, sizeof(flash_img_hdr_t), 1, pFile);
fwrite(pBuf, 1, filesize, pFile);
fclose(pFile);
return 0;
}
+385
View File
@@ -0,0 +1,385 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define ARCH_NAME "data"
#define ENT_NAME "ram"
#define JTAG_ADDR_WIDTH 16
// --------------------------------------------------------------
void basename(char *pSrc, char *pDst)
{
int i, size;
size = strlen(pSrc);
while(pSrc[size] != '.')
size--;
for (i=0; i < size; i++)
pDst[i] = pSrc[i];
pDst[i] = 0;
}
int SaveRAM(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
{
FILE *pFileIn, *pFileOut;
long start, end;
int i, word, filesize, romsize;
pFileIn = fopen(pFilenameIn, "rb");
if (!pFileIn)
{
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
return 1;
}
pFileOut = fopen(pFilenameOut, "wb");
if (!pFileOut)
{
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
return 1;
}
fseek(pFileIn, 0, SEEK_SET);
start = ftell(pFileIn);
fseek(pFileIn, 0, SEEK_END);
end = ftell(pFileIn);
fseek(pFileIn, 0, SEEK_SET);
filesize = (end-start);
romsize = (int)pow(2, nbits_addr+2);
// -------------------------------------------------------------------------
// Header
// -------------------------------------------------------------------------
fprintf(pFileOut, "LIBRARY IEEE;\n");
fprintf(pFileOut, "USE IEEE.STD_LOGIC_1164.ALL;\n");
fprintf(pFileOut, "USE IEEE.NUMERIC_STD.ALL;\n");
fprintf(pFileOut, "\n");
fprintf(pFileOut, "ENTITY %s IS\n", ENT_NAME);
fprintf(pFileOut, "\tPort\n");
fprintf(pFileOut, "\t(\n");
fprintf(pFileOut, "\t\tclk\t\t: in STD_LOGIC;\n");
fprintf(pFileOut, "\t\tce\t\t: in STD_LOGIC;\n");
fprintf(pFileOut, "\t\twe\t\t: in unsigned(%d downto 0);\n", nbits_data/8-1);
fprintf(pFileOut, "\t\taddr\t\t: in unsigned(%d downto 0);\n", nbits_data-1);
fprintf(pFileOut, "\t\tdin\t\t: in unsigned(%d downto 0);\n", nbits_data-1);
fprintf(pFileOut, "\t\tdout\t\t: out unsigned(%d downto 0)\n", nbits_data-1);
fprintf(pFileOut, "\t);\n");
fprintf(pFileOut, "END %s;\n", ENT_NAME);
fprintf(pFileOut, "\n");
fprintf(pFileOut, "ARCHITECTURE %s OF %s IS\n", ARCH_NAME, ENT_NAME);
fprintf(pFileOut, "\n");
fprintf(pFileOut, "\tconstant depth : natural := %d;\n", romsize/4);
fprintf(pFileOut, "\tsubtype word_t is unsigned(%d downto 0);\n", nbits_data-1);
fprintf(pFileOut, "\ttype word_array_t is array (0 to %d) of word_t;\n", romsize/4-1);
fprintf(pFileOut, "\tsignal sram : word_array_t :=\n");
fprintf(pFileOut, "\t(\n");
fprintf(pFileOut, "\n");
// -------------------------------------------------------------------------
// ROM part
// -------------------------------------------------------------------------
for (i=0; i < filesize; i += sizeof(int))
{
fread(&word, 1, sizeof(int), pFileIn);
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
if (i < (romsize-sizeof(int)))
fprintf(pFileOut, ", -- %8.8X\n", i);
else
fprintf(pFileOut, " -- %8.8X\n", i);
}
word = 0;
for (; i < romsize; i += sizeof(int))
{
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
if (i < (romsize-sizeof(int)))
fprintf(pFileOut, ", -- %8.8X\n", i);
else
fprintf(pFileOut, " -- %8.8X\n", i);
}
fprintf(pFileOut, "\t);\n");
fprintf(pFileOut, "\n");
// -------------------------------------------------------------------------
// Trailer
// -------------------------------------------------------------------------
fprintf(pFileOut, "begin\n", ARCH_NAME);
fprintf(pFileOut, "\n");
fprintf(pFileOut, "RAM_RW:\n", ARCH_NAME);
fprintf(pFileOut, "\tprocess(clk)\n");
fprintf(pFileOut, "\tvariable index : natural range 0 to depth-1;\n");
fprintf(pFileOut, "\tbegin\n");
fprintf(pFileOut, "\t\tif rising_edge(clk) and ce = '1' then\n");
fprintf(pFileOut, "\t\t\tindex := to_integer(addr(%d downto 2));\n", nbits_addr+1);
fprintf(pFileOut, "\t\t\tif we(0) = '1' then\n");
fprintf(pFileOut, "\t\t\t\tsram(index)(7 downto 0)\t\t<= din(7 downto 0);\n");
fprintf(pFileOut, "\t\t\tend if;\n");
fprintf(pFileOut, "\t\t\tif we(1) = '1' then\n");
fprintf(pFileOut, "\t\t\t\tsram(index)(15 downto 8)\t<= din(15 downto 8);\n");
fprintf(pFileOut, "\t\t\tend if;\n");
fprintf(pFileOut, "\t\t\tif we(2) = '1' then\n");
fprintf(pFileOut, "\t\t\t\tsram(index)(23 downto 16)\t<= din(23 downto 16);\n");
fprintf(pFileOut, "\t\t\tend if;\n");
fprintf(pFileOut, "\t\t\tif we(3) = '1' then\n");
fprintf(pFileOut, "\t\t\t\tsram(index)(31 downto 24)\t\t<= din(31 downto 24);\n");
fprintf(pFileOut, "\t\t\tend if;\n");
fprintf(pFileOut, "\t\t\tdout <= sram(index);\n");
fprintf(pFileOut, "\t\tend if;\n");
fprintf(pFileOut, "\tend process;\n");
fprintf(pFileOut, "\n");
fprintf(pFileOut, "end %s;\n", ARCH_NAME);
return 0;
}
int SaveRAM_V4LD(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
{
FILE *pFileIn, *pFileOut;
long start, end;
int i, word, filesize, romsize;
char tpl[] = {"--------------------------------------------------------------------------\n-- Virtex-4: JTAG Loader\n--------------------------------------------------------------------------\n\ti00_BUFG : BUFG\n\tport map\n\t(\n\t\tO => bs_clk1,\n I => bs_clk0\n\t);\n\t\n\ti01_BUFG : BUFG\n\tport map\n\t(\n\t\tO => bs_update1,\n I => bs_update0\n\t);\n\n\tBSCAN_VIRTEX4_inst1 : BSCAN_VIRTEX4 \n\tgeneric map\n\t(\n\t\tJTAG_CHAIN => 1 -- Value to set BSCAN site of device. Possible values: (1,2,3 or 4)\n\t)\n\tport map \n\t(\n\t\tCAPTURE => bs_capture, -- CAPTURE output from TAP controller\n\t\tDRCK => bs_clk0, -- Data register output for USER functions\n\t\tRESET => bs_rst, -- Reset output from TAP controller\n\t\tSEL => bs_sel, -- USER active output\n\t\tSHIFT => bs_shift, -- SHIFT output from TAP controller\n\t\tTDI => bs_tdi, -- TDI output from TAP controller\n\t\tUPDATE => bs_update0, -- UPDATE output from TAP controller\n\t\tTDO => bs_tdo -- Data input for USER function\n\t);\n\n\tjtag_ld_addr <= user_regi(user_regi'left downto jtag_ld_dout'length);\n\tjtag_ld_din <= user_regi(jtag_ld_dout'length-1 downto 0);\n\tjtag_ld_clk <= bs_update1;\n\tjtag_ld_we <= bs_sel;\n\t\nsipo:\n\tprocess (bs_rst, bs_clk1, bs_tdi, bs_shift)\n\tbegin\n\t\tif bs_rst = '1' then\n\t\t\tuser_regi <= (others => '0');\n\t\telsif rising_edge(bs_clk1) then\n\t\t\tif bs_shift = '1' then\n\t\t\t\tuser_regi <= bs_tdi & user_regi(user_regi'left downto 1);\n\t\t\tend if;\n\t\tend if;\n\tend process;\t\n\npiso:\n\tprocess (bs_rst, bs_clk1, bs_shift, user_rego)\n\tbegin\n\t\tbs_tdo <= user_rego(0);\n\t\tif bs_rst = '1' then\n\t\t\tuser_rego <= (others => '0');\n\t\telsif rising_edge(bs_clk1) then\n\t\t\tif bs_shift = '1' then\n\t\t\t\tuser_rego <= user_rego(0) & user_rego(user_rego'left downto 1);\n\t\t\telse\n\t\t\t\tuser_rego <= (user_rego'left downto jtag_ld_dout'length => '0') & jtag_ld_dout;\t\n\t\n\t\t\tend if;\n\t\tend if;\n\tend process;\n\n"};
pFileIn = fopen(pFilenameIn, "rb");
if (!pFileIn)
{
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
return 1;
}
pFileOut = fopen(pFilenameOut, "wb");
if (!pFileOut)
{
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
return 1;
}
fseek(pFileIn, 0, SEEK_SET);
start = ftell(pFileIn);
fseek(pFileIn, 0, SEEK_END);
end = ftell(pFileIn);
fseek(pFileIn, 0, SEEK_SET);
filesize = (end-start);
romsize = (int)pow(2, nbits_addr+2);
// -------------------------------------------------------------------------
// Header
// -------------------------------------------------------------------------
fprintf(pFileOut, "LIBRARY IEEE;\n");
fprintf(pFileOut, "USE IEEE.STD_LOGIC_1164.ALL;\n");
fprintf(pFileOut, "USE IEEE.NUMERIC_STD.ALL;\n");
fprintf(pFileOut, "\n");
fprintf(pFileOut, "library UNISIM;\n");
fprintf(pFileOut, "use UNISIM.VComponents.all;\n");
fprintf(pFileOut, "\n");
fprintf(pFileOut, "ENTITY %s IS\n", ENT_NAME);
fprintf(pFileOut, "\tPort\n");
fprintf(pFileOut, "\t(\n");
fprintf(pFileOut, "\t\tclk\t\t: in STD_LOGIC;\n");
fprintf(pFileOut, "\t\tce\t\t: in STD_LOGIC;\n");
fprintf(pFileOut, "\t\taddr\t\t: in unsigned(%d downto 0);\n", nbits_data-1);
fprintf(pFileOut, "\t\tdout\t\t: out unsigned(%d downto 0)\n", nbits_data-1);
fprintf(pFileOut, "\t);\n");
fprintf(pFileOut, "END %s;\n", ENT_NAME);
fprintf(pFileOut, "\n");
fprintf(pFileOut, "ARCHITECTURE %s OF %s IS\n", ARCH_NAME, ENT_NAME);
fprintf(pFileOut, "\n");
fprintf(pFileOut, "\tsubtype word_t is unsigned(%d downto 0);\n", nbits_data-1);
fprintf(pFileOut, "\ttype word_array_t is array (0 to %d) of word_t;\n", romsize/4-1);
fprintf(pFileOut, "\tsignal jtag_ld_clk\t\t: STD_LOGIC;\n");
fprintf(pFileOut, "\tsignal jtag_ld_we\t\t: STD_LOGIC;\n");
fprintf(pFileOut, "\tsignal jtag_ld_addr\t\t: unsigned (%d downto 0);\n", JTAG_ADDR_WIDTH-1);
fprintf(pFileOut, "\tsignal jtag_ld_dout\t\t: unsigned (%d downto 0);\n", nbits_data-1);
fprintf(pFileOut, "\tsignal jtag_ld_din\t\t: unsigned (%d downto 0);\n", nbits_data-1);
fprintf(pFileOut, "\tsignal bs_rst, bs_sel, bs_shift, bs_tdi, bs_tdo : std_logic;\n");
fprintf(pFileOut, "\tsignal bs_capture, bs_clk0, bs_clk1, bs_update0, bs_update1 : std_logic;\n");
fprintf(pFileOut, "\tsignal user_regi, user_rego : unsigned (%d downto 0);\n", 31 + JTAG_ADDR_WIDTH);
fprintf(pFileOut, "\n");
fprintf(pFileOut, "\tsignal word_array : word_array_t :=\n");
fprintf(pFileOut, "\t(\n");
fprintf(pFileOut, "\n");
// -------------------------------------------------------------------------
// ROM part
// -------------------------------------------------------------------------
for (i=0; i < filesize; i += sizeof(int))
{
fread(&word, 1, sizeof(int), pFileIn);
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
if (i < (romsize-sizeof(int)))
fprintf(pFileOut, ", -- %8.8X\n", i);
else
fprintf(pFileOut, " -- %8.8X\n", i);
}
word = 0;
for (; i < romsize; i += sizeof(int))
{
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
if (i < (romsize-sizeof(int)))
fprintf(pFileOut, ", -- %8.8X\n", i);
else
fprintf(pFileOut, " -- %8.8X\n", i);
}
fprintf(pFileOut, "\t);\n");
fprintf(pFileOut, "\n");
fprintf(pFileOut, "begin\n", ARCH_NAME);
fprintf(pFileOut, "\n");
fprintf(pFileOut, "PROM_READ:\n", ARCH_NAME);
fprintf(pFileOut, "\tprocess(clk)\n");
fprintf(pFileOut, "\tbegin\n");
fprintf(pFileOut, "\t\tif rising_edge(clk) and ce = '1' then\n");
fprintf(pFileOut, "\t\t\tdout <= word_array(to_integer(addr(%d downto 2)));\n", nbits_addr+1);
fprintf(pFileOut, "\t\tend if;\n");
fprintf(pFileOut, "\tend process;\n");
fprintf(pFileOut, "\n");
// -------------------------------------------------------------------------
// Trailer
// -------------------------------------------------------------------------
fprintf(pFileOut, "\n");
fputs(tpl, pFileOut);
fprintf(pFileOut, "PROM_WRITE:\n", ARCH_NAME);
fprintf(pFileOut, "\tprocess(jtag_ld_clk, jtag_ld_we)\n");
fprintf(pFileOut, "\tbegin\n");
fprintf(pFileOut, "\t\tif rising_edge(jtag_ld_clk) then\n");
fprintf(pFileOut, "\t\t\tif jtag_ld_we = '1' then\n");
fprintf(pFileOut, "\t\t\t\tword_array(to_integer(jtag_ld_addr(%d downto 0))) <= jtag_ld_din;\n", nbits_addr-1);
fprintf(pFileOut, "\t\t\telse\n");
fprintf(pFileOut, "\t\t\t\tjtag_ld_dout <= word_array(to_integer(jtag_ld_addr(%d downto 0)));\n", nbits_addr-1);
fprintf(pFileOut, "\t\t\tend if;\n");
fprintf(pFileOut, "\t\tend if;\n");
fprintf(pFileOut, "\tend process;\n");
fprintf(pFileOut, "\n");
fprintf(pFileOut, "end %s;\n", ARCH_NAME);
return 0;
}
int SaveRAM_TCL(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
{
FILE *pFileIn, *pFileOut;
long start, end;
int i, word, word_addr, filesize, romsize;
char binstr_addr[33];
char binstr_data[33];
char tpl[] = {"# ---------------------------------------------------------------------\n# For Chipscope 9.1\n# ---------------------------------------------------------------------\n# Source JTAG/TCL frame work\ncd $env(CHIPSCOPE)\\\\bin\\\\nt\nsource csejtag.tcl\n\nnamespace import ::chipscope::*\n\n# Platform USB Cable\nset PLATFORM_USB_CABLE_ARGS [list \"port=USB2\" \"frequency=6000000\"]\n# frequency=\"24000000 | 12000000 | 6000000 | 3000000 | 1500000 | 750000\"\n\n# Create session\nset handle [::chipscope::csejtag_session create 0]\n\n# Open JTAG and lock\nset open_result [::chipscope::csejtag_target open $handle $CSEJTAG_TARGET_PLATFORMUSB 0 $PLATFORM_USB_CABLE_ARGS]\nset lock_result [::chipscope::csejtag_target lock $handle 1000]\n\nset devlist [::chipscope::csejtag_tap autodetect_chain $handle $CSEJTAG_SCAN_DEFAULT]\n\n# Get Device ID\nset devtype \"Virtex-4SX\"\nset devid 2\nset irlength [::chipscope::csejtag_tap get_irlength $handle $devid]\nset idcode [::chipscope::csejtag_tap get_device_idcode $handle $devid]\n\nset CSE_OP $CSEJTAG_SHIFT_READWRITE\nset CSE_ES $CSEJTAG_RUN_TEST_IDLE\n\n# Write Program\n"};
pFileIn = fopen(pFilenameIn, "rb");
if (!pFileIn)
{
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
return 1;
}
pFileOut = fopen(pFilenameOut, "wb");
if (!pFileOut)
{
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
return 1;
}
fseek(pFileIn, 0, SEEK_SET);
start = ftell(pFileIn);
fseek(pFileIn, 0, SEEK_END);
end = ftell(pFileIn);
fseek(pFileIn, 0, SEEK_SET);
filesize = (end-start);
romsize = (int)pow(2, nbits_addr+2);
// -------------------------------------------------------------------------
// Header
// -------------------------------------------------------------------------
fputs(tpl, pFileOut);
// -------------------------------------------------------------------------
// ROM part
// -------------------------------------------------------------------------
fprintf(pFileOut, "# Assembled from %s\n", pFilenameIn);
fprintf(pFileOut, "# ---------------------------------------------------------------\n");
fprintf(pFileOut, "# Shift the USER2 Instruction (b1111000011) into the Instruction Register of FPGA\n");
fprintf(pFileOut, "# User 2\n");
fprintf(pFileOut, "set result [::chipscope::csejtag_tap shift_device_ir $handle $devid $CSE_OP $CSE_ES 0 $irlength \"3C3\"]\n\n");
word_addr = 0;
for (i=0; i < filesize; i += sizeof(int))
{
fread(&word, 1, sizeof(int), pFileIn);
fprintf(pFileOut, "::chipscope::csejtag_tap shift_device_dr $handle $devid $CSE_OP $CSE_ES 0 %d \"%4.4X%8.8X\"\n", nbits_data + JTAG_ADDR_WIDTH, word_addr, word);
word_addr++;
}
fprintf(pFileOut, "\n");
// -------------------------------------------------------------------------
// Trailer
// -------------------------------------------------------------------------
fprintf(pFileOut, "::chipscope::csejtag_target unlock $handle\n");
fprintf(pFileOut, "::chipscope::csejtag_target close $handle\n");
fprintf(pFileOut, "::chipscope::csejtag_session destroy $handle\n");
fprintf(pFileOut, "exit\n");
return 0;
}
int main(int argc, char *argv[])
{
char *pFilenameIn;
char name_prj[1024];
char name_rom_tcl[1024];
char name_rom[1024];
char name_rom_v4ld[1024];
FILE *pFileIn;
int filesize, romsize, nbits_addr, nbits_data;
long start, end;
int word, i;
if (argc < 2)
{
fprintf(stderr, "Usage: ramgen <input file> <num. word address bits>\n");
return 1;
}
pFilenameIn = argv[1];
if (argc == 3)
nbits_addr = atoi(argv[2]);
basename(pFilenameIn, name_prj);
sprintf(name_rom, "%s.vhd", name_prj);
sprintf(name_rom_v4ld, "%s_ld.vhd", name_prj);
sprintf(name_rom_tcl, "%s.tcl", name_prj);
SaveRAM(pFilenameIn, name_rom, ARCH_NAME, ENT_NAME, nbits_addr, 32);
// SaveROM_V4LD(pFilenameIn, name_rom_v4ld, ARCH_NAME, ENT_NAME, nbits_addr, 32);
SaveRAM_TCL(pFilenameIn, name_rom_tcl, ARCH_NAME, ENT_NAME, nbits_addr, 32);
return 0;
}
+368
View File
@@ -0,0 +1,368 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define ARCH_NAME "data"
#define ENT_NAME "rom"
#define JTAG_ADDR_WIDTH 16
// --------------------------------------------------------------
void basename(char *pSrc, char *pDst)
{
int i, size;
size = strlen(pSrc);
while(pSrc[size] != '.')
size--;
for (i=0; i < size; i++)
pDst[i] = pSrc[i];
pDst[i] = 0;
}
int SaveROM(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
{
FILE *pFileIn, *pFileOut;
long start, end;
int i, word, filesize, romsize;
pFileIn = fopen(pFilenameIn, "rb");
if (!pFileIn)
{
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
return 1;
}
pFileOut = fopen(pFilenameOut, "wb");
if (!pFileOut)
{
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
return 1;
}
fseek(pFileIn, 0, SEEK_SET);
start = ftell(pFileIn);
fseek(pFileIn, 0, SEEK_END);
end = ftell(pFileIn);
fseek(pFileIn, 0, SEEK_SET);
filesize = (end-start);
romsize = (int)pow(2, nbits_addr+2);
// -------------------------------------------------------------------------
// Header
// -------------------------------------------------------------------------
fprintf(pFileOut, "LIBRARY IEEE;\n");
fprintf(pFileOut, "USE IEEE.STD_LOGIC_1164.ALL;\n");
fprintf(pFileOut, "USE IEEE.NUMERIC_STD.ALL;\n");
fprintf(pFileOut, "\n");
fprintf(pFileOut, "ENTITY %s IS\n", ENT_NAME);
fprintf(pFileOut, "\tPort\n");
fprintf(pFileOut, "\t(\n");
fprintf(pFileOut, "\t\tclk\t\t: in STD_LOGIC;\n");
fprintf(pFileOut, "\t\tce\t\t: in STD_LOGIC;\n");
fprintf(pFileOut, "\t\taddr\t\t: in unsigned(%d downto 0);\n", nbits_data-1);
fprintf(pFileOut, "\t\tdout\t\t: out unsigned(%d downto 0)\n", nbits_data-1);
fprintf(pFileOut, "\t);\n");
fprintf(pFileOut, "END %s;\n", ENT_NAME);
fprintf(pFileOut, "\n");
fprintf(pFileOut, "ARCHITECTURE %s OF %s IS\n", ARCH_NAME, ENT_NAME);
fprintf(pFileOut, "\n");
fprintf(pFileOut, "\tsubtype word_t is unsigned(%d downto 0);\n", nbits_data-1);
fprintf(pFileOut, "\ttype word_array_t is array (0 to %d) of word_t;\n", romsize/4-1);
fprintf(pFileOut, "\tconstant word_array : word_array_t :=\n");
fprintf(pFileOut, "\t(\n");
fprintf(pFileOut, "\n");
// -------------------------------------------------------------------------
// ROM part
// -------------------------------------------------------------------------
for (i=0; i < filesize; i += sizeof(int))
{
fread(&word, 1, sizeof(int), pFileIn);
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
if (i < (romsize-sizeof(int)))
fprintf(pFileOut, ", -- %8.8X\n", i);
else
fprintf(pFileOut, " -- %8.8X\n", i);
}
word = 0;
for (; i < romsize; i += sizeof(int))
{
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
if (i < (romsize-sizeof(int)))
fprintf(pFileOut, ", -- %8.8X\n", i);
else
fprintf(pFileOut, " -- %8.8X\n", i);
}
fprintf(pFileOut, "\t);\n");
fprintf(pFileOut, "\n");
// -------------------------------------------------------------------------
// Trailer
// -------------------------------------------------------------------------
fprintf(pFileOut, "begin\n", ARCH_NAME);
fprintf(pFileOut, "\n");
fprintf(pFileOut, "PROM_READ:\n", ARCH_NAME);
fprintf(pFileOut, "\tprocess(clk)\n");
fprintf(pFileOut, "\tbegin\n");
fprintf(pFileOut, "\t\tif rising_edge(clk) and ce = '1' then\n");
fprintf(pFileOut, "\t\t\tdout <= word_array(to_integer(addr(%d downto 2)));\n", nbits_addr+1);
fprintf(pFileOut, "\t\tend if;\n");
fprintf(pFileOut, "\tend process;\n");
fprintf(pFileOut, "\n");
fprintf(pFileOut, "end %s;\n", ARCH_NAME);
return 0;
}
int SaveROM_V4LD(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
{
FILE *pFileIn, *pFileOut;
long start, end;
int i, word, filesize, romsize;
char tpl[] = {"--------------------------------------------------------------------------\n-- Virtex-4: JTAG Loader\n--------------------------------------------------------------------------\n\ti00_BUFG : BUFG\n\tport map\n\t(\n\t\tO => bs_clk1,\n I => bs_clk0\n\t);\n\t\n\ti01_BUFG : BUFG\n\tport map\n\t(\n\t\tO => bs_update1,\n I => bs_update0\n\t);\n\n\tBSCAN_VIRTEX4_inst1 : BSCAN_VIRTEX4 \n\tgeneric map\n\t(\n\t\tJTAG_CHAIN => 1 -- Value to set BSCAN site of device. Possible values: (1,2,3 or 4)\n\t)\n\tport map \n\t(\n\t\tCAPTURE => bs_capture, -- CAPTURE output from TAP controller\n\t\tDRCK => bs_clk0, -- Data register output for USER functions\n\t\tRESET => bs_rst, -- Reset output from TAP controller\n\t\tSEL => bs_sel, -- USER active output\n\t\tSHIFT => bs_shift, -- SHIFT output from TAP controller\n\t\tTDI => bs_tdi, -- TDI output from TAP controller\n\t\tUPDATE => bs_update0, -- UPDATE output from TAP controller\n\t\tTDO => bs_tdo -- Data input for USER function\n\t);\n\n\tjtag_ld_addr <= user_regi(user_regi'left downto jtag_ld_dout'length);\n\tjtag_ld_din <= user_regi(jtag_ld_dout'length-1 downto 0);\n\tjtag_ld_clk <= bs_update1;\n\tjtag_ld_we <= bs_sel;\n\t\nsipo:\n\tprocess (bs_rst, bs_clk1, bs_tdi, bs_shift)\n\tbegin\n\t\tif bs_rst = '1' then\n\t\t\tuser_regi <= (others => '0');\n\t\telsif rising_edge(bs_clk1) then\n\t\t\tif bs_shift = '1' then\n\t\t\t\tuser_regi <= bs_tdi & user_regi(user_regi'left downto 1);\n\t\t\tend if;\n\t\tend if;\n\tend process;\t\n\npiso:\n\tprocess (bs_rst, bs_clk1, bs_shift, user_rego)\n\tbegin\n\t\tbs_tdo <= user_rego(0);\n\t\tif bs_rst = '1' then\n\t\t\tuser_rego <= (others => '0');\n\t\telsif rising_edge(bs_clk1) then\n\t\t\tif bs_shift = '1' then\n\t\t\t\tuser_rego <= user_rego(0) & user_rego(user_rego'left downto 1);\n\t\t\telse\n\t\t\t\tuser_rego <= (user_rego'left downto jtag_ld_dout'length => '0') & jtag_ld_dout;\t\n\t\n\t\t\tend if;\n\t\tend if;\n\tend process;\n\n"};
pFileIn = fopen(pFilenameIn, "rb");
if (!pFileIn)
{
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
return 1;
}
pFileOut = fopen(pFilenameOut, "wb");
if (!pFileOut)
{
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
return 1;
}
fseek(pFileIn, 0, SEEK_SET);
start = ftell(pFileIn);
fseek(pFileIn, 0, SEEK_END);
end = ftell(pFileIn);
fseek(pFileIn, 0, SEEK_SET);
filesize = (end-start);
romsize = (int)pow(2, nbits_addr+2);
// -------------------------------------------------------------------------
// Header
// -------------------------------------------------------------------------
fprintf(pFileOut, "LIBRARY IEEE;\n");
fprintf(pFileOut, "USE IEEE.STD_LOGIC_1164.ALL;\n");
fprintf(pFileOut, "USE IEEE.NUMERIC_STD.ALL;\n");
fprintf(pFileOut, "\n");
fprintf(pFileOut, "library UNISIM;\n");
fprintf(pFileOut, "use UNISIM.VComponents.all;\n");
fprintf(pFileOut, "\n");
fprintf(pFileOut, "ENTITY %s IS\n", ENT_NAME);
fprintf(pFileOut, "\tPort\n");
fprintf(pFileOut, "\t(\n");
fprintf(pFileOut, "\t\tclk\t\t: in STD_LOGIC;\n");
fprintf(pFileOut, "\t\tce\t\t: in STD_LOGIC;\n");
fprintf(pFileOut, "\t\taddr\t\t: in unsigned(%d downto 0);\n", nbits_data-1);
fprintf(pFileOut, "\t\tdout\t\t: out unsigned(%d downto 0)\n", nbits_data-1);
fprintf(pFileOut, "\t);\n");
fprintf(pFileOut, "END %s;\n", ENT_NAME);
fprintf(pFileOut, "\n");
fprintf(pFileOut, "ARCHITECTURE %s OF %s IS\n", ARCH_NAME, ENT_NAME);
fprintf(pFileOut, "\n");
fprintf(pFileOut, "\tsubtype word_t is unsigned(%d downto 0);\n", nbits_data-1);
fprintf(pFileOut, "\ttype word_array_t is array (0 to %d) of word_t;\n", romsize/4-1);
fprintf(pFileOut, "\tsignal jtag_ld_clk\t\t: STD_LOGIC;\n");
fprintf(pFileOut, "\tsignal jtag_ld_we\t\t: STD_LOGIC;\n");
fprintf(pFileOut, "\tsignal jtag_ld_addr\t\t: unsigned (%d downto 0);\n", JTAG_ADDR_WIDTH-1);
fprintf(pFileOut, "\tsignal jtag_ld_dout\t\t: unsigned (%d downto 0);\n", nbits_data-1);
fprintf(pFileOut, "\tsignal jtag_ld_din\t\t: unsigned (%d downto 0);\n", nbits_data-1);
fprintf(pFileOut, "\tsignal bs_rst, bs_sel, bs_shift, bs_tdi, bs_tdo : std_logic;\n");
fprintf(pFileOut, "\tsignal bs_capture, bs_clk0, bs_clk1, bs_update0, bs_update1 : std_logic;\n");
fprintf(pFileOut, "\tsignal user_regi, user_rego : unsigned (%d downto 0);\n", 31 + JTAG_ADDR_WIDTH);
fprintf(pFileOut, "\n");
fprintf(pFileOut, "\tsignal word_array : word_array_t :=\n");
fprintf(pFileOut, "\t(\n");
fprintf(pFileOut, "\n");
// -------------------------------------------------------------------------
// ROM part
// -------------------------------------------------------------------------
for (i=0; i < filesize; i += sizeof(int))
{
fread(&word, 1, sizeof(int), pFileIn);
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
if (i < (romsize-sizeof(int)))
fprintf(pFileOut, ", -- %8.8X\n", i);
else
fprintf(pFileOut, " -- %8.8X\n", i);
}
word = 0;
for (; i < romsize; i += sizeof(int))
{
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
if (i < (romsize-sizeof(int)))
fprintf(pFileOut, ", -- %8.8X\n", i);
else
fprintf(pFileOut, " -- %8.8X\n", i);
}
fprintf(pFileOut, "\t);\n");
fprintf(pFileOut, "\n");
fprintf(pFileOut, "begin\n", ARCH_NAME);
fprintf(pFileOut, "\n");
fprintf(pFileOut, "PROM_READ:\n", ARCH_NAME);
fprintf(pFileOut, "\tprocess(clk)\n");
fprintf(pFileOut, "\tbegin\n");
fprintf(pFileOut, "\t\tif rising_edge(clk) and ce = '1' then\n");
fprintf(pFileOut, "\t\t\tdout <= word_array(to_integer(addr(%d downto 2)));\n", nbits_addr+1);
fprintf(pFileOut, "\t\tend if;\n");
fprintf(pFileOut, "\tend process;\n");
fprintf(pFileOut, "\n");
// -------------------------------------------------------------------------
// Trailer
// -------------------------------------------------------------------------
fprintf(pFileOut, "\n");
fputs(tpl, pFileOut);
fprintf(pFileOut, "PROM_WRITE:\n", ARCH_NAME);
fprintf(pFileOut, "\tprocess(jtag_ld_clk, jtag_ld_we)\n");
fprintf(pFileOut, "\tbegin\n");
fprintf(pFileOut, "\t\tif rising_edge(jtag_ld_clk) then\n");
fprintf(pFileOut, "\t\t\tif jtag_ld_we = '1' then\n");
fprintf(pFileOut, "\t\t\t\tword_array(to_integer(jtag_ld_addr(%d downto 0))) <= jtag_ld_din;\n", nbits_addr-1);
fprintf(pFileOut, "\t\t\telse\n");
fprintf(pFileOut, "\t\t\t\tjtag_ld_dout <= word_array(to_integer(jtag_ld_addr(%d downto 0)));\n", nbits_addr-1);
fprintf(pFileOut, "\t\t\tend if;\n");
fprintf(pFileOut, "\t\tend if;\n");
fprintf(pFileOut, "\tend process;\n");
fprintf(pFileOut, "\n");
fprintf(pFileOut, "end %s;\n", ARCH_NAME);
return 0;
}
int SaveROM_TCL(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntName, int nbits_addr, int nbits_data)
{
FILE *pFileIn, *pFileOut;
long start, end;
int i, word, word_addr, filesize, romsize;
char binstr_addr[33];
char binstr_data[33];
char tpl[] = {"# ---------------------------------------------------------------------\n# For Chipscope 9.1\n# ---------------------------------------------------------------------\n# Source JTAG/TCL frame work\ncd $env(CHIPSCOPE)\\\\bin\\\\nt\nsource csejtag.tcl\n\nnamespace import ::chipscope::*\n\n# Platform USB Cable\nset PLATFORM_USB_CABLE_ARGS [list \"port=USB2\" \"frequency=6000000\"]\n# frequency=\"24000000 | 12000000 | 6000000 | 3000000 | 1500000 | 750000\"\n\n# Create session\nset handle [::chipscope::csejtag_session create 0]\n\n# Open JTAG and lock\nset open_result [::chipscope::csejtag_target open $handle $CSEJTAG_TARGET_PLATFORMUSB 0 $PLATFORM_USB_CABLE_ARGS]\nset lock_result [::chipscope::csejtag_target lock $handle 1000]\n\nset devlist [::chipscope::csejtag_tap autodetect_chain $handle $CSEJTAG_SCAN_DEFAULT]\n\n# Get Device ID\nset devtype \"Virtex-4SX\"\nset devid 2\nset irlength [::chipscope::csejtag_tap get_irlength $handle $devid]\nset idcode [::chipscope::csejtag_tap get_device_idcode $handle $devid]\n\nset CSE_OP $CSEJTAG_SHIFT_READWRITE\nset CSE_ES $CSEJTAG_RUN_TEST_IDLE\n\n# Write Program\n"};
pFileIn = fopen(pFilenameIn, "rb");
if (!pFileIn)
{
fprintf(stderr, "Error opening file %s\n", pFilenameIn);
return 1;
}
pFileOut = fopen(pFilenameOut, "wb");
if (!pFileOut)
{
fprintf(stderr, "Error opening file %s\n", pFilenameOut);
return 1;
}
fseek(pFileIn, 0, SEEK_SET);
start = ftell(pFileIn);
fseek(pFileIn, 0, SEEK_END);
end = ftell(pFileIn);
fseek(pFileIn, 0, SEEK_SET);
filesize = (end-start);
romsize = (int)pow(2, nbits_addr+2);
// -------------------------------------------------------------------------
// Header
// -------------------------------------------------------------------------
fputs(tpl, pFileOut);
// -------------------------------------------------------------------------
// ROM part
// -------------------------------------------------------------------------
fprintf(pFileOut, "# Assembled from %s\n", pFilenameIn);
fprintf(pFileOut, "# ---------------------------------------------------------------\n");
fprintf(pFileOut, "# Shift the USER1 Instruction (b1111000010) into the Instruction Register of FPGA\n");
fprintf(pFileOut, "# User 1\n");
fprintf(pFileOut, "set result [::chipscope::csejtag_tap shift_device_ir $handle $devid $CSE_OP $CSE_ES 0 $irlength \"3C2\"]\n\n");
word_addr = 0;
for (i=0; i < filesize; i += sizeof(int))
{
fread(&word, 1, sizeof(int), pFileIn);
fprintf(pFileOut, "::chipscope::csejtag_tap shift_device_dr $handle $devid $CSE_OP $CSE_ES 0 %d \"%4.4X%8.8X\"\n", nbits_data + JTAG_ADDR_WIDTH, word_addr, word);
word_addr++;
}
fprintf(pFileOut, "\n");
// -------------------------------------------------------------------------
// Trailer
// -------------------------------------------------------------------------
fprintf(pFileOut, "::chipscope::csejtag_target unlock $handle\n");
fprintf(pFileOut, "::chipscope::csejtag_target close $handle\n");
fprintf(pFileOut, "::chipscope::csejtag_session destroy $handle\n");
fprintf(pFileOut, "exit\n");
return 0;
}
int main(int argc, char *argv[])
{
char *pFilenameIn;
char name_prj[1024];
char name_rom[1024];
char name_rom_v4ld[1024];
char name_rom_tcl[1024];
FILE *pFileIn;
int filesize, romsize, nbits_addr, nbits_data;
long start, end;
int word, i;
if (argc < 2)
{
fprintf(stderr, "Usage: romgen <input file> <num. word address bits>\n");
return 1;
}
pFilenameIn = argv[1];
if (argc == 3)
nbits_addr = atoi(argv[2]);
basename(pFilenameIn, name_prj);
sprintf(name_rom, "%s.vhd", name_prj);
sprintf(name_rom_v4ld, "%s_ld.vhd", name_prj);
sprintf(name_rom_tcl, "%s.tcl", name_prj);
SaveROM(pFilenameIn, name_rom, ARCH_NAME, ENT_NAME, nbits_addr, 32);
SaveROM_V4LD(pFilenameIn, name_rom_v4ld, ARCH_NAME, ENT_NAME, nbits_addr, 32);
SaveROM_TCL(pFilenameIn, name_rom_tcl, ARCH_NAME, ENT_NAME, nbits_addr, 32);
return 0;
}
-2
View File
@@ -1,2 +0,0 @@
VHDL/lib/emac/emac_jb.vhd
-8
View File
@@ -1,8 +0,0 @@
VHDL/lib/emac/sim/tb_emac_jb.fdo
VHDL/lib/emac/sim/tb_serdes.fdo
VHDL/lib/emac/sim/tb_emac_jb.wdo
VHDL/lib/emac/sim/tb_serdes.wdo
VHDL/lib/emac/sim/tb_serdes.fdo
VHDL/lib/emac/sim/tb_serdes.wdo
-14
View File
@@ -1,14 +0,0 @@
## NOTE: Do not edit this file.
## Autogenerated by ProjNav (creatfdo.tcl) on Thu Jul 06 20:49:07 Westeuropäische Sommerzeit 2006
##
vlib work
vcom -explicit -93 "../../misc/utils_pkg.vhd"
vcom -explicit -93 "../src/crc32.vhd"
vcom -explicit -93 "../src/tb_crc32.vhd"
vsim -t 1ps -lib work tb_crc32
view wave
do {tb_crc32.wdo}
view structure
view signals
run 1 us
-25
View File
@@ -1,25 +0,0 @@
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate -format Logic /tb_crc32/clk
add wave -noupdate -format Logic /tb_crc32/rst
add wave -noupdate -format Logic /tb_crc32/din_vld
add wave -noupdate -format Literal -radix hexadecimal /tb_crc32/din
add wave -noupdate -format Literal -radix hexadecimal /tb_crc32/crc32
add wave -noupdate -format Logic /tb_crc32/crc32_vld
add wave -noupdate -format Literal -radix hexadecimal /tb_crc32/test_data
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {667016 ps} 0}
configure wave -namecolwidth 150
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 100
configure wave -griddelta 40
configure wave -timeline 1
update
WaveRestoreZoom {0 ps} {1050 ns}
-15
View File
@@ -1,15 +0,0 @@
## NOTE: Do not edit this file.
## Autogenerated by ProjNav (creatfdo.tcl) on Thu Jul 06 20:49:07 Westeuropäische Sommerzeit 2006
##
vlib work
vcom -explicit -93 "../../misc/utils_pkg.vhd"
vcom -explicit -93 "../src/piso.vhd"
vcom -explicit -93 "../src/sipo.vhd"
vcom -explicit -93 "../src/tb_serdes.vhd"
vsim -t 1ps -lib work tb_serdes
view wave
do {tb_serdes.wdo}
view structure
view signals
run 20 us
-58
View File
@@ -1,58 +0,0 @@
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate -format Logic /tb_serdes/clk
add wave -noupdate -format Logic /tb_serdes/rst
add wave -noupdate -divider PiSo
add wave -noupdate -format Logic /tb_serdes/clk
add wave -noupdate -format Logic /tb_serdes/piso_din_vld
add wave -noupdate -format Logic /tb_serdes/piso_din_rdy
add wave -noupdate -format Literal /tb_serdes/piso_din_be
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/piso_din
add wave -noupdate -format Logic /tb_serdes/piso_dout_vld
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/piso_dout
add wave -noupdate -format Logic /tb_serdes/piso_dout_en
add wave -noupdate -divider SiPo
add wave -noupdate -format Logic /tb_serdes/clk
add wave -noupdate -format Logic /tb_serdes/sipo_enable
add wave -noupdate -format Logic /tb_serdes/sipo_rst
add wave -noupdate -format Logic /tb_serdes/sipo_din_vld
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/sipo_din
add wave -noupdate -format Logic /tb_serdes/sipo_dout_vld
add wave -noupdate -format Logic /tb_serdes/sipo_dout_en
add wave -noupdate -format Literal /tb_serdes/sipo_dout_be
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/sipo_dout
add wave -noupdate -divider PiSo
add wave -noupdate -format Logic /tb_serdes/clk
add wave -noupdate -format Logic /tb_serdes/piso2_din_vld
add wave -noupdate -format Logic /tb_serdes/piso2_din_rdy
add wave -noupdate -format Literal /tb_serdes/piso2_din_be
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/piso2_din
add wave -noupdate -format Logic /tb_serdes/piso2_dout_vld
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/piso2_dout
add wave -noupdate -format Logic /tb_serdes/piso2_dout_en
add wave -noupdate -divider SiPo
add wave -noupdate -format Logic /tb_serdes/clk
add wave -noupdate -format Logic /tb_serdes/sipo2_enable
add wave -noupdate -format Logic /tb_serdes/sipo2_rst
add wave -noupdate -format Logic /tb_serdes/sipo2_din_vld
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/sipo2_din
add wave -noupdate -format Logic /tb_serdes/sipo2_dout_vld
add wave -noupdate -format Logic /tb_serdes/sipo2_dout_en
add wave -noupdate -format Literal /tb_serdes/sipo2_dout_be
add wave -noupdate -format Literal -radix hexadecimal /tb_serdes/sipo2_dout
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {19757882 ps} 0} {{Cursor 2} {49999912163 ps} 0} {{Cursor 3} {49999529250 ps} 0}
configure wave -namecolwidth 150
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 100
configure wave -griddelta 40
configure wave -timeline 1
update
WaveRestoreZoom {0 ps} {21 us}
-34
View File
@@ -1,34 +0,0 @@
## NOTE: Do not edit this file.
## Autogenerated by ProjNav (creatfdo.tcl) on Thu Jul 06 20:49:07 Westeuropäische Sommerzeit 2006
##
vlib work
vcom -explicit -93 "../../misc/utils_pkg.vhd"
vcom -explicit -93 "../../rams/dpram_1w1r2c_ra_sim.vhd"
vcom -explicit -93 "../../rams/dpram_2w2r2c_ra_sim.vhd"
vcom -explicit -93 "../../rams/dpram_1w1r2c_ro_sim.vhd"
vcom -explicit -93 "../../rams/dpram_2w2r2c_ro_sim.vhd"
vcom -explicit -93 "../../FIFO/src/fifo_ctrl_pkg.vhd"
vcom -explicit -93 "../../FIFO/src/fifo_sync_ctrl.vhd"
vcom -explicit -93 "../../FIFO/src/fifo_sync.vhd"
vcom -explicit -93 "../../FIFO/src/gray_counter.vhd"
vcom -explicit -93 "../../FIFO/src/fifo_async_ctrl.vhd"
vcom -explicit -93 "../../FIFO/src/fifo_async.vhd"
vcom -explicit -93 "../../JBUS/src/busmaster_types.vhd"
vcom -explicit -93 "../../JBUS/src/busmaster_sync.vhd"
vcom -explicit -93 "../../JBUS/src/dmac.vhd"
vcom -explicit -93 "../src/piso.vhd"
vcom -explicit -93 "../src/sipo.vhd"
vcom -explicit -93 "../src/crc32.vhd"
vcom -explicit -93 "../src/emac_types.vhd"
vcom -explicit -93 "../src/emac_rx.vhd"
vcom -explicit -93 "../src/emac_tx.vhd"
vcom -explicit -93 "../src/emac_top_jb.vhd"
vcom -explicit -93 "../src/pkt_gen.vhd"
vcom -explicit -93 "../src/tb_emac_top_jb.vhd"
vsim -t 1ps -lib work tb_emac_top_jb
view wave
do {tb_emac_top_jb.wdo}
view structure
view signals
run 16000 us
-236
View File
@@ -1,236 +0,0 @@
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate -divider {Ethernet MAC}
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/clk_i
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/rst_i
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/ram64
add wave -noupdate -divider Slave
add wave -noupdate -format Logic -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/int_o
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/cyc_i
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/stb_i
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/sel_i
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/we_i
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/ack_o
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/srdy_o
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mrdy_i
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/addr_i
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/dat_i
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/dat_o
add wave -noupdate -divider Master
add wave -noupdate -format Logic /tb_emac_top_jb/cyc_o
add wave -noupdate -format Logic /tb_emac_top_jb/stb_o
add wave -noupdate -format Logic /tb_emac_top_jb/we_o
add wave -noupdate -format Literal /tb_emac_top_jb/sel_o
add wave -noupdate -format Logic /tb_emac_top_jb/ack_i
add wave -noupdate -format Logic /tb_emac_top_jb/mrdy_o
add wave -noupdate -format Logic /tb_emac_top_jb/srdy_i
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/addr_o
add wave -noupdate -format Literal /tb_emac_top_jb/mdat_i
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/mdat_o
add wave -noupdate -divider MII
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_rx_clk
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_rx_dv
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_rx_er
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/mii_rx
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_tx_clk
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_tx_en
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_tx_er
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/mii_tx
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_gtx_clk
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_crs
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/mii_col
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/status_reg
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/size_reg
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/dat_o_reg
add wave -noupdate -format Literal /tb_emac_top_jb/emac_action
add wave -noupdate -format Logic /tb_emac_top_jb/dat_o_cnt_rst
add wave -noupdate -format Literal /tb_emac_top_jb/dat_o_cnt
add wave -noupdate -format Literal /tb_emac_top_jb/pkt_count
add wave -noupdate -divider {Packet generator}
add wave -noupdate -format Literal /tb_emac_top_jb/inst_pkt_gen/tx_packets
add wave -noupdate -format Literal /tb_emac_top_jb/inst_pkt_gen/tx_bytes
add wave -noupdate -format Literal -radix unsigned /tb_emac_top_jb/inst_pkt_gen/pkt_nbytes
add wave -noupdate -format Literal -radix unsigned /tb_emac_top_jb/inst_pkt_gen/pkt_nwords
add wave -noupdate -format Literal /tb_emac_top_jb/inst_pkt_gen/host_s
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_emac_top_jb/inst_pkt_gen/tx_ctrl_in
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_emac_top_jb/inst_pkt_gen/tx_ctrl_out
add wave -noupdate -format Literal /tb_emac_top_jb/inst_pkt_gen/tx_bytes
add wave -noupdate -format Literal /tb_emac_top_jb/inst_pkt_gen/tx_packets
add wave -noupdate -format Literal -radix unsigned /tb_emac_top_jb/inst_pkt_gen/fill_size
add wave -noupdate -format Literal -radix unsigned /tb_emac_top_jb/inst_pkt_gen/fill_cnt
add wave -noupdate -format Logic /tb_emac_top_jb/inst_pkt_gen/fill_rdy
add wave -noupdate -format Logic /tb_emac_top_jb/inst_pkt_gen/fill_set
add wave -noupdate -format Logic /tb_emac_top_jb/inst_pkt_gen/fill_en
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_pkt_gen/tx_din
add wave -noupdate -format Logic /tb_emac_top_jb/inst_pkt_gen/tx_din_vld
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/pktgen_tx
add wave -noupdate -format Logic /tb_emac_top_jb/pktgen_tx_en
add wave -noupdate -format Logic /tb_emac_top_jb/pktgen_tx_er
add wave -noupdate -format Logic /tb_emac_top_jb/pktgen_en
add wave -noupdate -divider RX-DMA
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/master_req
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/master_gnt
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/dma_start
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/dma_active
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/dma_end
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_rdy
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_en
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_rw
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_addr_start
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_num_xfers
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_addr_auto_inc
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_complete
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/req_complete_ack
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/gen_dmac__0/inst_dmac/s
add wave -noupdate -divider RX
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/clk
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/rst
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/dout_re
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/dout
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ctrl_in
add wave -noupdate -format Literal -radix unsigned -expand /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ctrl_out
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mii_rx_clk
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mii_rx_dv
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mii_rx_er
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mii_rx
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mii_crs
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mii_col
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/cmd_fifo_din
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/cmd_fifo_dout
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/cmd_fifo_we
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/cmd_fifo_re
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/cmd_fifo_empty
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/cmd_fifo_full
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/host_ptr
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/host_ram_limit
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/host_ram_base
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/commit_en
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/xfer_ram_limit
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/xfer_ram_full
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/xfer_base
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/xfer_ptr
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ram_en_a
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ram_we_a
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ram_addr_a
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ram_din_a
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ram_en_b
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/ram_addr_b
add wave -noupdate -format Literal -radix unsigned /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/byte_count
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_din
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_din_vld
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_dout
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_dout_be
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_dout_vld
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_dout_en
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_en
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo32_rst
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo8_dout
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo8_rst
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo8_dout_vld
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/sipo8_dout_en
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/host_s
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/xfer_s
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/preamble_bsy
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/preamble_ok
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/preamble_rdy
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mac_chk_rdy
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mac_chk_ok
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mac_chk_num_ok
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mac_chk_addr
add wave -noupdate -format Literal -radix unsigned /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/mac_chk_cnt
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/fcs_vld
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/fcs_din_vld
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/fcs
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_rx/fcs_chk_ok
add wave -noupdate -divider TX
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/clk
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/rst
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/din_vld
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/din
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ctrl_in
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ctrl_out
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/cmd_fifo_din
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/cmd_fifo_dout
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/cmd_fifo_we
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/cmd_fifo_re
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/cmd_fifo_empty
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/cmd_fifo_full
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_pre_rdy
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_bsy
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_set
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_en
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_cnt_en
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_base
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_size
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_cnt
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_ptr
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fill_remain
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/alloc_ok
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/alloc_req
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/alloc_ack
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/nwords_free
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/alloc_size
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mem_alloc_en
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mem_free_en
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/commit_en
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/uncommit_en
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_bsy
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_size
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_ptr
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_cnt
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_cnt_en
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_en
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_set
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ram_en_a
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ram_we_a
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ram_addr_a
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ram_din_a
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ram_en_b
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ram_addr_b
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/ram_dout_b
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso32_din
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso32_din_be
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso32_din_rdy
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso32_din_vld
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso32_dout
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso32_dout_vld
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso32_dout_en
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_fifo_we
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_fifo_re
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_fifo_full
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_fifo_empty
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_fifo_re_dly
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso8_din_vld
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso8_din
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso8_dout_vld
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso8_din_rdy
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/piso8_dout
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fcs_rst
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fcs_en
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fcs_din_vld
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fcs_vld
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/fcs
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_tx_clk
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_tx_en
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_tx_er
add wave -noupdate -format Literal -radix hexadecimal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mii_tx
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/host_s
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/xfer_s
add wave -noupdate -format Logic /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mem_free_req
add wave -noupdate -format Literal /tb_emac_top_jb/inst_emac_top_jb/inst_emac_tx/mem_free_ack
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {15999470765 ps} 0} {{Cursor 2} {49999967706 ps} 0} {{Cursor 3} {42725669958 ps} 0} {{Cursor 4} {10461803096 ps} 0} {{Cursor 5} {10000 ps} 0}
configure wave -namecolwidth 150
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 100
configure wave -griddelta 40
configure wave -timeline 1
update
WaveRestoreZoom {0 ps} {379173 ps}
-8
View File
@@ -1,8 +0,0 @@
VHDL/lib/emac/emac_jb.vhd
VHDL/lib/emac/src/emac_jb.vhd
VHDL/lib/emac/src/emac_jb.vhd
VHDL/lib/emac/src/tb_emac_jb.vhd
VHDL/lib/emac/src/tb_serdes.vhd
VHDL/lib/emac/src/tb_serdes.vhd
-64
View File
@@ -1,64 +0,0 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
use std.textio.all; -- Imports the standard textio package.
use work.utils_pkg.all; -- Imports the standard textio package.
ENTITY crc32 IS
Generic
(
crc32_init : unsigned(31 downto 0) := X"00000000"
);
Port
(
rst : in STD_LOGIC;
clk : in STD_LOGIC;
din_vld : in STD_LOGIC;
din : in unsigned(7 downto 0);
crc32_vld : out STD_LOGIC;
crc32_out : out unsigned(31 downto 0)
);
END crc32;
ARCHITECTURE behavior OF crc32 IS
type crc_table_t is array (0 to 15) of unsigned(31 downto 0);
constant crc_table : crc_table_t :=
(
X"4DBDF21C", X"500AE278", X"76D3D2D4", X"6B64C2B0",
X"3B61B38C", X"26D6A3E8", X"000F9344", X"1DB88320",
X"A005713C", X"BDB26158", X"9B6B51F4", X"86DC4190",
X"D6D930AC", X"CB6E20C8", X"EDB71064", X"F0000000"
);
signal crc0 : unsigned(31 downto 0);
signal crc1 : unsigned(31 downto 0);
signal crc2 : unsigned(31 downto 0);
--------------------------------------------------------------------------
begin
crc1 <= X"0" & crc0(31 downto 4) xor crc_table(to_integer(crc0(3 downto 0) xor din(3 downto 0)));
crc2 <= X"0" & crc1(31 downto 4) xor crc_table(to_integer(crc1(3 downto 0) xor din(7 downto 4)));
crc32_out <= crc0;
--------------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
crc0 <= crc32_init;
crc32_vld <= '0';
elsif din_vld = '1' then
crc0 <= crc2;
crc32_vld <= '1';
end if;
end if;
end process;
--------------------------------------------------------------------------
end behavior;
-561
View File
@@ -1,561 +0,0 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
use std.textio.all; -- Imports the standard textio package.
use work.emac_types.all;
use work.utils_pkg.all;
ENTITY emac_rx IS
Generic
(
f_sysclk : real := 100.0;
RAM_SIZE : natural := 2048
);
Port
(
clk : in STD_LOGIC;
rst : in STD_LOGIC;
dout_re : in STD_LOGIC;
dout : out unsigned(31 downto 0);
ctrl_in : in rx_ctrl_in_t;
ctrl_out : out rx_ctrl_out_t;
mii_rx_clk : in STD_LOGIC;
mii_rx_dv : in STD_LOGIC;
mii_rx_er : in STD_LOGIC;
mii_rx : in unsigned(7 downto 0);
mii_crs : in STD_LOGIC;
mii_col : in STD_LOGIC
);
END emac_rx;
ARCHITECTURE behavior OF emac_rx IS
constant RAM_ADDR_WIDTH : natural := NextExpBaseTwo(RAM_SIZE);
subtype word_ptr_t is unsigned(RAM_ADDR_WIDTH-1 downto 0);
-- Signals for EMAC connections
signal cmd_fifo_din : unsigned(2*word_ptr_t'length+2 downto 0);
signal cmd_fifo_dout : unsigned(2*word_ptr_t'length+2 downto 0);
signal cmd_fifo_we : std_logic;
signal cmd_fifo_re : std_logic;
signal cmd_fifo_empty : std_logic;
signal cmd_fifo_full : std_logic;
signal reset_en : std_logic;
signal host_ptr : word_ptr_t;
signal host_ptr_next : word_ptr_t;
signal host_ram_limit : word_ptr_t;
signal host_ram_base : word_ptr_t;
signal commit_en : std_logic;
signal xfer_ram_limit : word_ptr_t;
signal xfer_ram_full : std_logic;
signal xfer_base : word_ptr_t;
signal xfer_ptr : word_ptr_t;
signal xfer_en : std_logic;
signal xfer_set : std_logic;
signal xfer_vld : std_logic;
signal xfer_promiscious : std_logic;
signal ram_en_a : std_logic;
signal ram_we_a : std_logic;
signal ram_addr_a : word_ptr_t;
signal ram_din_a : unsigned(31 downto 0);
signal ram_dout_b : unsigned(31 downto 0);
signal ram_en_b : std_logic;
signal ram_addr_b : word_ptr_t;
signal sipo32_din : unsigned(7 downto 0);
signal sipo32_din_vld : std_logic;
signal sipo32_dout : unsigned(31 downto 0);
signal sipo32_dout_be : unsigned(3 downto 0);
signal sipo32_dout_vld : std_logic;
signal sipo32_dout_en : std_logic;
signal sipo32_en : std_logic;
signal sipo32_rst : std_logic;
signal sipo8_dout : unsigned(7 downto 0);
signal sipo8_rst : std_logic;
signal sipo8_dout_vld : std_logic;
signal sipo8_dout_en : std_logic;
signal sipo8_en : std_logic;
signal byte_count_rst : std_logic;
signal byte_count : word_ptr_t;
signal reset_pipe : unsigned(31 downto 0);
signal preamble_en : std_logic;
signal preamble_rdy : std_logic;
signal preamble_bsy : std_logic;
signal preamble_OK : std_logic;
signal mac_chk_rdy : std_logic;
signal mac_chk_BC : std_logic;
signal mac_chk_OK : std_logic;
signal mac_chk_num_OK : natural range 0 to 6;
signal mac_chk_num_BC : natural range 0 to 6;
signal mac_chk_cnt : natural range 0 to 5;
signal mac_addr : mac_addr_t;
signal mac_chk_addr : mac_addr_t;
signal Gbps_en : std_logic;
signal fcs_chk_en : std_logic;
signal rx_en : std_logic;
signal fcs_vld : std_logic;
signal fcs_din_vld : std_logic;
signal fcs_din : unsigned(7 downto 0);
signal fcs : unsigned(31 downto 0);
signal fcs_chk_OK : std_logic;
type host_state_t is (host_init, host_flush, host_idle);
signal host_s, host_sn : host_state_t;
type xfer_state_t is (xfer_init, xfer_idle, xfer_preamble, xfer_setup, xfer_active, xfer_finish, xfer_commit);
signal xfer_s, xfer_sn : xfer_state_t;
alias cmd_mac_ok_in is cmd_fifo_din(cmd_fifo_din'left);
alias cmd_bcast_in is cmd_fifo_din(cmd_fifo_din'left-1);
alias cmd_pkt_valid_in is cmd_fifo_din(cmd_fifo_din'left-2);
alias cmd_nbytes_in is cmd_fifo_din(word_ptr_t'length-1 downto 0);
alias cmd_base_in is cmd_fifo_din(2*word_ptr_t'length-1 downto word_ptr_t'length);
alias cmd_mac_ok_out is cmd_fifo_dout(cmd_fifo_dout'left);
alias cmd_bcast_out is cmd_fifo_dout(cmd_fifo_dout'left-1);
alias cmd_pkt_valid_out is cmd_fifo_dout(cmd_fifo_dout'left-2);
alias cmd_nbytes_out is cmd_fifo_dout(word_ptr_t'length-1 downto 0);
alias cmd_base_out is cmd_fifo_dout(2*word_ptr_t'length-1 downto word_ptr_t'length);
begin
ctrl_out.rx_size <= resize(cmd_nbytes_out, 16);
ctrl_out.pkt_avail <= not cmd_fifo_empty;
ctrl_out.pkt_valid <= cmd_pkt_valid_out;
ctrl_out.pkt_bcast <= cmd_bcast_out;
ctrl_out.pkt_mac_match <= cmd_mac_ok_out;
ctrl_out.reset_busy <= reset_en;
dout <= ram_dout_b;
ram_en_b <= '1';
ram_addr_b <= host_ptr_next;
ram_en_a <= '1';
ram_din_a <= sipo32_dout;
ram_addr_a <= xfer_ptr;
ram_we_a <= xfer_en and sipo32_dout_vld;
xfer_vld <= (mac_chk_OK or mac_chk_BC or xfer_promiscious) and (not fcs_chk_en or fcs_chk_OK);
cmd_fifo_we <= commit_en and xfer_vld;
cmd_fifo_re <= ctrl_in.pkt_free_en;
cmd_pkt_valid_in <= fcs_chk_OK;
cmd_mac_ok_in <= mac_chk_OK;
cmd_bcast_in <= mac_chk_BC;
cmd_nbytes_in <= byte_count;
cmd_base_in <= xfer_base;
reset_en <= reset_pipe(reset_pipe'left);
------------------------------------------------------------------
reset_gen:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' or ctrl_in.reset = '1' then
reset_pipe <= (others => '1');
else
reset_pipe <= reset_pipe(reset_pipe'left-1 downto 0) & '0';
end if;
end if;
end process;
------------------------------------------------------------------
-- Fill stuff
------------------------------------------------------------------
fill_pointer:
process(clk)
begin
if rising_edge(clk) then
if ctrl_in.pkt_req_en = '1' then
host_ptr <= cmd_base_out;
elsif dout_re = '1' then
host_ptr <= host_ptr_next;
end if;
end if;
end process;
host_ptr_next <= host_ptr + 1 when dout_re = '1' else host_ptr;
------------------------------------------------------------------
-- Transfer stuff
------------------------------------------------------------------
host2xfer_sync_register:
process(mii_rx_clk)
begin
if rising_edge(mii_rx_clk) then
xfer_promiscious <= ctrl_in.promiscious;
Gbps_en <= ctrl_in.Gbps_en;
fcs_chk_en <= ctrl_in.fcs_chk_en;
mac_addr <= ctrl_in.mac_addr;
xfer_ram_limit <= host_ram_limit;
end if;
end process;
host_limit_register:
process(clk)
begin
if rising_edge(clk) then
host_ram_base <= xfer_base;
if cmd_fifo_empty = '1' then
host_ram_limit <= host_ram_base - 1;
else
host_ram_limit <= cmd_base_out - 1;
end if;
end if;
end process;
xfer_ram_full_detect:
process(mii_rx_clk)
begin
if rising_edge(mii_rx_clk) then
if xfer_set = '1' or reset_en = '1' then
xfer_ram_full <= '0';
elsif xfer_en = '1' and sipo32_dout_vld = '1' then
if xfer_ptr = xfer_ram_limit then
xfer_ram_full <= '1';
end if;
end if;
end if;
end process;
xfer_base_logic:
process(mii_rx_clk)
begin
if rising_edge(mii_rx_clk) then
if reset_en = '1' then
xfer_base <= (others => '0');
elsif commit_en = '1' and xfer_vld = '1' then
xfer_base <= xfer_ptr;
end if;
end if;
end process;
xfer_pointer:
process(mii_rx_clk)
begin
if rising_edge(mii_rx_clk) then
if xfer_set = '1' then
xfer_ptr <= xfer_base;
elsif xfer_en = '1' and sipo32_dout_vld = '1' then
xfer_ptr <= xfer_ptr + 1;
end if;
end if;
end process;
------------------------------------------------------------------
byte_counter:
process(mii_rx_clk)
begin
if rising_edge(mii_rx_clk) then
if byte_count_rst = '1' then
if fcs_chk_en = '0' then
byte_count <= to_unsigned(0, RAM_ADDR_WIDTH);
else
byte_count <= unsigned(to_signed(-4, RAM_ADDR_WIDTH));
end if;
elsif sipo32_en = '1' and sipo32_din_vld = '1' then
byte_count <= byte_count + 1;
end if;
end if;
end process;
preamble_sync_logic:
process(mii_rx_clk)
begin
if rising_edge(mii_rx_clk) then
if preamble_en = '0' then
preamble_rdy <= '0';
preamble_bsy <= '0';
preamble_OK <= '0';
elsif sipo32_din_vld = '1' then
if preamble_bsy = '1' then
if sipo32_din = X"D5" then
preamble_OK <= '1';
end if;
end if;
if sipo32_din /= X"55" then
preamble_bsy <= '0';
preamble_rdy <= preamble_bsy;
else
preamble_bsy <= '1';
end if;
end if;
end if;
end process;
mac_check_logic:
process(mii_rx_clk)
begin
if rising_edge(mii_rx_clk) then
if byte_count_rst = '1' then
mac_chk_rdy <= '0';
mac_chk_OK <= '0';
mac_chk_BC <= '0';
mac_chk_cnt <= 0;
mac_chk_num_OK <= 0;
mac_chk_num_BC <= 0;
mac_chk_addr <= mac_addr;
elsif mac_chk_rdy = '1' then
if mac_chk_num_OK = 6 then
mac_chk_OK <= '1';
end if;
if mac_chk_num_BC = 6 then
mac_chk_BC <= '1';
end if;
elsif sipo32_din_vld = '1' and sipo32_en = '1' then
if sipo32_din = mac_chk_addr(mac_chk_cnt) then
mac_chk_num_OK <= mac_chk_num_OK + 1;
end if;
if sipo32_din = X"FF" then
mac_chk_num_BC <= mac_chk_num_BC + 1;
end if;
if mac_chk_cnt /= 5 then
mac_chk_cnt <= mac_chk_cnt + 1;
else
mac_chk_rdy <= '1';
end if;
end if;
end if;
end process;
------------------------------------------------------------------
xfer_state_next:
process(mii_rx_clk)
begin
if rising_edge(mii_rx_clk) then
if reset_en = '1' then
xfer_s <= xfer_init;
else
xfer_s <= xfer_sn;
end if;
end if;
end process;
xfer_state:
process(xfer_s, rx_en, sipo32_dout_en, preamble_bsy, preamble_OK, xfer_ram_full)
begin
commit_en <= '0';
xfer_set <= '0';
xfer_en <= '0';
sipo32_rst <= '0';
sipo32_en <= '0';
byte_count_rst <= '0';
preamble_en <= '0';
xfer_sn <= xfer_s;
case xfer_s is
when xfer_init =>
sipo32_rst <= '1';
if rx_en = '0' then
xfer_sn <= xfer_idle;
end if;
when xfer_idle =>
preamble_en <= rx_en;
if preamble_bsy = '1' then
xfer_sn <= xfer_preamble;
end if;
when xfer_preamble =>
preamble_en <= rx_en;
byte_count_rst <= preamble_bsy;
sipo32_en <= rx_en and not preamble_bsy;
if preamble_bsy = '0' then
xfer_sn <= xfer_init;
if preamble_OK = '1' then
xfer_sn <= xfer_setup;
end if;
end if;
when xfer_setup =>
xfer_set <= '1';
sipo32_en <= rx_en;
xfer_en <= sipo32_dout_en;
xfer_sn <= xfer_active;
when xfer_active =>
xfer_en <= sipo32_dout_en;
sipo32_en <= rx_en;
if xfer_ram_full = '1' then
xfer_sn <= xfer_init;
elsif rx_en = '0' then
xfer_sn <= xfer_finish;
end if;
when xfer_finish =>
xfer_en <= sipo32_dout_en;
if sipo32_dout_en = '0' then
xfer_sn <= xfer_commit;
end if;
when xfer_commit =>
commit_en <= '1';
xfer_sn <= xfer_init;
when others =>
xfer_sn <= xfer_init;
end case;
end process;
------------------------------------------------------------------
-- Instantiate synchronous FIFO
inst_cmd_fifo: entity work.fifo_async
GENERIC MAP
(
addr_width => NextExpBaseTwo(RAM_SIZE) - 4, -- RAMSIZE(words)/MIN_PACKET_LEN(words)
data_width => cmd_fifo_din'length,
do_last_read_update => false
)
PORT MAP
(
rst => reset_en,
clk_w => mii_rx_clk,
clk_r => clk,
we => cmd_fifo_we,
re => cmd_fifo_re,
fifo_full => cmd_fifo_full,
fifo_empty => cmd_fifo_empty,
fifo_afull => open,
fifo_aempty => open,
data_w => cmd_fifo_din,
data_r => cmd_fifo_dout
);
inst_ram : entity work.dpram_1w1r2c_ro
GENERIC MAP
(
addr_width => RAM_ADDR_WIDTH,
data_width => 32
)
PORT MAP
(
clk_a => mii_rx_clk,
clk_b => clk,
en_a => ram_en_a,
en_b => ram_en_b,
we_a => ram_we_a,
addr_a => ram_addr_a,
addr_b => ram_addr_b,
din_a => ram_din_a,
dout_b => ram_dout_b
);
inst_sipo32 : entity work.sipo
GENERIC MAP
(
data_width_in => 8,
data_width_out => 32,
msb_first => true
)
PORT MAP
(
rst => sipo32_rst,
clk => mii_rx_clk,
din_vld => sipo32_din_vld,
din_en => sipo32_en,
din => sipo32_din,
dout_be => sipo32_dout_be,
dout_vld => sipo32_dout_vld,
dout => sipo32_dout,
dout_en => sipo32_dout_en
);
inst_fcs: entity work.crc32
GENERIC MAP
(
crc32_init => X"00000000"
)
PORT MAP
(
rst => byte_count_rst,
clk => mii_rx_clk,
din_vld => fcs_din_vld,
din => fcs_din,
crc32_vld => fcs_vld,
crc32_out => fcs
);
fcs_din <= sipo32_din;
fcs_din_vld <= sipo32_en and sipo32_din_vld;
fcs_chk_register:
process(mii_rx_clk)
begin
if rising_edge(mii_rx_clk) then
if fcs_vld = '1' then
fcs_chk_OK <= '0';
if fcs = X"2144DF1C" then
fcs_chk_OK <= '1';
end if;
end if;
end if;
end process;
mii_input_register:
process(mii_rx_clk)
begin
if rising_edge(mii_rx_clk) then
if Gbps_en = '1' then
sipo32_din <= mii_rx;
sipo32_din_vld <= not mii_rx_er;
rx_en <= mii_rx_dv;
else
sipo32_din <= sipo8_dout;
sipo32_din_vld <= sipo8_dout_vld;
rx_en <= sipo8_dout_en;
end if;
end if;
end process;
inst_sipo_8bit : entity work.sipo
GENERIC MAP
(
data_width_in => 4,
data_width_out => 8,
msb_first => false
)
PORT MAP
(
rst => sipo8_rst,
clk => mii_rx_clk,
din_vld => mii_rx_dv,
din_en => mii_rx_dv,
din => mii_rx(3 downto 0),
dout_be => open,
dout_vld => sipo8_dout_vld,
dout => sipo8_dout,
dout_en => sipo8_dout_en
);
sipo8_rst <= reset_en or not (mii_rx_dv or sipo8_dout_en);
sipo8_en <= not mii_rx_er;
end behavior;
-503
View File
@@ -1,503 +0,0 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
use std.textio.all; -- Imports the standard textio package.
use work.emac_types.all;
use work.utils_pkg.all;
use work.busmaster_types.all;
ENTITY emac_top_jb IS
Generic
(
f_sysclk : real := 100.0;
TX_RAM_SIZE : natural := 2048;
RX_RAM_SIZE : natural := 2048
);
Port
(
-- JBUS Slave
CLK_I : in STD_LOGIC;
RST_I : in STD_LOGIC;
INT_O : out STD_LOGIC;
CYC_I : in STD_LOGIC;
STB_I : in STD_LOGIC;
SEL_I : in unsigned(3 downto 0);
WE_I : in STD_LOGIC;
ACK_O : out STD_LOGIC;
SRDY_O : out STD_LOGIC;
MRDY_I : in STD_LOGIC;
ADDR_I : in unsigned(31 downto 0);
DAT_I : in unsigned(31 downto 0);
DAT_O : out unsigned(31 downto 0);
-- JBUS Master
ACK_I : in std_logic;
SRDY_I : in std_logic;
MDAT_I : in unsigned(31 downto 0);
MDAT_O : out unsigned(31 downto 0);
ADDR_O : out unsigned(31 downto 0);
SEL_O : out unsigned(3 downto 0);
WE_O : out std_logic;
CYC_O : out std_logic;
STB_O : out std_logic;
MRDY_O : out std_logic;
-- MII
mii_rx_clk : in STD_LOGIC;
mii_rx_dv : in STD_LOGIC;
mii_rx_er : in STD_LOGIC;
mii_rx : in unsigned(7 downto 0);
mii_tx_clk : in STD_LOGIC;
mii_tx_en : out STD_LOGIC;
mii_tx_er : out STD_LOGIC;
mii_tx : out unsigned(7 downto 0);
mii_gtx_clk : out STD_LOGIC;
mii_crs : in STD_LOGIC;
mii_col : in STD_LOGIC
);
END emac_top_jb;
ARCHITECTURE behavior OF emac_top_jb IS
-- Constants
constant DMA_NUM_CHANNEL : integer := 2;
constant DMA_CH_WRITE : integer := 0;
constant DMA_CH_READ : integer := 1;
constant DMA_RW_CONF : unsigned(DMA_NUM_CHANNEL-1 downto 0) := "01";
-- Signals for EMAC connections
signal tx_ctrl_in : tx_ctrl_in_t;
signal tx_ctrl_out : tx_ctrl_out_t;
signal tx_din : unsigned(31 downto 0);
signal tx_din_vld : std_logic;
signal rx_ctrl_in : rx_ctrl_in_t;
signal rx_ctrl_out : rx_ctrl_out_t;
signal rx_dout : unsigned(31 downto 0);
signal rx_dout_re : std_logic;
signal rx_int_en : std_logic;
signal tx_int_en : std_logic;
signal irq_rx : std_logic;
signal irq_tx : std_logic;
signal ready : std_logic;
signal read : std_logic;
signal write : std_logic;
signal rx_read_en_CPU : std_logic;
signal rx_req_en_CPU : std_logic;
signal rx_free_en_CPU : std_logic;
signal tx_write_en_CPU : std_logic;
signal reg_read : std_logic;
signal reg_write : std_logic;
signal reg_addr : unsigned(3 downto 0);
-- DMA Controller
signal dma_master_req : unsigned(DMA_NUM_CHANNEL-1 downto 0);
signal dma_master_gnt : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0');
signal dma_req_rdy : unsigned(DMA_NUM_CHANNEL-1 downto 0);
signal dma_req_en : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0');
signal dma_req_addr_auto_inc : unsigned(DMA_NUM_CHANNEL-1 downto 0);
type array32_t is array (0 to DMA_NUM_CHANNEL-1) of unsigned(31 downto 0);
signal dma_req_addr : array32_t;
signal dma_req_num_xfers : array32_t;
signal dma_req_complete : unsigned(DMA_NUM_CHANNEL-1 downto 0);
signal dma_req_complete_ack : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0');
signal dma_start : unsigned(DMA_NUM_CHANNEL-1 downto 0);
signal dma_active : unsigned(DMA_NUM_CHANNEL-1 downto 0);
signal dma_end : unsigned(DMA_NUM_CHANNEL-1 downto 0);
signal dma_bus_cmd_cycle_finished : unsigned(DMA_NUM_CHANNEL-1 downto 0);
signal dma_bus_cmd_cycle_en : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0');
signal dma_bus_cmd_rdy : unsigned(DMA_NUM_CHANNEL-1 downto 0);
signal dma_bus_cmd_we : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0');
type array_bus_cmd_t is array (0 to DMA_NUM_CHANNEL-1) of bm_cmd_t;
signal dma_bus_cmd : array_bus_cmd_t;
-- Busmaster arbiter
signal arb_idx : natural range 0 to DMA_NUM_CHANNEL-1;
-- BUS Master controller
signal bus_din_re : std_logic;
signal bus_cmd_cycle_finished : std_logic;
signal bus_cmd_cycle_en : std_logic := '0';
signal bus_cmd_rdy : std_logic;
signal bus_cmd_we : std_logic := '0';
signal bus_cmd : bm_cmd_t;
signal bus_din_rdy : std_logic;
signal bus_din_vld : std_logic := '0';
signal bus_din : unsigned(31 downto 0) := (others => '-');
signal bus_dout : unsigned(31 downto 0);
signal bus_dout_vld : std_logic;
signal bus_dout_re : std_logic := '0';
begin
mii_gtx_clk <= '0';
SRDY_O <= CYC_I and ready;
read <= STB_I and CYC_I and not WE_I;
write <= STB_I and CYC_I and WE_I;
rx_read_en_CPU <= read and ADDR_I(15);
tx_write_en_CPU <= write and ADDR_I(15);
reg_read <= read and not ADDR_I(15);
reg_write <= write and not ADDR_I(15);
reg_addr <= ADDR_I(5 downto 2);
ready <= not tx_ctrl_in.pkt_alloc_en;
tx_din_vld <= tx_write_en_CPU;
tx_din <= DAT_I;
rx_ctrl_in.pkt_free_en <= rx_free_en_CPU or dma_end(0);
rx_ctrl_in.pkt_req_en <= rx_req_en_CPU or dma_start(0);
rx_dout_re <= rx_read_en_CPU or (dma_active(DMA_CH_WRITE) and bus_din_rdy);
bus_din <= rx_dout;
bus_din_vld <= dma_active(DMA_CH_WRITE);
dma_master_gnt(0) <= SRDY_I;
dma_req_en(0) <= rx_ctrl_out.pkt_avail;
dma_req_num_xfers(0) <= X"0000" & "00" & rx_ctrl_out.rx_size(15 downto 2) when rx_ctrl_out.rx_size(1 downto 0) = "00" else X"0000" & "00" & rx_ctrl_out.rx_size(15 downto 2) + 1;
dma_req_addr(0) <= X"00000800";
dma_req_addr_auto_inc <= "11";
------------------------------------------------------------------
registers_write:
process(CLK_I)
begin
if rising_edge(CLK_I) then
tx_ctrl_in.pkt_alloc_en <= '0';
tx_ctrl_in.pkt_commit_en <= '0';
tx_ctrl_in.reset <= '0';
rx_free_en_CPU <= '0';
rx_req_en_CPU <= '0';
rx_ctrl_in.reset <= '0';
if RST_I = '1' then
rx_int_en <= '0';
tx_int_en <= '0';
tx_ctrl_in.tx_size <= (others => '0');
rx_ctrl_in.mac_addr <= (X"03", X"02", X"01", X"00", X"07", X"06");
rx_ctrl_in.promiscious <= '0';
tx_ctrl_in.Gbps_en <= '0';
rx_ctrl_in.Gbps_en <= '0';
tx_ctrl_in.fcs_gen_en <= '0';
rx_ctrl_in.fcs_chk_en <= '0';
elsif reg_write = '1' then
-- 0x0000 .. 0x003C
case reg_addr is
-- 0x0000
when "0000" =>
rx_ctrl_in.reset <= DAT_I(31);
rx_ctrl_in.Gbps_en <= DAT_I(30);
rx_ctrl_in.fcs_chk_en <= DAT_I(29);
rx_ctrl_in.promiscious <= DAT_I(23);
rx_req_en_CPU <= DAT_I(17);
rx_free_en_CPU <= DAT_I(16);
rx_int_en <= DAT_I(4);
-- 0x0004
-- rx_size R/O
-- 0x0008
when "0010" =>
tx_ctrl_in.reset <= DAT_I(31);
tx_ctrl_in.Gbps_en <= DAT_I(30);
tx_ctrl_in.fcs_gen_en <= DAT_I(29);
tx_ctrl_in.pkt_alloc_en <= DAT_I(17);
tx_ctrl_in.pkt_commit_en <= DAT_I(16);
tx_int_en <= DAT_I(4);
-- 0x000C
when "0011" =>
tx_ctrl_in.tx_size <= DAT_I(15 downto 0);
-- 0x0010
-- Gap
-- 0x0014
-- Gap
-- 0x0018
when "0110" =>
rx_ctrl_in.mac_addr(0) <= DAT_I(31 downto 24);
rx_ctrl_in.mac_addr(1) <= DAT_I(23 downto 16);
rx_ctrl_in.mac_addr(2) <= DAT_I(15 downto 8);
rx_ctrl_in.mac_addr(3) <= DAT_I(7 downto 0);
-- 0x001C
when "0111" =>
rx_ctrl_in.mac_addr(4) <= DAT_I(31 downto 24);
rx_ctrl_in.mac_addr(5) <= DAT_I(23 downto 16);
-- 0x0020 .. 0x003C
-- Gap
when others => null;
end case;
end if;
end if;
end process;
registers_read:
process(CLK_I)
begin
if rising_edge(CLK_I) then
ACK_O <= rx_read_en_CPU;
DAT_O <= rx_dout;
if reg_read = '1' then
-- 0x0000 .. 0x003C
case reg_addr is
-- 0x0000
when "0000" =>
ACK_O <= ready;
DAT_O <= (others => '0');
DAT_O(31) <= rx_ctrl_out.reset_busy;
DAT_O(30) <= rx_ctrl_in.Gbps_en;
DAT_O(29) <= rx_ctrl_in.fcs_chk_en;
DAT_O(23) <= rx_ctrl_in.promiscious;
DAT_O(19) <= rx_ctrl_out.pkt_bcast;
DAT_O(18) <= rx_ctrl_out.pkt_mac_match;
DAT_O(17) <= rx_ctrl_out.pkt_valid;
DAT_O(16) <= rx_ctrl_out.pkt_avail;
DAT_O(4) <= rx_int_en;
-- 0x0004
when "0001" =>
ACK_O <= '1';
DAT_O <= X"0000" & rx_ctrl_out.rx_size;
-- 0x0008
when "0010" =>
ACK_O <= ready;
DAT_O <= (others => '0');
DAT_O(31) <= tx_ctrl_out.reset_busy;
DAT_O(30) <= tx_ctrl_in.Gbps_en;
DAT_O(29) <= tx_ctrl_in.fcs_gen_en;
DAT_O(24) <= tx_ctrl_out.pkt_done;
DAT_O(17) <= tx_ctrl_out.pkt_alloc_req;
DAT_O(16) <= tx_ctrl_out.pkt_armed;
DAT_O(4) <= tx_int_en;
-- 0x000C
when "0011" =>
ACK_O <= '1';
DAT_O <= X"0000" & tx_ctrl_out.tx_size;
-- 0x0010
-- Gap
-- 0x0014
-- Gap
-- 0x0018
when "0110" =>
ACK_O <= '1';
DAT_O <= rx_ctrl_in.mac_addr(0) & rx_ctrl_in.mac_addr(1) & rx_ctrl_in.mac_addr(2) & rx_ctrl_in.mac_addr(3);
-- 0x001C
when "0111" =>
ACK_O <= '1';
DAT_O <= rx_ctrl_in.mac_addr(4) & rx_ctrl_in.mac_addr(5) & X"0000";
-- 0x0020 .. 0x003C
-- Gap
when others => null;
end case;
end if;
end if;
end process;
irq_register:
process(CLK_I)
begin
if rising_edge(CLK_I) then
INT_O <= irq_rx or irq_tx;
irq_tx <= tx_int_en and tx_ctrl_out.pkt_done;
irq_rx <= rx_int_en and rx_ctrl_out.pkt_avail;
end if;
end process;
inst_emac_rx : entity work.emac_rx
GENERIC MAP
(
f_sysclk => f_sysclk,
RAM_SIZE => RX_RAM_SIZE
)
PORT MAP
(
clk => CLK_I,
rst => RST_I,
dout_re => rx_dout_re,
dout => rx_dout,
ctrl_in => rx_ctrl_in,
ctrl_out => rx_ctrl_out,
mii_rx_clk => mii_rx_clk,
mii_rx_dv => mii_rx_dv,
mii_rx_er => mii_rx_er,
mii_rx => mii_rx,
mii_crs => mii_crs,
mii_col => mii_col
);
inst_emac_tx : entity work.emac_tx
GENERIC MAP
(
f_sysclk => f_sysclk,
RAM_SIZE => TX_RAM_SIZE
)
PORT MAP
(
clk => CLK_I,
rst => RST_I,
din_vld => tx_din_vld,
din => tx_din,
ctrl_in => tx_ctrl_in,
ctrl_out => tx_ctrl_out,
mii_tx_clk => mii_tx_clk,
mii_tx_en => mii_tx_en,
mii_tx_er => mii_tx_er,
mii_tx => mii_tx
);
gen_dmac:
for i in 0 to DMA_NUM_CHANNEL-1 generate
dma_bus_cmd_cycle_finished(i) <= bus_cmd_cycle_finished;
dma_bus_cmd_rdy(i) <= bus_cmd_rdy;
inst_dmac : entity work.dmac
Generic map
(
DATA_WIDTH => 32,
XFER_CHUNK_SIZE => 32
)
Port map
(
clk => CLK_I,
rst => RST_I,
master_req => dma_master_req(i),
master_gnt => dma_master_gnt(i),
req_rdy => dma_req_rdy(i),
req_en => dma_req_en(i),
req_rw => DMA_RW_CONF(i),
req_addr_auto_inc => dma_req_addr_auto_inc(i),
req_addr_start => dma_req_addr(i),
req_num_xfers => dma_req_num_xfers(i),
req_complete => dma_req_complete(i),
req_complete_ack => dma_req_complete_ack(i),
dma_start => dma_start(i),
dma_active => dma_active(i),
dma_end => dma_end(i),
-- busmaster control
bus_cyc_complete => dma_bus_cmd_cycle_finished(i),
bus_cmd_rdy => dma_bus_cmd_rdy(i),
bus_cmd_we => dma_bus_cmd_we(i),
bus_cmd_cycle_en => dma_bus_cmd_cycle_en(i),
-- busmaster command
bus_cmd_out => dma_bus_cmd(i)
);
end generate;
inst_busmaster_sync : entity work.busmaster_sync
GENERIC MAP
(
DATA_WIDTH => 32,
FIFO_DEPTH => 4
)
PORT MAP
(
-- System signals
rst => RST_I,
clk => CLK_I,
cmd_cycle_finished => bus_cmd_cycle_finished,
cmd_cycle_en => bus_cmd_cycle_en,
cmd_rdy => bus_cmd_rdy,
cmd_we => bus_cmd_we,
cmd_in => bus_cmd,
din_rdy => bus_din_rdy,
din_we => bus_din_vld,
din => bus_din,
dout => bus_dout,
dout_vld => bus_dout_vld,
dout_re => bus_dout_re,
-- JBUS Master signals
CYC_O => CYC_O,
STB_O => STB_O,
WE_O => WE_O,
SEL_O => SEL_O,
ACK_I => ACK_I,
SRDY_I => SRDY_I,
MRDY_O => MRDY_O,
ADDR_O => ADDR_O,
MDAT_I => MDAT_I,
MDAT_O => MDAT_O
);
arbiter_proc:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if RST_I = '1' then
dma_master_gnt <= (others => '0');
arb_idx <= 0;
elsif dma_master_req(arb_idx) = '0' then
if arb_idx /= DMA_NUM_CHANNEL-1 then
arb_idx <= arb_idx + 1;
else
arb_idx <= 0;
end if;
else
dma_master_gnt <= (others => '0');
dma_master_gnt(arb_idx) <= '1';
end if;
end if;
end process;
arbiter_mux:
process(dma_master_gnt, dma_bus_cmd, dma_bus_cmd_we, dma_bus_cmd_cycle_en)
variable v_bus_cmd_we : std_logic;
variable v_bus_cmd_cycle_en : std_logic;
begin
v_bus_cmd_we := '0';
v_bus_cmd_cycle_en := '0';
for i in 0 to DMA_NUM_CHANNEL-1 loop
v_bus_cmd_we := v_bus_cmd_we or dma_bus_cmd_we(i);
v_bus_cmd_cycle_en := v_bus_cmd_cycle_en or dma_bus_cmd_cycle_en(i);
if dma_master_gnt(i) = '1' then
bus_cmd <= dma_bus_cmd(i);
end if;
end loop;
bus_cmd_we <= v_bus_cmd_we;
bus_cmd_cycle_en <= v_bus_cmd_cycle_en;
end process;
end behavior;
-751
View File
@@ -1,751 +0,0 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
use std.textio.all; -- Imports the standard textio package.
use work.emac_types.all;
use work.utils_pkg.all;
ENTITY emac_tx IS
Generic
(
f_sysclk : real := 100.0;
RAM_SIZE : natural := 2048
);
Port
(
clk : in STD_LOGIC;
rst : in STD_LOGIC;
din_vld : in STD_LOGIC;
din : in unsigned(31 downto 0);
ctrl_in : in tx_ctrl_in_t;
ctrl_out : out tx_ctrl_out_t;
mii_tx_clk : in STD_LOGIC;
mii_tx_en : out STD_LOGIC;
mii_tx_er : out STD_LOGIC;
mii_tx : out unsigned(7 downto 0)
);
END emac_tx;
ARCHITECTURE behavior OF emac_tx IS
constant RAM_ADDR_WIDTH : natural := NextExpBaseTwo(RAM_SIZE);
subtype word_ptr_t is unsigned(RAM_ADDR_WIDTH-1 downto 0);
signal cmd_fifo_din : unsigned(2*word_ptr_t'length-1 downto 0);
signal cmd_fifo_dout : unsigned(2*word_ptr_t'length-1 downto 0);
signal cmd_fifo_we : std_logic;
signal cmd_fifo_re : std_logic;
signal cmd_fifo_empty : std_logic;
signal cmd_fifo_full : std_logic;
signal reset_en : std_logic;
signal fill_base : word_ptr_t;
signal fill_size : word_ptr_t;
signal fill_cnt : word_ptr_t;
signal fill_ptr : word_ptr_t;
signal fill_pre_rdy : std_logic;
signal fill_bsy : std_logic;
signal fill_remain : unsigned(1 downto 0);
signal fill_set : std_logic;
signal fill_en : std_logic;
signal fill_cnt_en : std_logic;
signal alloc_OK : std_logic;
signal alloc_req : std_logic;
signal alloc_ack : std_logic;
signal alloc_size : word_ptr_t;
signal alloc_remain : unsigned(1 downto 0);
signal commit_en : std_logic;
signal uncommit_en : std_logic;
signal mem_alloc_en : std_logic;
signal mem_free_en : std_logic;
signal nwords_free : word_ptr_t;
signal mem_free_req : std_logic;
signal mem_free_ack : unsigned(1 downto 0);
signal xfer_size : word_ptr_t;
signal xfer_ptr : word_ptr_t;
signal xfer_cnt : word_ptr_t;
signal xfer_set : std_logic;
signal xfer_en : std_logic;
signal xfer_cnt_en : std_logic;
signal xfer_bsy : std_logic;
signal xfer_free_en : std_logic;
signal ram_en_a : std_logic;
signal ram_we_a : std_logic;
signal ram_addr_a : word_ptr_t;
signal ram_din_a : unsigned(35 downto 0);
signal ram_en_b : std_logic;
signal ram_addr_b : word_ptr_t;
signal ram_dout_b : unsigned(35 downto 0);
signal piso32_din : unsigned(31 downto 0);
signal piso32_din_be : unsigned(3 downto 0);
signal piso32_din_rdy : std_logic;
signal piso32_din_vld : std_logic;
signal piso32_dout : unsigned(7 downto 0);
signal piso32_dout_vld : std_logic;
signal piso32_dout_en : std_logic;
signal piso8_dout_vld : std_logic;
signal piso8_din_rdy : std_logic;
signal piso8_din_vld : std_logic;
signal piso8_dout : unsigned(3 downto 0);
signal piso8_din : unsigned(7 downto 0);
signal reset_pipe : unsigned(31 downto 0);
signal Gbps_en : std_logic;
signal fcs_gen_en : std_logic;
signal fcs_inject_en : std_logic;
signal fcs_rst : std_logic;
signal fcs_en : unsigned(7 downto 0);
signal fcs_vld : std_logic;
signal fcs_din_vld : std_logic;
signal fcs : unsigned(31 downto 0);
signal fcs_rev_endian : unsigned(31 downto 0);
signal mii_fifo_we : std_logic;
signal mii_fifo_re : std_logic;
signal mii_fifo_full : std_logic;
signal mii_fifo_empty : std_logic;
signal mii_fifo_re_dly : unsigned(23 downto 0);
signal mii_bsy : std_logic;
type host_state_t is (host_init, host_idle, host_alloc, host_setup, host_arm, host_fill, host_commit);
signal host_s, host_sn : host_state_t;
type xfer_state_t is (xfer_init, xfer_idle, xfer_start, xfer_preamble0, xfer_preamble1, xfer_active, xfer_crc, xfer_stop, xfer_finish);
signal xfer_s, xfer_sn : xfer_state_t;
type piso_byte_mask_array_t is array (0 to 3) of unsigned (3 downto 0);
constant piso_byte_mask_rom : piso_byte_mask_array_t :=
(
"1111",
"1000",
"1100",
"1110"
);
signal preamble_en : std_logic;
signal preamble_addr : natural range 0 to 1;
type preamble_t is array (0 to 1) of unsigned(31 downto 0);
constant preamble : preamble_t :=
(
X"55555555",
X"555555D5"
);
begin
ctrl_out.pkt_alloc_req <= alloc_req;
ctrl_out.pkt_done <= cmd_fifo_empty;
ctrl_out.reset_busy <= reset_en;
ram_en_a <= din_vld;
ram_we_a <= fill_bsy;
ram_din_a(31 downto 0) <= din;
ram_din_a(35 downto 32) <= piso_byte_mask_rom(to_integer(fill_remain)) when fill_pre_rdy = '1' else "1111";
ram_addr_a <= fill_ptr;
piso32_din <= preamble(preamble_addr) when preamble_en = '1' else fcs_rev_endian when fcs_inject_en = '1' else ram_dout_b(31 downto 0);
piso32_din_be <= "1111" when (preamble_en = '1' or fcs_inject_en = '1') else ram_dout_b(35 downto 32);
cmd_fifo_we <= commit_en;
cmd_fifo_re <= uncommit_en;
cmd_fifo_din <= fill_size & fill_base;
ram_en_b <= piso32_din_rdy;
ram_addr_b <= xfer_ptr;
reset_en <= reset_pipe(reset_pipe'left);
xfer_cnt_en <= xfer_bsy and piso32_din_rdy;
fill_cnt_en <= fill_bsy and din_vld;
mem_free_en <= not mem_free_ack(0) and mem_free_ack(1);
fcs_rev_endian <= fcs(7 downto 0) & fcs(15 downto 8) & fcs(23 downto 16) & fcs(31 downto 24);
------------------------------------------------------------------
reset_gen:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' or ctrl_in.reset = '1' then
reset_pipe <= (others => '1');
else
reset_pipe <= reset_pipe(reset_pipe'left-1 downto 0) & '0';
end if;
end if;
end process;
------------------------------------------------------------------
host_state_next:
process(clk)
begin
if rising_edge(clk) then
if reset_en = '1' then
host_s <= host_init;
else
host_s <= host_sn;
end if;
end if;
end process;
host_state:
process(host_s, alloc_OK, fill_bsy, ctrl_in.pkt_commit_en, alloc_req, mem_free_ack)
begin
fill_set <= '0';
fill_en <= '0';
commit_en <= '0';
alloc_ack <= '0';
mem_alloc_en <= '0';
host_sn <= host_s;
case host_s is
when host_init =>
host_sn <= host_idle;
when host_idle =>
if alloc_req = '1' then
host_sn <= host_alloc;
end if;
when host_alloc =>
if alloc_OK = '1' then
host_sn <= host_setup;
else
host_sn <= host_idle;
alloc_ack <= '1';
end if;
when host_setup =>
fill_set <= '1';
host_sn <= host_arm;
when host_arm =>
fill_en <= '1';
alloc_ack <= '1';
host_sn <= host_fill;
when host_fill =>
fill_en <= '1';
if alloc_req = '1' then
host_sn <= host_alloc;
elsif ctrl_in.pkt_commit_en = '1' then
host_sn <= host_commit;
end if;
when host_commit =>
if mem_free_ack = "00" then
commit_en <= '1';
mem_alloc_en <= '1';
host_sn <= host_idle;
end if;
when others =>
host_sn <= host_idle;
end case;
end process;
------------------------------------------------------------------
-- Allocation stuff
------------------------------------------------------------------
alloc_request_logic:
process(clk)
begin
if rising_edge(clk) then
if reset_en = '1' then
alloc_req <= '0';
elsif ctrl_in.pkt_alloc_en = '1' and alloc_req = '0' then
alloc_req <= '1';
alloc_remain <= ctrl_in.tx_size(1 downto 0);
alloc_size <= ctrl_in.tx_size(word_ptr_t'left+2 downto 2);
if ctrl_in.tx_size(1 downto 0) /= "00" then
alloc_size <= ctrl_in.tx_size(word_ptr_t'left+2 downto 2) + 1;
end if;
ctrl_out.tx_size <= resize(ctrl_in.tx_size(word_ptr_t'left downto 0), 16);
elsif alloc_ack = '1' then
alloc_req <= '0';
end if;
end if;
end process;
------------------------------------------------------------------
host_alloc_armed_register:
process(clk)
begin
if rising_edge(clk) then
if reset_en = '1' or commit_en = '1' then
ctrl_out.pkt_armed <= '0';
elsif alloc_ack = '1' then
ctrl_out.pkt_armed <= alloc_OK;
end if;
end if;
end process;
------------------------------------------------------------------
alloc_eval_logic:
process(clk)
begin
if rising_edge(clk) then
alloc_OK <= '0';
if alloc_size < nwords_free then
alloc_OK <= '1';
end if;
end if;
end process;
------------------------------------------------------------------
fill_base_logic:
process(clk)
begin
if rising_edge(clk) then
if reset_en = '1' then
fill_base <= (others => '0');
elsif commit_en = '1' then
fill_base <= fill_ptr;
end if;
end if;
end process;
------------------------------------------------------------------
mem_free_counter:
process(clk)
begin
if rising_edge(clk) then
if reset_en = '1' then
nwords_free <= (others => '1');
elsif mem_alloc_en = '1' then
nwords_free <= nwords_free - fill_size;
elsif mem_free_en = '1' then
nwords_free <= nwords_free + xfer_size;
end if;
end if;
end process;
------------------------------------------------------------------
mem_free_mii:
process(mii_tx_clk)
begin
if rising_edge(mii_tx_clk) then
if reset_en = '1' then
mem_free_req <= '0';
elsif mem_free_ack(0) = '0' then
if xfer_free_en = '1' then
mem_free_req <= '1';
end if;
else
mem_free_req <= '0';
end if;
end if;
end process;
------------------------------------------------------------------
mem_free_host:
process(clk)
begin
if rising_edge(clk) then
mem_free_ack(1) <= mem_free_ack(0);
if reset_en = '1' then
mem_free_ack <= "00";
elsif mem_free_req = '1' then
if mem_alloc_en = '0' then
mem_free_ack(0) <= '1';
end if;
else
mem_free_ack(0) <= '0';
end if;
end if;
end process;
------------------------------------------------------------------
-- Fill stuff
------------------------------------------------------------------
fill_counter:
process(clk)
begin
if rising_edge(clk) then
if fill_set = '1' then
fill_bsy <= '0';
fill_pre_rdy <= '0';
fill_cnt <= alloc_size;
fill_size <= alloc_size;
fill_remain <= alloc_remain;
elsif fill_en = '1' then
fill_bsy <= '1';
if fill_cnt_en = '1' or fill_bsy = '0' then
if fill_cnt /= 1 then
fill_cnt <= fill_cnt - 1;
else
fill_pre_rdy <= '1';
end if;
if fill_pre_rdy = '1' then
fill_bsy <= '0';
end if;
end if;
end if;
end if;
end process;
------------------------------------------------------------------
fill_pointer:
process(clk)
begin
if rising_edge(clk) then
if fill_set = '1' then
fill_ptr <= fill_base;
elsif fill_cnt_en = '1' then
fill_ptr <= fill_ptr + 1;
end if;
end if;
end process;
------------------------------------------------------------------
-- Transfer stuff
------------------------------------------------------------------
host2xfer_sync_register:
process(mii_tx_clk)
begin
if rising_edge(mii_tx_clk) then
Gbps_en <= ctrl_in.Gbps_en;
fcs_gen_en <= ctrl_in.fcs_gen_en;
end if;
end process;
------------------------------------------------------------------
xfer_counter:
process(mii_tx_clk)
begin
if rising_edge(mii_tx_clk) then
xfer_bsy <= '0';
if xfer_set = '1' then
xfer_cnt <= cmd_fifo_dout(cmd_fifo_dout'left downto word_ptr_t'length);
xfer_size <= (others => '0');
elsif xfer_en = '1' then
xfer_bsy <= '1';
if xfer_cnt_en = '1' or xfer_bsy = '0' then
if xfer_cnt /= 0 then
xfer_cnt <= xfer_cnt - 1;
xfer_size <= xfer_size + 1;
else
xfer_bsy <= '0';
end if;
end if;
end if;
end if;
end process;
------------------------------------------------------------------
xfer_pointer:
process(mii_tx_clk)
begin
if rising_edge(mii_tx_clk) then
if xfer_set = '1' then
xfer_ptr <= cmd_fifo_dout(xfer_ptr'left downto 0);
elsif xfer_en = '1' then
if xfer_bsy = '0' or xfer_cnt_en = '1' then
xfer_ptr <= xfer_ptr + 1;
end if;
end if;
end if;
end process;
------------------------------------------------------------------
xfer_state_next:
process(mii_tx_clk)
begin
if rising_edge(mii_tx_clk) then
if reset_en = '1' then
xfer_s <= xfer_init;
else
xfer_s <= xfer_sn;
end if;
end if;
end process;
xfer_state:
process(xfer_s, mii_bsy, cmd_fifo_empty, piso32_din_rdy, piso32_dout_vld, xfer_bsy, fcs_gen_en)
begin
piso32_din_vld <= '0';
preamble_en <= '0';
preamble_addr <= 0;
xfer_set <= '0';
xfer_en <= '0';
xfer_free_en <= '0';
fcs_rst <= '0';
fcs_inject_en <= '0';
uncommit_en <= '0';
xfer_sn <= xfer_s;
case xfer_s is
when xfer_init =>
xfer_sn <= xfer_idle;
when xfer_idle =>
if cmd_fifo_empty = '0' and mii_bsy = '0' then
xfer_sn <= xfer_start;
end if;
when xfer_start =>
if cmd_fifo_empty = '0' then
xfer_sn <= xfer_preamble0;
end if;
when xfer_preamble0 =>
xfer_set <= '1';
fcs_rst <= '1';
preamble_addr <= 0;
preamble_en <= '1';
piso32_din_vld <= '1';
if piso32_din_rdy = '1' then
xfer_sn <= xfer_preamble1;
end if;
when xfer_preamble1 =>
preamble_addr <= 1;
preamble_en <= '1';
piso32_din_vld <= '1';
if piso32_din_rdy = '1' then
xfer_sn <= xfer_active;
xfer_en <= '1';
end if;
when xfer_active =>
piso32_din_vld <= xfer_bsy;
xfer_en <= '1';
if xfer_bsy = '0' then
xfer_sn <= xfer_stop;
end if;
when xfer_stop =>
if piso32_dout_vld = '0' then
xfer_sn <= xfer_finish;
if fcs_gen_en = '1' then
xfer_sn <= xfer_crc;
end if;
end if;
when xfer_crc =>
fcs_inject_en <= piso32_din_rdy;
piso32_din_vld <= '1';
if piso32_din_rdy = '1' then
xfer_sn <= xfer_finish;
end if;
when xfer_finish =>
uncommit_en <= '1';
xfer_free_en <= '1';
xfer_sn <= xfer_idle;
when others =>
xfer_sn <= xfer_idle;
end case;
end process;
------------------------------------------------------------------
inst_ram : entity work.dpram_1w1r2c_ro
GENERIC MAP
(
addr_width => RAM_ADDR_WIDTH,
data_width => ram_din_a'length
)
PORT MAP
(
clk_a => clk,
clk_b => mii_tx_clk,
en_a => ram_en_a,
en_b => ram_en_b,
we_a => ram_we_a,
addr_a => ram_addr_a,
addr_b => ram_addr_b,
din_a => ram_din_a,
dout_b => ram_dout_b
);
------------------------------------------------------------------
-- Instantiate synchronous FIFO
inst_cmd_fifo: entity work.fifo_async
GENERIC MAP
(
addr_width => NextExpBaseTwo(RAM_SIZE) - 4, -- RAMSIZE(words)/MIN_PACKET_LEN(words)
data_width => cmd_fifo_din'length,
do_last_read_update => true
)
PORT MAP
(
rst => reset_en,
clk_w => clk,
clk_r => mii_tx_clk,
we => cmd_fifo_we,
re => cmd_fifo_re,
fifo_full => cmd_fifo_full,
fifo_empty => cmd_fifo_empty,
fifo_afull => open,
fifo_aempty => open,
data_w => cmd_fifo_din,
data_r => cmd_fifo_dout
);
------------------------------------------------------------------
inst_piso32 : entity work.piso
GENERIC MAP
(
data_width_in => 32,
data_width_out => 8,
msb_first => true
)
PORT MAP
(
rst => reset_en,
clk => mii_tx_clk,
din_vld => piso32_din_vld,
din_rdy => piso32_din_rdy,
din_be => piso32_din_be,
din => piso32_din,
dout_vld => piso32_dout_vld,
dout_en => piso32_dout_en,
dout => piso32_dout
);
piso32_dout_en <= not mii_fifo_full; --'1' when Gbps_en = '1' else piso8_din_rdy;
------------------------------------------------------------------
fcs_enable_gen:
process(mii_tx_clk)
begin
if rising_edge(mii_tx_clk) then
if fcs_rst = '1' then
fcs_en <= (others => '0');
elsif piso32_dout_vld = '1' then
fcs_en <= fcs_en(fcs_en'left-1 downto 0) & '1';
end if;
end if;
end process;
------------------------------------------------------------------
inst_fcs: entity work.crc32
GENERIC MAP
(
crc32_init => X"00000000"
)
PORT MAP
(
rst => fcs_rst,
clk => mii_tx_clk,
din_vld => fcs_din_vld,
din => piso32_dout,
crc32_vld => fcs_vld,
crc32_out => fcs
);
fcs_din_vld <= fcs_en(fcs_en'left) and piso32_dout_vld and piso32_dout_en;
------------------------------------------------------------------
-- ensures continous MII-data stream and also acts as Inter Frame Gap delay
mii_fifo_re_dly_gen:
process(mii_tx_clk)
begin
if rising_edge(mii_tx_clk) then
if mii_fifo_empty = '1' then
if Gbps_en = '0' then
mii_fifo_re_dly <= X"000000"; -- 100 mbps
else
mii_fifo_re_dly <= X"000FFF"; -- Gigabit
end if;
else
mii_fifo_re_dly <= mii_fifo_re_dly(mii_fifo_re_dly'left-1 downto 0) & not mii_fifo_empty;
end if;
end if;
end process;
mii_bsy <= mii_fifo_re_dly(mii_fifo_re_dly'left);
------------------------------------------------------------------
-- Instantiate synchronous FIFO
inst_mii_fifo: entity work.fifo_sync
GENERIC MAP
(
addr_width => 4,
data_width => piso32_dout'length,
do_last_read_update => true
)
PORT MAP
(
rst => reset_en,
clk => mii_tx_clk,
we => mii_fifo_we,
re => mii_fifo_re,
fifo_full => mii_fifo_full,
fifo_empty => mii_fifo_empty,
fifo_afull => open,
fifo_aempty => open,
data_w => piso32_dout,
data_r => piso8_din
);
mii_fifo_re <= mii_bsy when Gbps_en = '1' else (piso8_din_rdy and mii_bsy);
mii_fifo_we <= piso32_dout_vld;
------------------------------------------------------------------
inst_piso8 : entity work.piso
GENERIC MAP
(
data_width_in => 8,
data_width_out => 4,
msb_first => false
)
PORT MAP
(
rst => reset_en,
clk => mii_tx_clk,
din_vld => piso8_din_vld,
din_rdy => piso8_din_rdy,
din_be => "11",
din => piso8_din,
dout_vld => piso8_dout_vld,
dout_en => '1',
dout => piso8_dout
);
piso8_din_vld <= not mii_fifo_empty and mii_bsy;
------------------------------------------------------------------
mii_output_register:
process(mii_tx_clk)
begin
if rising_edge(mii_tx_clk) then
mii_tx_er <= '0';
if Gbps_en = '1' then
mii_tx_en <= piso8_din_vld;
mii_tx <= piso8_din;
else
mii_tx_en <= piso8_dout_vld;
mii_tx <= "0000" & piso8_dout;
end if;
end if;
end process;
------------------------------------------------------------------
end behavior;
-63
View File
@@ -1,63 +0,0 @@
-- Package File Template
--
-- Purpose: This package defines supplemental types, subtypes,
-- constants, and functions
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
package emac_types is
-- Constants
type mac_addr_t is array (0 to 5) of unsigned (7 downto 0);
-- Types
type tx_ctrl_in_t is record
Gbps_en : std_logic;
reset : std_logic;
fcs_gen_en : std_logic;
tx_size : unsigned(15 downto 0);
pkt_commit_en : std_logic;
pkt_alloc_en : std_logic;
end record;
type tx_ctrl_out_t is record
tx_size : unsigned(15 downto 0);
pkt_done : std_logic;
pkt_alloc_req : std_logic;
pkt_armed : std_logic;
reset_busy : std_logic;
end record;
type rx_ctrl_in_t is record
Gbps_en : std_logic;
reset : std_logic;
fcs_chk_en : std_logic;
pkt_req_en : std_logic;
pkt_free_en : std_logic;
mac_addr : mac_addr_t;
promiscious : std_logic;
end record;
type rx_ctrl_out_t is record
pkt_avail : std_logic;
pkt_valid : std_logic;
pkt_bcast : std_logic;
pkt_mac_match : std_logic;
rx_size : unsigned(15 downto 0);
reset_busy : std_logic;
end record;
-- Functions
end emac_types;
package body emac_types is
end emac_types;
-124
View File
@@ -1,124 +0,0 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
use std.textio.all; -- Imports the standard textio package.
use work.utils_pkg.all; -- Imports the standard textio package.
ENTITY piso IS
Generic
(
data_width_in : natural := 32;
data_width_out : natural := 8;
msb_first : boolean := false
);
Port
(
rst : in STD_LOGIC;
clk : in STD_LOGIC;
din_vld : in STD_LOGIC;
din_rdy : out STD_LOGIC;
din_be : in unsigned(data_width_in/data_width_out-1 downto 0);
din : in unsigned(data_width_in-1 downto 0);
dout_vld : out STD_LOGIC;
dout_en : in STD_LOGIC;
dout : out unsigned(data_width_out-1 downto 0)
);
END piso;
ARCHITECTURE behavior OF piso IS
constant num_shifts : natural := data_width_in/data_width_out;
signal pre_fin : STD_LOGIC;
signal shift_cnt_pipe : unsigned(num_shifts-1 downto 0);
signal shift_pipe : unsigned(data_width_in-1 downto 0);
signal vld_pipe : unsigned(num_shifts-1 downto 0);
signal din_reg : unsigned(data_width_in-1 downto 0);
signal din_be_reg : unsigned(num_shifts-1 downto 0);
signal din_reg_empty : STD_LOGIC;
--------------------------------------------------------------------------
begin
pre_fin <= shift_cnt_pipe(shift_cnt_pipe'left-1);
din_rdy <= din_reg_empty;
dout_vld <= vld_pipe(vld_pipe'left) when msb_first else vld_pipe(0);
dout <= shift_pipe(shift_pipe'left downto shift_pipe'left-data_width_out+1) when msb_first
else shift_pipe(data_width_out-1 downto 0);
--------------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
din_reg_empty <= '1';
elsif din_reg_empty = '1' then
if din_vld = '1' then
din_reg_empty <= '0';
end if;
elsif pre_fin = '1' and dout_en = '1' then
din_reg_empty <= '1';
end if;
end if;
end process;
process(clk)
begin
if rising_edge(clk) then
if din_vld = '1' and din_reg_empty = '1' then
din_reg <= din;
din_be_reg <= din_be;
end if;
end if;
end process;
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
shift_cnt_pipe <= (others => '1');
elsif (pre_fin = '1' and dout_en = '1' and din_reg_empty = '0') then
shift_cnt_pipe <= (others => '0');
elsif dout_en = '1' then
shift_cnt_pipe <= shift_cnt_pipe(shift_cnt_pipe'left-1 downto 0) & '1';
end if;
end if;
end process;
--------------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if (pre_fin = '1' and dout_en = '1' and din_reg_empty = '0') then
shift_pipe <= din_reg;
elsif dout_en = '1' then
if (msb_first) then
shift_pipe <= shift_pipe(shift_pipe'left-data_width_out downto 0) & (data_width_out-1 downto 0 => '0');
else
shift_pipe <= (data_width_out-1 downto 0 => '0') & shift_pipe(shift_pipe'left downto data_width_out);
end if;
end if;
end if;
end process;
--------------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
vld_pipe <= (others => '0');
elsif (pre_fin = '1' and dout_en = '1' and din_reg_empty = '0') then
vld_pipe <= din_be_reg;
elsif dout_en = '1' then
if (msb_first) then
vld_pipe <= vld_pipe(vld_pipe'left-1 downto 0) & '0';
else
vld_pipe <= '0' & vld_pipe(vld_pipe'left downto 1);
end if;
end if;
end if;
end process;
--------------------------------------------------------------------------
end behavior;
-230
View File
@@ -1,230 +0,0 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE IEEE.MATH_REAL.ALL;
use std.textio.all; -- Imports the standard textio package.
use work.emac_types.all;
use work.utils_pkg.all;
ENTITY pkt_gen IS
Generic
(
f_sysclk : real := 100.0;
TX_RAM_SIZE : natural := 2048;
PKT_SIZE_MIN : natural := 64;
PKT_SIZE_MAX : natural := 1518
);
Port
(
clk : in STD_LOGIC;
rst : in STD_LOGIC;
en : in STD_LOGIC;
gigabit_en : in STD_LOGIC;
fcs_gen_en : in STD_LOGIC;
mii_tx_clk : in STD_LOGIC;
mii_tx_en : out STD_LOGIC;
mii_tx_er : out STD_LOGIC;
mii_tx : out unsigned(7 downto 0)
);
END pkt_gen;
ARCHITECTURE behavior OF pkt_gen IS
subtype word_ptr_t is unsigned(15 downto 0);
signal pkt_data : unsigned(31 downto 0);
signal pkt_nbytes : word_ptr_t := X"0040";
signal pkt_nwords : word_ptr_t := X"0010";
signal fill_size : word_ptr_t;
signal fill_cnt : word_ptr_t;
signal fill_rdy : std_logic;
signal fill_set : std_logic;
signal fill_en : std_logic;
signal tx_packets : natural;
signal tx_bytes : natural;
signal tx_ctrl_in : tx_ctrl_in_t;
signal tx_ctrl_out : tx_ctrl_out_t;
signal tx_din : unsigned(31 downto 0);
signal tx_din_vld : std_logic;
type host_state_t is (host_init, host_idle, host_alloc, host_setup, host_arm, host_fill, host_commit);
signal host_s, host_sn : host_state_t;
begin
------------------------------------------------------------------
host_state_next:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
host_s <= host_init;
else
host_s <= host_sn;
end if;
end if;
end process;
host_state:
process(host_s, tx_ctrl_out, pkt_nbytes, fill_rdy, en, gigabit_en, fcs_gen_en)
begin
tx_ctrl_in.pkt_alloc_en <= '0';
tx_ctrl_in.pkt_commit_en <= '0';
tx_ctrl_in.reset <= '0';
tx_ctrl_in.Gbps_en <= gigabit_en;
tx_ctrl_in.fcs_gen_en <= fcs_gen_en;
tx_ctrl_in.tx_size <= pkt_nbytes;
fill_set <= '0';
fill_en <= '0';
host_sn <= host_s;
case host_s is
when host_init =>
if tx_ctrl_out.reset_busy = '0' then
host_sn <= host_idle;
end if;
when host_idle =>
if tx_ctrl_out.pkt_alloc_req = '0' and en = '1' then
tx_ctrl_in.pkt_alloc_en <= '1';
host_sn <= host_alloc;
end if;
when host_alloc =>
if tx_ctrl_out.pkt_alloc_req = '0' then
if tx_ctrl_out.pkt_armed = '1' then
host_sn <= host_setup;
else
host_sn <= host_idle;
end if;
end if;
when host_setup =>
fill_set <= '1';
host_sn <= host_fill;
when host_fill =>
fill_en <= '1';
if fill_rdy = '1' then
host_sn <= host_commit;
end if;
when host_commit =>
tx_ctrl_in.pkt_commit_en <= '1';
host_sn <= host_idle;
when others =>
host_sn <= host_idle;
end case;
end process;
------------------------------------------------------------------
pkt_generator:
process(clk)
variable size : word_ptr_t;
variable krand : real;
variable seed1 : integer;
variable seed2 : integer;
begin
if rising_edge(clk) then
if rst = '1' then
size := to_unsigned(PKT_SIZE_MIN, word_ptr_t'length);
seed1 := 31101970;
seed2 := 12586901;
tx_packets <= 0;
tx_bytes <= 0;
elsif tx_ctrl_in.pkt_commit_en = '1' then
uniform(seed1, seed2, krand);
size := to_unsigned(PKT_SIZE_MIN + natural(real(PKT_SIZE_MAX-PKT_SIZE_MIN)*krand), word_ptr_t'length);
tx_packets <= tx_packets + 1;
tx_bytes <= tx_bytes + to_integer(pkt_nbytes);
end if;
pkt_nbytes <= size;
if size(1 downto 0) = 0 then
pkt_nwords <= "00" & size(word_ptr_t'left downto 2);
else
pkt_nwords <= "00" & size(word_ptr_t'left downto 2) + 1;
end if;
end if;
end process;
------------------------------------------------------------------
pkt_data_gen:
process(clk)
variable data : unsigned(7 downto 0);
begin
if rising_edge(clk) then
tx_din_vld <= fill_en;
if fill_set = '1' then
data := X"00";
tx_din <= X"03020100";
elsif fill_en = '1' then
tx_din(7 downto 0) <= data;
data := data + 1;
tx_din(15 downto 8) <= data;
data := data + 1;
tx_din(23 downto 16) <= data;
data := data + 1;
tx_din(31 downto 24) <= data;
data := data + 1;
end if;
end if;
end process;
------------------------------------------------------------------
pkt_data_counter:
process(clk)
begin
if rising_edge(clk) then
if fill_set = '1' then
fill_size <= (others => '0');
fill_rdy <= '0';
fill_cnt <= pkt_nwords;
elsif fill_en = '1' then
if fill_cnt /= 0 then
fill_cnt <= fill_cnt - 1;
fill_size <= fill_size + 1;
else
fill_rdy <= '1';
end if;
end if;
end if;
end process;
------------------------------------------------------------------
inst_emac_tx : entity work.emac_tx
GENERIC MAP
(
f_sysclk => f_sysclk,
RAM_SIZE => TX_RAM_SIZE
)
PORT MAP
(
clk => clk,
rst => rst,
din_vld => tx_din_vld,
din => tx_din,
ctrl_in => tx_ctrl_in,
ctrl_out => tx_ctrl_out,
mii_tx_clk => mii_tx_clk,
mii_tx_en => mii_tx_en,
mii_tx_er => mii_tx_er,
mii_tx => mii_tx
);
end behavior;
-111
View File
@@ -1,111 +0,0 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
use std.textio.all; -- Imports the standard textio package.
use work.utils_pkg.all; -- Imports the standard textio package.
ENTITY shifter IS
Generic
(
data_width : natural := 32;
aggregate_size : natural := 8;
do_pipelined : boolean := true
);
Port
(
rst : in STD_LOGIC;
clk : in STD_LOGIC;
sa : in integer;
din_vld : in STD_LOGIC;
din : in unsigned(data_width-1 downto 0);
dout_vld : out STD_LOGIC;
dout : out unsigned(data_width-1 downto 0)
);
END shifter;
ARCHITECTURE behavior OF shifter IS
constant num_rounds : natural := NextExpBaseTwo(data_width/aggregate_size);
subtype sa_rnd_t is signed(num_rounds-1 downto 0);
subtype word_t is unsigned(data_width-1 downto 0);
type word_array_t is array (0 to num_rounds) of word_t;
signal rot_data : word_array_t;
signal sa_rnd : sa_rnd_t;
type sa_rnd_array_t is array (0 to num_rounds) of sa_rnd_t;
signal sa_rnd_pipe : sa_rnd_array_t;
signal dout_vld_pipe : unsigned(0 to num_rounds);
--------------------------------------------------------------------------
function rol_stage(x : unsigned; en : std_logic; stage_num : natural; size : natural) return unsigned is
variable result : unsigned(x'range);
constant sa : natural := (2**stage_num) * size;
begin
if en = '1' then
result := x(x'left-sa downto 0) & x(x'left downto x'length-sa);
else
result := x;
end if;
return result;
end rol_stage;
--------------------------------------------------------------------------
begin
--------------------------------------------------------------------------
gen_non_pipelined:
if do_pipelined = false generate
begin
rot_data(0) <= din;
gen_rotate_right:
for stage in 0 to num_rounds-1 generate
begin
rot_data(stage+1) <= rol_stage(rot_data(stage), sa_rnd(stage), stage, aggregate_size);
end generate;
sa_rnd <= to_signed(sa, num_rounds);
dout <= rot_data(num_rounds);
dout_vld <= din_vld;
end generate;
--------------------------------------------------------------------------
gen_pipelined:
if do_pipelined = true generate
begin
rot_data(0) <= din;
sa_rnd_pipe(0) <= to_signed(sa, num_rounds);
dout_vld_pipe(0) <= din_vld;
gen_rotate_right:
for stage in 0 to num_rounds-1 generate
begin
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
dout_vld_pipe(stage+1) <= '0';
else
dout_vld_pipe(stage+1) <= dout_vld_pipe(stage);
if dout_vld_pipe(stage) = '1' then
sa_rnd_pipe(stage+1) <= sa_rnd_pipe(stage);
rot_data(stage+1) <= rol_stage(rot_data(stage), sa_rnd_pipe(stage)(stage), stage, aggregate_size);
end if;
end if;
end if;
end process;
end generate;
dout <= rot_data(num_rounds);
dout_vld <= dout_vld_pipe(num_rounds);
end generate;
--------------------------------------------------------------------------
end behavior;
-118
View File
@@ -1,118 +0,0 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
use std.textio.all; -- Imports the standard textio package.
use work.utils_pkg.all; -- Imports the standard textio package.
ENTITY sipo IS
Generic
(
data_width_in : natural := 8;
data_width_out : natural := 32;
msb_first : boolean := false
);
Port
(
rst : in STD_LOGIC;
clk : in STD_LOGIC;
din_en : in STD_LOGIC;
din_vld : in STD_LOGIC;
din : in unsigned(data_width_in-1 downto 0);
dout_en : out STD_LOGIC;
dout_vld : out STD_LOGIC;
dout : out unsigned(data_width_out-1 downto 0);
dout_be : out unsigned(data_width_out/data_width_in-1 downto 0)
);
END sipo;
ARCHITECTURE behavior OF sipo IS
constant num_shifts : natural := data_width_out/data_width_in;
signal pre_fin : STD_LOGIC;
signal shift_cnt_pipe : unsigned(num_shifts-1 downto 0);
signal shift_pipe : unsigned(data_width_out-1 downto 0);
signal out_en : STD_LOGIC;
signal out_vld : STD_LOGIC;
signal din_vld_r : STD_LOGIC;
signal abort : STD_LOGIC;
--------------------------------------------------------------------------
begin
pre_fin <= shift_cnt_pipe(shift_cnt_pipe'left) when msb_first else shift_cnt_pipe(0);
dout_en <= out_en;
dout_vld <= out_vld;
--------------------------------------------------------------------------
process(clk)
begin
if rising_edge(clk) then
if rst = '1' or pre_fin = '1' then
abort <= '0';
elsif din_vld_r = '1' and din_en = '0' then
abort <= '1';
end if;
end if;
end process;
process(clk)
begin
if rising_edge(clk) then
din_vld_r <= din_vld and din_en;
if rst = '1' then
out_en <= '0';
elsif out_en = '0' then
out_en <= pre_fin and din_en;
elsif out_vld = '1' then
out_en <= din_en;
end if;
end if;
end process;
process(clk)
begin
if rising_edge(clk) then
out_vld <= pre_fin;
if pre_fin = '1' then
dout <= shift_pipe;
dout_be <= shift_cnt_pipe;
end if;
end if;
end process;
process(clk)
begin
if rising_edge(clk) then
if rst = '1' or pre_fin = '1' then
if (msb_first) then
shift_cnt_pipe <= (shift_cnt_pipe'left downto 1 => '0') & (din_en and din_vld);
else
shift_cnt_pipe <= (din_en and din_vld) & (shift_cnt_pipe'left downto 1 => '0');
end if;
elsif din_vld = '1' or abort = '1' then
if (msb_first) then
shift_cnt_pipe <= shift_cnt_pipe(shift_cnt_pipe'left-1 downto 0) & din_en;
else
shift_cnt_pipe <= din_en & shift_cnt_pipe(shift_cnt_pipe'left downto 1);
end if;
end if;
end if;
end process;
process(clk)
begin
if rising_edge(clk) then
if din_vld = '1' or abort = '1' then
if (msb_first) then
shift_pipe <= shift_pipe(shift_pipe'left-data_width_in downto 0) & din;
else
shift_pipe <= din & shift_pipe(shift_pipe'left downto data_width_in);
end if;
end if;
end if;
end process;
--------------------------------------------------------------------------
end behavior;
-106
View File
@@ -1,106 +0,0 @@
-------------------------------------------------------------------------
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
-- This file: testbench for system test using Xilinx ML-402
-- Copyright (C) 2007 J. Ahrensfeld
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2.1 of the License, or (at your option) any later version.
-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- Lesser General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public
-- License along with this library; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- For questions and ideas, please contact the author at jens@jayfield.org
-----------------------------------------------------------------------
LIBRARY ieee;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY tb_crc32 IS
END tb_crc32;
ARCHITECTURE behavior OF tb_crc32 IS
constant CLK_PERIOD : time := 10 ns;
signal CLK : std_logic := '1';
signal RST : std_logic := '1';
signal din_vld : std_logic := '0';
signal din : unsigned(7 downto 0) := (others => '-');
signal crc32 : unsigned(31 downto 0);
signal crc32_vld : std_logic;
type byte_array_t is array (0 to 61) of unsigned(7 downto 0);
signal test_data : byte_array_t :=
(
X"00", X"0A", X"E6", X"F0", X"05", X"A3", X"00", X"12",
X"34", X"56", X"78", X"90", X"08", X"00", X"45", X"00",
X"00", X"30", X"B3", X"FE", X"00", X"00", X"80", X"11",
X"72", X"BA", X"0A", X"00", X"00", X"03", X"0A", X"00",
X"00", X"02", X"04", X"00", X"04", X"00", X"00", X"1C",
X"89", X"4D", X"00", X"01", X"02", X"03", X"04", X"05",
X"06", X"07", X"08", X"09", X"0A", X"0B", X"0C", X"0D",
X"0E", X"0F", X"10", X"11", X"12", X"13"
);
BEGIN
inst_crc32: entity work.crc32
PORT MAP
(
rst => RST,
clk => CLK,
din_vld => din_vld,
din => din,
crc32_vld => crc32_vld,
crc32_out => crc32
);
CLK_GEN: process
begin
wait for CLK_PERIOD/2;
CLK <= not CLK;
end process;
-- Master
STIMULUS: process
begin
wait for 6*CLK_PERIOD;
RST <= '0';
wait for 6*CLK_PERIOD;
wait until rising_edge(CLK);
for i in 0 to 61 loop
din_vld <= '1';
din <= test_data(i);
wait until rising_edge(CLK);
end loop;
din <= (others => '-');
din_vld <= '0';
wait;
end process;
END;
-224
View File
@@ -1,224 +0,0 @@
-------------------------------------------------------------------------
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
-- This file: testbench for system test using Xilinx ML-402
-- Copyright (C) 2007 J. Ahrensfeld
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2.1 of the License, or (at your option) any later version.
-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- Lesser General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public
-- License along with this library; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- For questions and ideas, please contact the author at jens@jayfield.org
-----------------------------------------------------------------------
LIBRARY ieee;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY tb_serdes IS
END tb_serdes;
ARCHITECTURE behavior OF tb_serdes IS
constant CLK_PERIOD : time := 10 ns;
signal CLK : std_logic := '1';
signal RST : std_logic := '1';
signal piso_din_vld : std_logic := '0';
signal piso_din_rdy : std_logic;
signal piso_din_be : unsigned(3 downto 0) := (others => '0');
signal piso_din : unsigned(31 downto 0) := (others => '-');
signal piso_dout_vld : std_logic;
signal piso_dout : unsigned(7 downto 0);
signal piso_dout_en : std_logic;
signal piso2_din_vld : std_logic := '0';
signal piso2_din_rdy : std_logic;
signal piso2_din_be : unsigned(1 downto 0) := (others => '1');
signal piso2_din : unsigned(7 downto 0) := (others => '-');
signal piso2_dout_vld : std_logic;
signal piso2_dout : unsigned(3 downto 0);
signal piso2_dout_en : std_logic;
signal sipo_enable : std_logic := '0';
signal sipo_rst : std_logic := '0';
signal sipo_din_vld : std_logic := '0';
signal sipo_din : unsigned(7 downto 0) := (others => '-');
signal sipo_dout_vld : std_logic;
signal sipo_dout_en : std_logic;
signal sipo_dout_be : unsigned(3 downto 0);
signal sipo_dout : unsigned(31 downto 0);
signal sipo2_enable : std_logic := '0';
signal sipo2_rst : std_logic := '0';
signal sipo2_din_vld : std_logic := '0';
signal sipo2_din : unsigned(3 downto 0) := (others => '-');
signal sipo2_dout_vld : std_logic;
signal sipo2_dout_en : std_logic;
signal sipo2_dout_be : unsigned(1 downto 0);
signal sipo2_dout : unsigned(7 downto 0);
BEGIN
inst_piso : entity work.piso
GENERIC MAP
(
data_width_in => 32,
data_width_out => 8,
msb_first => true
)
PORT MAP
(
rst => RST,
clk => CLK,
din_vld => piso_din_vld,
din_rdy => piso_din_rdy,
din_be => piso_din_be,
din => piso_din,
dout_vld => piso_dout_vld,
dout_en => piso_dout_en,
dout => piso_dout
);
piso_dout_en <= piso2_din_rdy;
inst_piso2 : entity work.piso
GENERIC MAP
(
data_width_in => 8,
data_width_out => 4,
msb_first => true
)
PORT MAP
(
rst => RST,
clk => CLK,
din_vld => piso2_din_vld,
din_rdy => piso2_din_rdy,
din_be => piso2_din_be,
din => piso2_din,
dout_vld => piso2_dout_vld,
dout_en => piso2_dout_en,
dout => piso2_dout
);
piso2_din_vld <= piso_dout_vld;
piso2_dout_en <= '1';
piso2_din <= piso_dout;
inst_sipo : entity work.sipo
GENERIC MAP
(
data_width_in => 8,
data_width_out => 32,
msb_first => true
)
PORT MAP
(
rst => RST,
clk => CLK,
din_en => sipo_enable,
din_vld => sipo_din_vld,
din => sipo_din,
dout_be => sipo_dout_be,
dout_vld => sipo_dout_vld,
dout => sipo_dout,
dout_en => sipo_dout_en
);
sipo_din <= sipo2_dout;
sipo_din_vld <= sipo2_dout_vld;
sipo_enable <= sipo2_dout_en;
sipo_rst <= RST or not piso2_dout_vld;
inst_sipo2 : entity work.sipo
GENERIC MAP
(
data_width_in => 4,
data_width_out => 8,
msb_first => true
)
PORT MAP
(
rst => RST,
clk => CLK,
din_en => sipo2_enable,
din_vld => sipo2_din_vld,
din => sipo2_din,
dout_be => sipo2_dout_be,
dout_vld => sipo2_dout_vld,
dout => sipo2_dout,
dout_en => sipo2_dout_en
);
sipo2_din <= piso2_dout;
sipo2_din_vld <= piso2_dout_vld;
sipo2_enable <= sipo2_din_vld;
sipo_rst <= RST or not piso2_dout_vld;
CLK_GEN: process
begin
wait for CLK_PERIOD/2;
CLK <= not CLK;
end process;
-- Master
STIMULUS: process
begin
wait for 600*CLK_PERIOD;
RST <= '0';
wait for 60*CLK_PERIOD;
for i in 1 to 10 loop
wait until rising_edge(CLK);
piso_din_vld <= '1';
piso_din <= X"12345678";
piso_din_be <= "1111";
wait until rising_edge(CLK) and piso_din_rdy = '1';
piso_din <= piso_din + X"12345678";
piso_din_be <= "1111";
wait until rising_edge(CLK) and piso_din_rdy = '1';
piso_din <= piso_din + X"12345678";
piso_din_be <= "1111";
wait until rising_edge(CLK) and piso_din_rdy = '1';
piso_din <= piso_din + X"12345678";
piso_din_be <= "1100";
wait until rising_edge(CLK) and piso_din_rdy = '1';
piso_din <= (others => '-');
piso_din_vld <= '0';
wait until rising_edge(CLK) and piso_dout_vld = '0';
-- wait until rising_edge(CLK);
-- wait until rising_edge(CLK) and sipo_dout_vld = '1';
--
wait for 33*CLK_PERIOD;
end loop;
wait;
end process;
END;
-761
View File
@@ -1,761 +0,0 @@
-------------------------------------------------------------------------
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
-- This file: testbench for system test using Xilinx ML-402
-- Copyright (C) 2007 J. Ahrensfeld
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2.1 of the License, or (at your option) any later version.
-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- Lesser General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public
-- License along with this library; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- For questions and ideas, please contact the author at jens@jayfield.org
-----------------------------------------------------------------------
LIBRARY ieee;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY tb_emac_top_jb IS
END tb_emac_top_jb;
ARCHITECTURE behavior OF tb_emac_top_jb IS
constant CLK_PERIOD : time := 10 ns;
constant MII_CLK_PERIOD : time := 37.7 ns;
signal CLK : std_logic := '1';
signal RST : std_logic := '1';
-- Slave
signal CYC_I : std_logic := '0';
signal STB_I : std_logic := '0';
signal WE_I : std_logic := '0';
signal SEL_I : unsigned(3 downto 0) := (others => '1');
signal ACK_O : std_logic;
signal INT_O : std_logic;
signal MRDY_I : std_logic := '0';
signal SRDY_O : std_logic;
signal ADDR_I : unsigned(31 downto 0) := (others => '-');
signal DAT_I : unsigned(31 downto 0) := (others => '-');
signal DAT_O : unsigned(31 downto 0) := (others => '-');
signal DAT_O_reg : unsigned(31 downto 0) := (others => '-');
signal status_reg : unsigned(31 downto 0) := (others => '0');
signal size_reg : unsigned(31 downto 0) := (others => '0');
-- Master
signal CYC_O : std_logic;
signal STB_O : std_logic;
signal WE_O : std_logic;
signal SEL_O : unsigned(3 downto 0) := (others => '1');
signal ACK_I : std_logic := '0';
signal MRDY_O : std_logic := '1';
signal SRDY_I : std_logic := '1';
signal ADDR_O : unsigned(31 downto 0) := (others => '-');
signal MDAT_I : unsigned(31 downto 0) := (others => '-');
signal MDAT_O : unsigned(31 downto 0) := (others => '-');
-- MII signals
signal mii_rx_clk_board : std_logic := '1';
signal mii_tx_clk_board : std_logic := '1';
signal mii_rx_clk : std_logic := '1';
signal mii_tx_clk : std_logic := '1';
signal mii_rx : unsigned(7 downto 0) := (others => '-');
signal mii_tx : unsigned(7 downto 0);
signal mii_rx_dv : std_logic := '0';
signal mii_rx_er : std_logic := '0';
signal mii_tx_en : std_logic;
signal mii_tx_er : std_logic;
signal mii_crs : std_logic := '0';
signal mii_col : std_logic := '0';
signal mii_gtx_clk : std_logic;
signal loop_back_en : std_logic := '0';
signal pktgen_tx : unsigned(7 downto 0);
signal pktgen_tx_en : std_logic;
signal pktgen_tx_er : std_logic;
signal pktgen_en : std_logic := '0';
signal pktgen_gigabit : std_logic := '0';
signal pktgen_fcs_en : std_logic := '0';
signal dat_o_cnt_en : std_logic := '0';
signal dat_o_cnt_rst : std_logic := '1';
signal dat_o_cnt : natural;
signal pkt_count : natural;
type emac_action_t is (emac_idle, emac_alloc, emac_write, emac_commit, emac_wait_data, emac_read, emac_free);
signal emac_action : emac_action_t;
constant RX_STATUS_REG_ADDR : unsigned(31 downto 0) := X"0000_0000";
constant RX_SIZE_REG_ADDR : unsigned(31 downto 0) := X"0000_0004";
constant TX_STATUS_REG_ADDR : unsigned(31 downto 0) := X"0000_0008";
constant TX_SIZE_REG_ADDR : unsigned(31 downto 0) := X"0000_000C";
constant DATA_REG_ADDR : unsigned(31 downto 0) := X"0000_8000";
-- 64Bit RAM
signal MDAT_I_64 : unsigned(63 downto 0) := (others => '-');
signal MDAT_O_64 : unsigned(63 downto 0) := (others => '-');
type ram_t is array (0 to 511) of unsigned(63 downto 0);
signal ram64 : ram_t;
BEGIN
MDAT_I <= MDAT_I_64(31 downto 0);
MDAT_O_64 <= MDAT_O & MDAT_O;
process(CLK)
variable res: unsigned(63 downto 0);
variable ram_data : unsigned(63 downto 0);
variable data8: unsigned(7 downto 0);
begin
if rising_edge(CLK) then
if RST = '1' then
data8 := X"00";
for i in 0 to 255 loop
ram_data(7 downto 0) := data8;
data8 := data8 + 1;
ram_data(15 downto 8) := data8;
data8 := data8 + 1;
ram_data(23 downto 16) := data8;
data8 := data8 + 1;
ram_data(31 downto 24) := data8;
data8 := data8 + 1;
ram_data(39 downto 32) := data8;
data8 := data8 + 1;
ram_data(47 downto 40) := data8;
data8 := data8 + 1;
ram_data(55 downto 48) := data8;
data8 := data8 + 1;
ram_data(63 downto 56) := data8;
data8 := data8 + 1;
ram64(i) <= ram_data;
end loop;
else
ACK_I <= '0';
if (CYC_O and STB_O) = '1' then
if WE_O = '0' then
ACK_I <= '1';
ram_data := ram64(to_integer(ADDR_O(31 downto 3)));
if ADDR_O(2) = '0' then
res := ram_data;
else
res := ram_data(31 downto 0) & ram_data(63 downto 32);
end if;
else -- WE=1
ram_data := ram64(to_integer(ADDR_O(31 downto 3)));
-- ram_data := (others => '-');
if ADDR_O(2) = '0' then
if SEL_O = "11111111" then
ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64;
elsif SEL_O = "00001111" then
ram64(to_integer(ADDR_O(31 downto 3))) <= ram_data(63 downto 32) & MDAT_O_64(31 downto 0);
elsif SEL_O = "11110000" then
ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64(63 downto 32) & ram_data(31 downto 0);
end if;
else
if SEL_O = "11111111" then
ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64(31 downto 0) & MDAT_O_64(63 downto 32);
elsif SEL_O = "00001111" then
ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64(31 downto 0) & ram_data(31 downto 0);
elsif SEL_O = "11110000" then
ram64(to_integer(ADDR_O(31 downto 3))) <= ram_data(63 downto 32) & MDAT_O_64(63 downto 32);
end if;
end if;
end if;
end if;
MDAT_I_64 <= res;
end if;
end if;
end process;
inst_emac_top_jb : entity work.emac_top_jb
GENERIC MAP
(
f_sysclk => 100.0,
RX_RAM_SIZE => 2048,
TX_RAM_SIZE => 2048
)
PORT MAP
(
-- JBUS Slave signals
CLK_I => CLK,
RST_I => RST,
INT_O => INT_O,
CYC_I => CYC_I,
STB_I => STB_I,
SEL_I => SEL_I,
WE_I => WE_I,
ACK_O => ACK_O,
SRDY_O => SRDY_O,
MRDY_I => MRDY_I,
ADDR_I => ADDR_I,
DAT_I => DAT_I,
DAT_O => DAT_O,
-- JBUS Master signals
CYC_O => CYC_O,
STB_O => STB_O,
WE_O => WE_O,
SEL_O => SEL_O,
ACK_I => ACK_I,
SRDY_I => SRDY_I,
MRDY_O => MRDY_O,
ADDR_O => ADDR_O,
MDAT_I => MDAT_I,
MDAT_O => MDAT_O,
mii_rx_clk => mii_rx_clk_board,
mii_rx_dv => mii_rx_dv,
mii_rx_er => mii_rx_er,
mii_rx => mii_rx,
mii_tx_clk => mii_tx_clk_board,
mii_tx_en => mii_tx_en,
mii_tx_er => mii_tx_er,
mii_tx => mii_tx,
mii_gtx_clk => mii_gtx_clk,
mii_crs => mii_crs,
mii_col => mii_col
);
inst_pkt_gen : entity work.pkt_gen
GENERIC MAP
(
f_sysclk => 100.0,
PKT_SIZE_MIN => 64,
PKT_SIZE_MAX => 1512
)
PORT MAP
(
clk => CLK,
rst => RST,
en => pktgen_en,
gigabit_en => pktgen_gigabit,
fcs_gen_en => pktgen_fcs_en,
mii_tx_clk => mii_tx_clk_board,
mii_tx_en => pktgen_tx_en,
mii_tx_er => pktgen_tx_er,
mii_tx => pktgen_tx
);
CLK_GEN: process
begin
wait for CLK_PERIOD/2;
CLK <= not CLK;
end process;
MII_CLK_GEN: process
begin
wait for MII_CLK_PERIOD/2;
mii_rx_clk <= not mii_rx_clk;
mii_tx_clk <= not mii_tx_clk;
end process;
mii_rx_clk_board <= mii_rx_clk;
mii_tx_clk_board <= mii_tx_clk;
DAT_O_register:
process(CLK)
begin
if rising_edge(CLK) then
if ACK_O = '1' then
DAT_O_reg <= DAT_O;
end if;
end if;
end process;
DAT_O_count_register:
process(CLK)
begin
if rising_edge(CLK) then
if dat_o_cnt_rst = '1' then
dat_o_cnt <= 0;
elsif ACK_O = '1' and dat_o_cnt_en = '1' then
dat_o_cnt <= dat_o_cnt + 1;
end if;
end if;
end process;
mii_rx <= mii_tx when loop_back_en = '1' else pktgen_tx;
mii_rx_dv <= mii_tx_en when loop_back_en = '1' else pktgen_tx_en;
mii_rx_er <= mii_tx_er when loop_back_en = '1' else pktgen_tx_er;
mii_crs <= '0';
mii_col <= '0';
-- Master
STIMULUS: process
procedure emac_tx_reset_100mbps is
begin
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"A000_0000";
STB_I <= '1';
WE_I <= '1';
ADDR_I <= TX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
WE_I <= '0';
end procedure emac_tx_reset_100mbps;
procedure emac_rx_reset_100mbps is
begin
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"A000_0000";
STB_I <= '1';
WE_I <= '1';
ADDR_I <= RX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
WE_I <= '0';
end procedure emac_rx_reset_100mbps;
procedure emac_tx_reset_1000mbps is
begin
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"E000_0000";
STB_I <= '1';
WE_I <= '1';
ADDR_I <= TX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
WE_I <= '0';
end procedure emac_tx_reset_1000mbps;
procedure emac_rx_reset_1000mbps is
begin
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"E000_0000";
STB_I <= '1';
WE_I <= '1';
ADDR_I <= RX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
WE_I <= '0';
end procedure emac_rx_reset_1000mbps;
procedure emac_alloc (size : natural) is
begin
-- TX-ALLOCATION
-- set TX-size
emac_action <= emac_alloc;
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= to_unsigned(size, 32);
STB_I <= '1';
WE_I <= '1';
ADDR_I <= TX_SIZE_REG_ADDR;
check_alloc_ok:
while(true) loop
-- set alloc request
wait until rising_edge(CLK) and SRDY_O = '1';
WE_I <= '0';
STB_I <= '1';
ADDR_I <= TX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
wait until rising_edge(CLK) and ACK_O = '1';
status_reg <= DAT_O;
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"0002_0000" or (not X"0001_0000" and status_reg);
STB_I <= '1';
WE_I <= '1';
ADDR_I <= TX_STATUS_REG_ADDR;
check_bsy:
while (true) loop
wait until rising_edge(CLK) and SRDY_O = '1';
WE_I <= '0';
STB_I <= '1';
ADDR_I <= TX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
wait until rising_edge(CLK) and ACK_O = '1';
status_reg <= DAT_O;
wait until rising_edge(CLK);
if status_reg(17) = '0' then
exit check_bsy;
end if;
end loop;
if status_reg(16) = '1' then
exit check_alloc_ok;
end if;
end loop;
CYC_I <= '0';
emac_action <= emac_idle;
end procedure emac_alloc;
procedure emac_commit is
begin
-- RX- DEALLOCATION
emac_action <= emac_commit;
-- set free request
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
WE_I <= '0';
STB_I <= '1';
ADDR_I <= TX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
wait until rising_edge(CLK) and ACK_O = '1';
status_reg <= DAT_O;
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"0001_0000" or (not X"0002_0000" and status_reg);
STB_I <= '1';
WE_I <= '1';
ADDR_I <= TX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
WE_I <= '0';
emac_action <= emac_idle;
end procedure emac_commit;
procedure emac_write (size : natural) is
variable data : unsigned (7 downto 0);
variable num_words : natural;
begin
-- FILL TX data
emac_action <= emac_write;
if (size mod 4) = 0 then
num_words := size/4;
else
num_words := size/4 + 1;
end if;
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
data := X"00";
ADDR_I <= DATA_REG_ADDR;
WE_I <= '1';
for i in 1 to num_words loop
STB_I <= '1';
DAT_I(7 downto 0) <= data;
data := data + 1;
DAT_I(15 downto 8) <= data;
data := data + 1;
DAT_I(23 downto 16) <= data;
data := data + 1;
DAT_I(31 downto 24) <= data;
data := data + 1;
wait until rising_edge(CLK) and SRDY_O = '1';
end loop;
STB_I <= '0';
wait until rising_edge(CLK) and SRDY_O = '1';
emac_commit;
emac_action <= emac_idle;
end procedure emac_write;
procedure emac_read (size_in : natural) is
variable data : unsigned (7 downto 0);
variable size, num_words : natural;
begin
return;
emac_action <= emac_wait_data;
-- check if data available
check_data_avail:
while (true) loop
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
WE_I <= '0';
STB_I <= '1';
ADDR_I <= RX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
wait until rising_edge(CLK) and ACK_O = '1';
status_reg <= DAT_O;
wait until rising_edge(CLK);
if status_reg(17) = '1' and status_reg(16) = '1' then
exit check_data_avail;
end if;
end loop;
read_size:
dat_o_cnt_rst <= '1';
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
WE_I <= '0';
STB_I <= '1';
ADDR_I <= RX_SIZE_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
wait until rising_edge(CLK) and ACK_O = '1';
size_reg <= DAT_O;
wait until rising_edge(CLK);
-- set packet request
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
WE_I <= '0';
STB_I <= '1';
ADDR_I <= RX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
wait until rising_edge(CLK) and ACK_O = '1';
status_reg <= DAT_O;
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"0002_0000" or (not X"0001_0000" and status_reg);
STB_I <= '1';
WE_I <= '1';
ADDR_I <= RX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
WE_I <= '0';
emac_action <= emac_read;
-- Read RX data
size := size_in;
if (size_in = 0) then
size := to_integer(size_reg(15 downto 0));
end if;
if (size mod 4) = 0 then
num_words := size/4;
else
num_words := size/4 + 1;
end if;
dat_o_cnt_rst <= '0';
dat_o_cnt_en <= '1';
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
ADDR_I <= DATA_REG_ADDR;
WE_I <= '0';
STB_I <= '1';
for i in 1 to num_words loop
wait until rising_edge(CLK) and SRDY_O = '1';
end loop;
STB_I <= '0';
wait until rising_edge(CLK) and dat_o_cnt = num_words;
dat_o_cnt_en <= '0';
emac_action <= emac_idle;
end procedure emac_read;
procedure emac_free is
begin
return;
-- RX- DEALLOCATION
emac_action <= emac_free;
-- set free request
CYC_I <= '1';
wait until rising_edge(CLK) and SRDY_O = '1';
WE_I <= '0';
STB_I <= '1';
ADDR_I <= RX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
wait until rising_edge(CLK) and ACK_O = '1';
status_reg <= DAT_O;
wait until rising_edge(CLK) and SRDY_O = '1';
DAT_I <= X"0001_0000" or (not X"0002_0000" and status_reg);
STB_I <= '1';
WE_I <= '1';
ADDR_I <= RX_STATUS_REG_ADDR;
wait until rising_edge(CLK) and SRDY_O = '1';
STB_I <= '0';
WE_I <= '0';
emac_action <= emac_idle;
end procedure emac_free;
begin
wait for 6*MII_CLK_PERIOD;
RST <= '0';
wait for 60*CLK_PERIOD;
emac_rx_reset_100mbps;
emac_tx_reset_100mbps;
pktgen_gigabit <= '0';
pktgen_fcs_en <= '1';
wait for 60*CLK_PERIOD;
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
emac_alloc (1004);
for i in 1 to 10 loop
for j in 1 to 100 loop
emac_alloc (72);
emac_write (72);
end loop;
wait for 1 ms;
end loop;
wait until rising_edge(mii_tx_clk) and mii_tx_en = '0';
wait for 6000*CLK_PERIOD;
loop_back_en <= '1';
emac_alloc (74);
emac_write (74);
emac_alloc (105);
emac_write (105);
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_alloc (103);
emac_write (103);
emac_read (0);
emac_free;
emac_alloc (71);
emac_write (71);
emac_read (0);
emac_free;
emac_alloc (82);
emac_write (82);
emac_alloc (86);
emac_write (86);
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_alloc (77);
emac_write (77);
emac_alloc (99);
emac_write (99);
emac_alloc (65);
emac_write (65);
emac_alloc (321);
emac_write (321);
emac_read (0);
emac_free;
emac_alloc (1111);
emac_write (1111);
emac_read (0);
emac_free;
emac_alloc (73);
emac_write (73);
emac_alloc (107);
emac_write (107);
emac_alloc (83);
emac_write (83);
emac_read (0);
emac_free;
emac_alloc (72);
emac_write (72);
emac_alloc (1003);
emac_write (1003);
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_read (0);
emac_free;
emac_read (0);
emac_free;
wait for 6000*CLK_PERIOD;
loop_back_en <= '0';
pktgen_en <= '1';
pkt_count <= 0;
for i in 1 to 500 loop
wait for 1 us;
emac_read (0);
emac_free;
pkt_count <= pkt_count + 1;
end loop;
pktgen_en <= '0';
emac_read (0);
emac_free;
wait;
end process;
END;