Initial import

git-svn-id: http://moon:8086/svn/vhdl/trunk@8 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
2008-08-23 08:34:09 +00:00
parent d3bd08bb52
commit a87b40a4be
27 changed files with 10441 additions and 0 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+886
View File
@@ -0,0 +1,886 @@
--------------------------------------------------------------------------
-- 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_rdy : in STD_LOGIC;
imem_en : out STD_LOGIC;
imem_addr : out word_t;
imem_data : in word_t;
dmem_rdy : in STD_LOGIC;
dmem_en : out STD_LOGIC;
dmem_re : out STD_LOGIC;
dmem_we : 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;
ce : in STD_LOGIC;
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 cpu_rst : STD_LOGIC;
signal reg_a : word_t;
signal reg_b : word_t;
signal ctrl_lines : ctrl_lines_t;
signal ID_act : STD_LOGIC;
signal EX_act : STD_LOGIC;
signal MEM_act : STD_LOGIC;
signal WB_act : STD_LOGIC;
signal ID_nop : STD_LOGIC;
signal EX_nop : STD_LOGIC;
signal MEM_nop : STD_LOGIC;
signal WB_nop : STD_LOGIC;
signal IF_stall : STD_LOGIC;
signal EX_stall : STD_LOGIC;
signal MEM_stall : STD_LOGIC;
signal WB_stall : STD_LOGIC;
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_en : STD_LOGIC;
signal cop_ctrl : cop_ctrl_in_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 events : event_t;
signal bcu_op_a : word_t;
signal bcu_op_b : word_t;
signal bcu_flags : bcu_flags_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 <= not halt and run_en;
events.Int <= int;
events.illegal <= EX_stage.ctrl.exc_illegal;
events.break <= EX_stage.ctrl.exc_break;
events.syscall <= EX_stage.ctrl.exc_syscall;
-- Stall Detection Unit ---------------------------------------------------
imem_en <= run_en and (not (ID_stage.cop_stat.exc_strobe or mul_dep) or ID_stage.cop_stat.ec) and not dmem_dep;
ID_nop <= cpu_rst or imem_dep;
EX_nop <= cpu_rst or EX_stage.cop_stat.exc_strobe or mul_dep;
MEM_nop <= cpu_rst or EX_stage.cop_stat.exc_strobe;
WB_nop <= cpu_rst or EX_stage.cop_stat.exc_strobe or dmem_dep;
IF_stall <= not cpu_run or mul_dep or ID_stage.cop_stat.ec or imem_dep or dmem_dep;
EX_stall <= not cpu_run or dmem_dep;
MEM_stall <= not cpu_run or dmem_dep;
WB_stall <= not cpu_run;
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;
---------------------------------------------------------------------------
events.inst_load_err <= '1' when EX_stage.epc(1 downto 0) /= "00" else '0';
events.inst_priv_addr <= EX_stage.epc(word_t'left);
cop_en <= not ID_nop;
--------------------------------------------------------------------------
-- 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,
ce => cop_en,
events => events,
IR_valid => ID_stage.ctrl.cop_instr_en,
IR => ID_stage.IR,
ctrl_in => cop_ctrl,
ctrl_out => ID_stage.cop_stat,
dout => cop_dout,
din => cop_din
);
cop_ctrl.bd_ex <= EX_stage.ctrl.branch;
cop_ctrl.bd_mem <= MEM_stage.ctrl.branch;
cop_ctrl.bd_wb <= WB_stage.ctrl.branch;
cop_ctrl.epc_id <= ID_stage.epc;
cop_ctrl.epc_ex <= EX_stage.epc;
cop_ctrl.epc_mem <= MEM_stage.epc;
cop_ctrl.epc_wb <= WB_stage.epc;
cop_ctrl.dmem_addr <= EX_stage.va;
--------------------------------------------------------------------------
-- IF stage
--------------------------------------------------------------------------
imem_addr <= pc.curr;
proc_stage_pc:
process(pc, rst, IF_stall)
begin
if rst = '1' then
pc.curr <= RESET_VECTOR after 2 ns;
elsif IF_stall = '0' then
if pc.is_branch 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 IF_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';
if rst = '1' then
pc.nxt <= RESET_VECTOR;
pc.last <= RESET_VECTOR;
elsif ID_stage.cop_stat.exc_strobe = '1' then
pc.nxt <= ID_stage.cop_stat.exc_vec;
elsif IF_stall = '0' then
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 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.z 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 rst = '1' then
reset_delay := (others => '1');
cpu_rst <= '1';
run_en <= '0';
elsif rising_edge(clk_1) then
if reset_delay /= (5 downto 0 => '0') then
reset_delay := reset_delay - 1;
else
cpu_rst <= '0';
end if;
if reset_delay(reset_delay'left) = '0' then
run_en <= '1';
end if;
end if;
end process;
--------------------------------------------------------------------------
-- ID stage
--------------------------------------------------------------------------
ID_act <= not ID_nop;
ID_stage.IR <= imem_data;
ID_stage.pcn <= pc.curr;
ID_stage.op <= decode_op(ID_stage.IR) when ID_nop = '0' else NOP;
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 ID_stage.cop_stat.reg_write;
ID_stage.epc <= pc.last;
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 <= 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 <= 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 => 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 <= mul_result when EX_stage.ctrl.mul_access = '1' else alu_result;
EX_act <= not (EX_nop or EX_stall);
proc_stage_ID_EX_1:
process(clk_1)
begin
if rising_edge(clk_1) then
if cpu_rst = '1' then
EX_stage.epc <= (others => '0');
elsif EX_stall = '0' then
EX_stage.op <= ID_stage.op;
if ID_nop = '0' then
EX_stage.IR <= ID_stage.IR;
else
EX_stage.IR <= (others => '0');
end if;
EX_stage.ctrl <= ID_stage.ctrl;
EX_stage.reg_write <= ID_stage.reg_write;
EX_stage.pcn <= ID_stage.pcn;
EX_stage.epc <= ID_stage.epc;
EX_stage.cop_stat <= ID_stage.cop_stat;
if EX_nop = '1' then
EX_stage.op <= NOP;
EX_stage.IR <= (others => '0');
EX_stage.ctrl <= ctrl_lines_default;
EX_stage.cop_stat.exc_strobe <= '0';
EX_stage.reg_write <= '0';
end if;
end if;
end if;
end process;
proc_stage_EX_except:
process(EX_stage)
begin
events.data_load_err <= '0';
events.data_store_err <= '0';
events.alu_ovf <= '0';
events.alu_uvf <= '0';
if EX_stage.ctrl.alu_exc_en = '1' then
if EX_stage.alu_flags.ovf = '1' then
events.alu_ovf <= '1';
end if;
if EX_stage.alu_flags.uvf = '1' then
events.alu_uvf <= '1';
end if;
end if;
if EX_stage.ctrl.except_en = '1' then
if EX_stage.ctrl.word2_en = '1' then
if EX_stage.va(0) = '1' then
events.data_load_err <= EX_stage.ctrl.dmem_en and not EX_stage.ctrl.dmem_we;
events.data_store_err <= EX_stage.ctrl.dmem_en and EX_stage.ctrl.dmem_we;
end if;
elsif EX_stage.va(1 downto 0) /= "00" then
events.data_load_err <= EX_stage.ctrl.dmem_en and not EX_stage.ctrl.dmem_we;
events.data_store_err <= EX_stage.ctrl.dmem_en and EX_stage.ctrl.dmem_we;
end if;
end if;
end process;
proc_stage_DMEM_ADDR:
process(clk_1)
variable vaddr : word_t;
begin
if rising_edge(clk_1) and EX_act = '1' then
vaddr := ID_stage.reg_a + extract_simm32(ID_stage.IR);
EX_stage.va <= vaddr;
if ID_stage.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 process;
dmem_we <= 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_re <= not EX_stage.ctrl.dmem_we;
dmem_en <= EX_stage.ctrl.dmem_en and not(ID_stage.cop_stat.exc_strobe) after 1 ns;
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;
--------------------------------------------------------------------------
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_fwd_reg_a:
process(clk_1)
begin
if rising_edge(clk_1) then
if EX_act = '1' then
EX_stage.reg_a <= ID_stage.reg_a;
bcu_op_a <= ID_stage.reg_a;
end if;
end if;
end process;
proc_stage_fwd_reg_b:
process(clk_1)
begin
if rising_edge(clk_1) then
if EX_act = '1' then
EX_stage.reg_b <= ID_stage.reg_b;
bcu_op_b <= ID_stage.reg_b;
end if;
end if;
end process;
alu_op1_mux:
process(EX_stage)
variable data : word_t;
begin
data := EX_stage.reg_a;
-- case EX_stage.ctrl.alu.op1_src is
--
-- when alu_src_reg =>
-- data := EX_stage.reg_a;
--
-- when alu_src_muldiv =>
-- data := mul_result;
--
-- when others => null;
--
-- end case;
EX_stage.alu_op1 <= data;
end process;
alu_op2_mux:
process(clk_1)
variable data : word_t;
begin
if rising_edge(clk_1) and EX_act = '1' 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 EX_act = '1' 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
--------------------------------------------------------------------------
MEM_act <= not (MEM_nop or MEM_stall);
proc_stage_MEM_n:
process(clk_1)
begin
if rising_edge(clk_1) then
if MEM_stall = '0' then
MEM_stage.op <= EX_stage.op;
MEM_stage.wreg_we <= EX_stage.wreg_we;
MEM_stage.ctrl <= EX_stage.ctrl;
MEM_stage.pcn <= EX_stage.pcn;
MEM_stage.epc <= EX_stage.epc;
MEM_stage.pa_off <= EX_stage.pa_off;
MEM_stage.reg_wptr <= EX_stage.reg_wptr;
MEM_stage.cop_stat <= EX_stage.cop_stat;
if EX_stage.ctrl.dmem_en = '1' then
MEM_stage.ex_result <= EX_stage.reg_b;
else
MEM_stage.ex_result <= EX_stage.result;
end if;
if MEM_nop = '1' then
MEM_stage.op <= NOP;
MEM_stage.wreg_we <= '0';
MEM_stage.ctrl <= ctrl_lines_default;
-- MEM_stage.epc <= (others => '0');
-- MEM_stage.pcn <= (others => '0');
-- MEM_stage.pa_off <= (others => '0');
-- MEM_stage.reg_wptr <= (others => '0');
-- MEM_stage.ex_result <= (others => '0');
end if;
end if;
end if;
end process;
proc_stage_MEM_mux:
process(MEM_stage, dmem_din, cop_dout)
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.cop_stat.cop_access = '1' then
data := cop_dout;
elsif 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;
--------------------------------------------------------------------------
-- WB stage
--------------------------------------------------------------------------
WB_act <= not (WB_nop or WB_stall);
proc_stage_WB_p:
process(clk_1)
begin
if rising_edge(clk_1) then
if WB_stall = '0' then
WB_stage.op <= MEM_stage.op;
WB_stage.ctrl <= MEM_stage.ctrl;
WB_stage.wreg_we <= MEM_stage.wreg_we;
WB_stage.reg_wptr <= MEM_stage.reg_wptr;
WB_stage.data <= MEM_stage.data;
WB_stage.epc <= MEM_stage.epc;
if WB_nop = '1' then
WB_stage.op <= NOP;
WB_stage.ctrl <= ctrl_lines_default;
WB_stage.wreg_we <= '0';
-- WB_stage.epc <= (others => '0');
-- WB_stage.reg_wptr <= (others => '0');
-- WB_stage.data <= (others => '0');
end if;
end if;
end if;
end process;
--------------------------------------------------------------------------
end Behavioral;
+681
View File
@@ -0,0 +1,681 @@
-------------------------------------------------------------------------
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
-- This file: 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;
use std.textio.all; -- Imports the standard textio package.
Library UNISIM;
use UNISIM.vcomponents.all;
library work;
use work.mips_types.all;
--use work.fifo_ctrl_pkg.all;
use work.sdram_config.all;
use work.sdram_types.all;
ENTITY mips_sys IS
GENERIC
(
sys_freq : integer := 100E6;
ddr_phaseshift : integer := 0;
ddr_frequency_hz : integer := 100E6
);
PORT
(
sys_rst_n_in : in std_logic;
sys_clk_in : in std_logic;
-- Buttons and LEDs
sys_btn : in unsigned(4 downto 0);
sys_dip : in unsigned(7 downto 0);
sys_led : out unsigned(8 downto 0);
-- UART
sys_rx : in std_logic;
sys_tx : out std_logic;
-- LCD
sys_lcd_d : inout unsigned(3 downto 0);
sys_lcd_e : out std_logic;
sys_lcd_rs : out std_logic;
sys_lcd_rw : out std_logic;
-- DDR SDRAM
sys_sdr_clk_p : out std_logic; -- ddr_sdram_clock
sys_sdr_clk_n : out std_logic; -- /ddr_sdram_clock
sys_sdr_cke_q : out std_logic; -- clock enable
sys_sdr_cs_qn : out std_logic; -- /chip select
sys_sdr_ras_qn : out std_logic; -- /ras
sys_sdr_cas_qn : out std_logic; -- /cas
sys_sdr_we_qn : out std_logic; -- /write enable
sys_sdr_dm_q : out unsigned(DDR_DM_WIDTH-1 downto 0); -- data mask bits, set to "00"
sys_sdr_dqs_q : inout unsigned(DDR_DQS_WIDTH-1 downto 0); -- data strobe, only for write
sys_sdr_ba_q : out unsigned(DDR_BANK_WIDTH-1 downto 0); -- bank select
sys_sdr_a_q : out unsigned(DDR_ADDR_WIDTH-1 downto 0); -- address bus
sys_sdr_data : inout unsigned(DDR_DATA_WIDTH-1 downto 0); -- bidir data bus
sys_sdr_clk_fb : in std_logic;
-- VGA
-- sys_vga_red : out unsigned(7 downto 0);
-- sys_vga_green : out unsigned(7 downto 0);
-- sys_vga_blue : out unsigned(7 downto 0);
-- sys_vga_blank_n : out std_logic;
-- sys_vga_sync_n : out std_logic;
-- sys_vga_hsync : out std_logic;
-- sys_vga_vsync : out std_logic;
-- sys_vga_clk : out std_logic;
sys_error : out unsigned(1 downto 0) -- indicates Errors
);
-- attribute BUFFER_TYPE : string;
-- attribute BUFFER_TYPE of sys_clk_in : signal is "BUFG";
-- attribute BUFFER_TYPE of sys_sdr_dcm_clk_fb : signal is "BUFG";
END mips_sys;
ARCHITECTURE behavior OF mips_sys IS
COMPONENT mips_top
Port
(
rst : in STD_LOGIC;
clk : in STD_LOGIC;
int : in unsigned(5 downto 0);
mem_valid : in STD_LOGIC;
mem_rdy : in STD_LOGIC;
mem_re : out STD_LOGIC;
mem_en : out STD_LOGIC;
mem_we : out unsigned(3 downto 0);
mem_din : in word_t;
mem_dout : out word_t;
mem_addr : out word_t
);
END COMPONENT;
signal int : unsigned(5 downto 0);
signal mem_din : word_t;
signal mem_dout : word_t;
signal mem_addr : word_t;
signal mem_re : std_logic;
signal mem_en : std_logic;
signal mem_we : unsigned(3 downto 0);
signal mem_valid : std_logic;
signal mem_rdy : std_logic;
COMPONENT rom
Port
(
clk : in STD_LOGIC;
ce : in STD_LOGIC;
addr : in word_t;
dout : out word_t
);
END COMPONENT;
signal rom_data : word_t;
COMPONENT ram
PORT
(
clk : in STD_LOGIC;
ce : in STD_LOGIC;
we : in unsigned(3 downto 0);
addr : in unsigned(31 downto 0);
din : in unsigned(31 downto 0);
dout : out unsigned(31 downto 0)
);
END COMPONENT;
signal ram_data : word_t;
COMPONENT lcd_port
PORT (
rst : in std_logic;
clk : in std_logic;
we : in std_logic;
din : in unsigned(7 downto 0);
dout : out unsigned(7 downto 0);
lcd_d : inout unsigned(3 downto 0);
lcd_e : out std_logic;
lcd_rs : out std_logic;
lcd_rw : out std_logic
);
END COMPONENT;
COMPONENT uart_tx
Port
(
data_in : in std_logic_vector(7 downto 0);
write_buffer : in std_logic;
reset_buffer : in std_logic;
en_16_x_baud : in std_logic;
serial_out : out std_logic;
buffer_full : out std_logic;
buffer_half_full : out std_logic;
clk : in std_logic
);
END COMPONENT;
COMPONENT uart_rx
Port
(
serial_in : in std_logic;
data_out : out std_logic_vector(7 downto 0);
read_buffer : in std_logic;
reset_buffer : in std_logic;
en_16_x_baud : in std_logic;
buffer_data_present : out std_logic;
buffer_full : out std_logic;
buffer_half_full : out std_logic;
clk : in std_logic
);
END COMPONENT;
signal rst : std_logic;
signal rst_in : std_logic;
signal started_up : std_logic := '1';
signal clk : std_logic;
signal led_reg : unsigned(7 downto 0);
signal cpu_lcd_out_reg, cpu_lcd_in_reg, reg_uart_tx: unsigned(7 downto 0);
signal cpu_lcd_we : std_logic;
signal err_led_reg : unsigned(1 downto 0);
signal btn_ps2_reg : unsigned(7 downto 0);
-- Signals to form an timer generating an interrupt every microsecond
subtype tick_usec_t is natural range 0 to 99;
signal tick_usec : tick_usec_t;
signal cnt_usec : word_t;
signal cnt_sec : word_t;
signal cnt_usec_preset : word_t;
signal cnt_sec_preset : word_t;
signal cnt_usec_en : std_logic;
signal cnt_usec_we : std_logic;
signal cnt_sec_en : std_logic;
signal cnt_sec_we : std_logic;
-- Signals for UART connections
signal baud_count : unsigned(7 downto 0);
signal en_16_x_baud : std_logic;
signal reg_we_uart_tx : std_logic;
signal tx_full : std_logic;
signal tx_half_full : std_logic;
signal reg_re_uart_rx : std_logic;
signal reg_uart_rx : std_logic_vector(7 downto 0);
signal rx_data_present : std_logic;
signal rx_full : std_logic;
signal rx_half_full : std_logic;
signal uart_status_port : unsigned(7 downto 0);
signal reg_uart_ctrl : unsigned(7 downto 0);
signal reg_uart_baud : unsigned(7 downto 0);
-- DDR SDRAM
constant BURST_LEN : natural := 2;
signal sdr_addr : user_addr_t;
signal sdr_busy_q : std_logic;
signal sdr_udata_in : unsigned(SDR_DATA_WIDTH-1 downto 0);
signal sdr_udata_out_q : unsigned(SDR_DATA_WIDTH-1 downto 0);
signal sdr_udata_vld_q : std_logic;
signal sdr_be : unsigned(SDR_DM_WIDTH-1 downto 0) := "00000000";
signal sdr_read : std_logic;
signal sdr_en : std_logic;
signal reg_data : word_t;
signal reg_data_vld : std_logic;
signal reg_en : std_logic;
signal rom_en : std_logic;
signal rom_data_vld : std_logic;
signal ram_en : std_logic;
signal ram_data_vld : std_logic;
signal sdram_en : std_logic;
signal sd_counter : word_t;
signal mem_re_r : std_logic;
signal mem_we_r : unsigned(3 downto 0);
signal mem_dout_r : word_t;
signal mem_addr_r : word_t;
-- attribute rom_style: string;
-- attribute rom_style of cmd_fifo_dout: signal is "DISTRIBUTED";
-- attribute rom_style of cpu_cpu_write_fifo_dout: signal is "DISTRIBUTED";
-- attribute rom_style of cpu_read_fifo_dout: signal is "DISTRIBUTED";
BEGIN
int <= "0000" & rx_data_present & btn_ps2_reg(4);
rst_in <= not (started_up and sys_rst_n_in);
en_mux:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
sdram_en <= '0';
else
reg_en <= '0';
rom_en <= '0';
ram_en <= '0';
-- sdram_en <= '0';
if mem_en = '1' then
mem_re_r <= mem_re;
mem_we_r <= mem_we;
mem_dout_r <= mem_dout;
mem_addr_r <= mem_addr;
if mem_addr(31 downto 28) = X"A" then
reg_en <= '1';
elsif (mem_addr(31 downto 28) = X"B" and mem_addr(15) = '0') then
rom_en <= '1';
elsif (mem_addr(31 downto 28) = X"B" and mem_addr(15) = '1') then
ram_en <= '1';
elsif (mem_addr(31 downto 28) = X"8" or mem_addr(30) = '1') then
sdram_en <= '1';
end if;
elsif sdr_busy_q = '0' then
sdram_en <= '0';
end if;
end if;
end if;
end process;
sdr_addr <= mem_addr_r(24 downto 2) & "0";
sdr_udata_in <= mem_dout_r & mem_dout_r;
sdr_be <= mem_we_r & mem_we_r;
sdr_read <= '1';
sdr_en <= sdram_en and not sdr_busy_q;
------------------------------------------------------------------
led_out:
process(rst, clk)
begin
if rst = '1' then
sys_led <= (others => '0');
sys_error <= (others => '0');
elsif rising_edge(clk) then
sys_led <= not mem_rdy & led_reg;
sys_error <= err_led_reg;
end if;
end process;
------------------------------------------------------------------
btn_ps2_register:
process(clk)
begin
if rising_edge(clk) then
btn_ps2_reg <= "000" & unsigned(sys_btn);
end if;
end process;
proc_sd_counter:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
sd_counter <= (others => '0');
elsif sdr_udata_vld_q = '1' then
sd_counter <= sd_counter + 1;
end if;
end if;
end process;
mem_valid <= sdr_udata_vld_q or reg_data_vld or rom_data_vld or ram_data_vld;
mem_din <= reg_data when reg_data_vld = '1' else
rom_data when rom_data_vld = '1' else
ram_data when ram_data_vld = '1' else
sdr_udata_out_q(mem_din'left downto mem_din'right);
------------------------------------------------------------------
inst_rom: rom
PORT MAP
(
clk => clk,
ce => rom_en,
addr => mem_addr_r,
dout => rom_data
);
inst_ram: ram
PORT MAP
(
clk => clk,
ce => ram_en,
we => mem_we_r,
addr => mem_addr_r,
din => mem_dout_r,
dout => ram_data
);
ram_read:
process(clk)
begin
if rising_edge(clk) then
ram_data_vld <= '0';
if ram_en = '1' and mem_re_r = '1' then
ram_data_vld <= '1';
end if;
end if;
end process;
rom_read:
process(clk)
begin
if rising_edge(clk) then
rom_data_vld <= '0';
if rom_en = '1' and mem_re_r = '1' then
rom_data_vld <= '1';
end if;
end if;
end process;
registers_read:
process(clk)
begin
if rising_edge(clk) then
reg_data_vld <= '0';
reg_re_uart_rx <= '0';
if reg_en = '1' and mem_re_r = '1' then
reg_data_vld <= '1';
reg_data <= (others => '0');
case mem_addr_r(5 downto 2) is
when "0000" => null;
when "0001" =>
reg_re_uart_rx <= mem_re_r;
reg_data(7 downto 0) <= unsigned(reg_uart_rx);
when "0010" =>
reg_data(7 downto 0) <= uart_status_port;
reg_data(15 downto 8) <= reg_uart_baud;
reg_data(23 downto 16) <= btn_ps2_reg;
reg_data(31 downto 24) <= cpu_lcd_in_reg;
when "0100" =>
reg_data <= cnt_usec;
when "0101" =>
reg_data <= cnt_sec;
when others => null;
end case;
end if;
end if;
end process;
------------------------------------------------------------------
registers_write:
process(clk)
begin
if rising_edge(clk) then
cpu_lcd_we <= '0';
reg_we_uart_tx <= '0';
cnt_usec_we <= '0';
cnt_sec_we <= '0';
if rst = '1' then
led_reg <= (others => '0');
err_led_reg <= (others => '0');
cpu_lcd_out_reg <= (others => '0');
reg_uart_baud <= to_unsigned(53, 8);
reg_uart_ctrl <= to_unsigned(0, 8);
elsif reg_en = '1' then
case mem_addr_r(5 downto 2) is
when "0000" =>
if mem_we_r(0) = '1' then
led_reg(7 downto 0) <= mem_dout_r(7 downto 0);
end if;
if mem_we_r(3) = '1' then
err_led_reg <= mem_dout_r(31 downto 30);
end if;
when "0001" =>
if mem_we_r(0) = '1' then
reg_we_uart_tx <= '1';
reg_uart_tx <= mem_dout_r(7 downto 0);
end if;
when "0010" =>
if mem_we_r(0) = '1' then
reg_uart_ctrl <= mem_dout_r(7 downto 0);
end if;
if mem_we_r(1) = '1' then
reg_uart_baud <= mem_dout_r(15 downto 8);
end if;
if mem_we_r(3) = '1' then
cpu_lcd_we <= '1';
cpu_lcd_out_reg <= mem_dout_r(31 downto 24);
end if;
when "0100" =>
if mem_we_r(3) = '1' then
cnt_usec_we <= '1';
cnt_usec_preset <= mem_dout_r;
end if;
when "0101" =>
if mem_we_r(3) = '1' then
cnt_sec_we <= '1';
cnt_sec_preset <= mem_dout_r;
end if;
when others => null;
end case;
end if;
end if;
end process;
------------------------------------------------------------------
mem_rdy <= not sdr_busy_q;
------------------------------------------------------------------
inst_mips_top: mips_top
PORT MAP
(
rst => rst,
clk => clk,
int => int,
mem_valid => mem_valid,
mem_rdy => mem_rdy,
mem_en => mem_en,
mem_re => mem_re,
mem_we => mem_we,
mem_din => mem_din,
mem_dout => mem_dout,
mem_addr => mem_addr
);
inst_lcd_port: lcd_port
PORT MAP
(
rst => rst,
clk => clk,
we => cpu_lcd_we,
din => cpu_lcd_out_reg,
dout => cpu_lcd_in_reg,
lcd_d => sys_lcd_d,
lcd_e => sys_lcd_e,
lcd_rs => sys_lcd_rs,
lcd_rw => sys_lcd_rw
);
inst_uart_tx: uart_tx
port map
(
data_in => std_logic_vector(reg_uart_tx),
write_buffer => reg_we_uart_tx,
reset_buffer => rst,
en_16_x_baud => en_16_x_baud,
serial_out => sys_tx,
buffer_full => tx_full,
buffer_half_full => tx_half_full,
clk => clk
);
inst_uart_rx: uart_rx
port map
(
serial_in => sys_rx,
data_out => reg_uart_rx,
read_buffer => reg_re_uart_rx,
reset_buffer => rst,
en_16_x_baud => en_16_x_baud,
buffer_data_present => rx_data_present,
buffer_full => rx_full,
buffer_half_full => rx_half_full,
clk => clk
);
uart_status_port <= (7 downto 5 => '0') & rx_data_present & rx_full & rx_half_full & tx_full & tx_half_full;
tick_usec_timer:
process(clk)
begin
if clk'event and clk='1' then
cnt_usec_en <= '0';
if rst = '1' then
tick_usec <= 0;
cnt_usec_en <= '0';
elsif tick_usec = tick_usec_t'high then
tick_usec <= 0;
cnt_usec_en <= '1';
else
tick_usec <= tick_usec + 1;
end if;
end if;
end process;
cnt_usec_timer:
process(clk)
begin
if clk'event and clk='1' then
cnt_sec_en <= '0';
if rst = '1' then
cnt_usec <= (others => '0');
cnt_sec_en <= '0';
elsif cnt_usec_we = '1' then
cnt_usec <= cnt_usec_preset;
elsif cnt_usec_en = '1' then
if cnt_usec = to_unsigned(1E6 - 1, word_t'length) then
cnt_usec <= (others => '0');
cnt_sec_en <= '1';
else
cnt_usec <= cnt_usec + 1;
end if;
end if;
end if;
end process;
cnt_sec_timer:
process(clk)
begin
if clk'event and clk='1' then
if rst = '1' then
cnt_sec <= (others => '0');
elsif cnt_sec_we = '1' then
cnt_sec <= cnt_sec_preset;
elsif cnt_sec_en = '1' then
cnt_sec <= cnt_sec + 1;
end if;
end if;
end process;
baud_timer:
process(clk)
begin
if clk'event and clk='1' then
if rst = '1' then
baud_count <= (others => '0');
elsif baud_count = reg_uart_baud then
baud_count <= (others => '0');
en_16_x_baud <= '1';
else
baud_count <= baud_count + 1;
en_16_x_baud <= '0';
end if;
end if;
end process;
-- DDR SDRAM Controller Core
inst_sdram_ctrl_frontend : entity work.sdram_ctrl_frontend
Generic map
(
BL => BURST_LEN,
read_phaseshift => ddr_phaseshift,
f_sysclk => ddr_frequency_hz,
fifo_depth => 4
)
Port map
(
sys_rst_in => rst_in,
sys_clk_in => sys_clk_in,
sys_rst_out => rst,
sys_clk_out => clk,
sys_clk_fb => sys_sdr_clk_fb,
busy => sdr_busy_q,
en => sdr_en,
r_wn => mem_re_r,
be => sdr_be,
addr => sdr_addr,
din => sdr_udata_in,
dout => sdr_udata_out_q,
dout_re => sdr_read,
dout_vld => sdr_udata_vld_q,
-- SDRAM signals
sd_clk_p => sys_sdr_clk_p,
sd_clk_n => sys_sdr_clk_n,
sd_cke => sys_sdr_cke_q,
sd_cs_n => sys_sdr_cs_qn,
sd_cas_n => sys_sdr_cas_qn,
sd_ras_n => sys_sdr_ras_qn,
sd_we_n => sys_sdr_we_qn,
sd_addr => sys_sdr_a_q,
sd_ba => sys_sdr_ba_q,
sd_dm => sys_sdr_dm_q,
sd_dqs => sys_sdr_dqs_q,
sd_data => sys_sdr_data
);
STARTUP_VIRTEX4_inst : STARTUP_VIRTEX4
port map (
EOS => started_up, -- End of Startup 1-bit output
CLK => open, -- Clock input for start-up sequence
GSR => '0', -- Global Set/Reset input (GSR cannot be used for the port name)
GTS => '0', -- Global 3-state input (GTS cannot be used for the port name)
USRCCLKO => '0', -- USRCCLKO 1-bit input
USRCCLKTS => '0', -- USRCCLKTS 1-bit input
USRDONEO => '0', -- USRDONEO 1-bit input
USRDONETS => '0' -- USRDONETS 1-bit input
);
------------------------------------------------------------------
END;
+19
View File
@@ -0,0 +1,19 @@
library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
configuration cpu_irom of cpu_embedded is
for rtl
for inst_irom : irom
use entity work.irom(loadable);
end for;
end for;
end configuration cpu_irom;
configuration system_xrom of systest is
for behavior
for inst_xrom : xrom
use entity work.xrom(loadable);
end for;
end for;
end configuration system_xrom;
+716
View File
@@ -0,0 +1,716 @@
-------------------------------------------------------------------------
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
-- This file: 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;
use std.textio.all; -- Imports the standard textio package.
Library UNISIM;
use UNISIM.vcomponents.all;
library work;
use work.mips_types.all;
--use work.fifo_ctrl_pkg.all;
use work.sdram_config.all;
use work.sdram_types.all;
ENTITY mips_sys IS
GENERIC
(
sys_freq : integer := 100E6;
ddr_phaseshift : integer := 0;
ddr_frequency_hz : integer := 100E6
);
PORT
(
sys_rst_n_in : in std_logic;
sys_clk_in : in std_logic;
-- Buttons and LEDs
sys_btn : in unsigned(4 downto 0);
sys_dip : in unsigned(7 downto 0);
sys_led : out unsigned(8 downto 0);
-- UART
sys_rx : in std_logic;
sys_tx : out std_logic;
-- User ROM
sys_user_rom_addr : out word_t;
sys_user_rom_din : in word_t;
sys_user_rom_clk : out std_logic;
sys_user_rom_en : out std_logic;
-- LCD
sys_lcd_d : inout unsigned(3 downto 0);
sys_lcd_e : out std_logic;
sys_lcd_rs : out std_logic;
sys_lcd_rw : out std_logic;
-- DDR SDRAM
sys_sdr_clk_p : out std_logic; -- ddr_sdram_clock
sys_sdr_clk_n : out std_logic; -- /ddr_sdram_clock
sys_sdr_cke_q : out std_logic; -- clock enable
sys_sdr_cs_qn : out std_logic; -- /chip select
sys_sdr_ras_qn : out std_logic; -- /ras
sys_sdr_cas_qn : out std_logic; -- /cas
sys_sdr_we_qn : out std_logic; -- /write enable
sys_sdr_dm_q : out unsigned(DDR_DM_WIDTH-1 downto 0); -- data mask bits, set to "00"
sys_sdr_dqs_q : inout unsigned(DDR_DQS_WIDTH-1 downto 0); -- data strobe, only for write
sys_sdr_ba_q : out unsigned(DDR_BANK_WIDTH-1 downto 0); -- bank select
sys_sdr_a_q : out unsigned(DDR_ADDR_WIDTH-1 downto 0); -- address bus
sys_sdr_data : inout unsigned(DDR_DATA_WIDTH-1 downto 0); -- bidir data bus
sys_sdr_clk_fb : in std_logic;
-- VGA
-- sys_vga_red : out unsigned(7 downto 0);
-- sys_vga_green : out unsigned(7 downto 0);
-- sys_vga_blue : out unsigned(7 downto 0);
-- sys_vga_blank_n : out std_logic;
-- sys_vga_sync_n : out std_logic;
-- sys_vga_hsync : out std_logic;
-- sys_vga_vsync : out std_logic;
-- sys_vga_clk : out std_logic;
sys_error : out unsigned(1 downto 0) -- indicates Errors
);
-- attribute BUFFER_TYPE : string;
-- attribute BUFFER_TYPE of sys_clk_in : signal is "BUFG";
-- attribute BUFFER_TYPE of sys_sdr_dcm_clk_fb : signal is "BUFG";
END mips_sys;
ARCHITECTURE behavior OF mips_sys IS
COMPONENT mips_top
Port
(
rst : in STD_LOGIC;
clk : in STD_LOGIC;
int : in unsigned(5 downto 0);
mem_valid : in STD_LOGIC;
mem_rdy : in STD_LOGIC;
mem_re : out STD_LOGIC;
mem_en : out STD_LOGIC;
mem_we : out unsigned(3 downto 0);
mem_din : in word_t;
mem_dout : out word_t;
mem_addr : out word_t
);
END COMPONENT;
signal int : unsigned(5 downto 0);
signal mem_din : word_t;
signal mem_dout : word_t;
signal mem_addr : word_t;
signal mem_re : std_logic;
signal mem_en : std_logic;
signal mem_we : unsigned(3 downto 0);
signal mem_valid : std_logic;
signal mem_rdy : std_logic;
COMPONENT rom
Port
(
clk : in STD_LOGIC;
ce : in STD_LOGIC;
addr : in word_t;
dout : out word_t
);
END COMPONENT;
signal rom_data : word_t;
COMPONENT ram
PORT
(
clk : in STD_LOGIC;
ce : in STD_LOGIC;
we : in unsigned(3 downto 0);
addr : in unsigned(31 downto 0);
din : in unsigned(31 downto 0);
dout : out unsigned(31 downto 0)
);
END COMPONENT;
signal ram_data : word_t;
COMPONENT lcd_port
PORT (
rst : in std_logic;
clk : in std_logic;
we : in std_logic;
din : in unsigned(7 downto 0);
dout : out unsigned(7 downto 0);
lcd_d : inout unsigned(3 downto 0);
lcd_e : out std_logic;
lcd_rs : out std_logic;
lcd_rw : out std_logic
);
END COMPONENT;
COMPONENT uart_tx
Port
(
data_in : in std_logic_vector(7 downto 0);
write_buffer : in std_logic;
reset_buffer : in std_logic;
en_16_x_baud : in std_logic;
serial_out : out std_logic;
buffer_full : out std_logic;
buffer_half_full : out std_logic;
clk : in std_logic
);
END COMPONENT;
COMPONENT uart_rx
Port
(
serial_in : in std_logic;
data_out : out std_logic_vector(7 downto 0);
read_buffer : in std_logic;
reset_buffer : in std_logic;
en_16_x_baud : in std_logic;
buffer_data_present : out std_logic;
buffer_full : out std_logic;
buffer_half_full : out std_logic;
clk : in std_logic
);
END COMPONENT;
signal rst : std_logic;
signal rst_in : std_logic;
signal started_up : std_logic := '1';
signal clk : std_logic;
signal led_reg : unsigned(7 downto 0);
signal cpu_lcd_out_reg, cpu_lcd_in_reg, reg_uart_tx: unsigned(7 downto 0);
signal cpu_lcd_we : std_logic;
signal err_led_reg : unsigned(1 downto 0);
signal btn_ps2_reg : unsigned(7 downto 0);
-- Signals to form an timer generating an interrupt every microsecond
subtype tick_usec_t is natural range 0 to 99;
signal tick_usec : tick_usec_t;
signal cnt_usec : word_t;
signal cnt_sec : word_t;
signal cnt_usec_preset : word_t;
signal cnt_sec_preset : word_t;
signal cnt_usec_en : std_logic;
signal cnt_usec_we : std_logic;
signal cnt_sec_en : std_logic;
signal cnt_sec_we : std_logic;
-- Signals for UART connections
signal baud_count : unsigned(7 downto 0);
signal en_16_x_baud : std_logic;
signal reg_we_uart_tx : std_logic;
signal tx_full : std_logic;
signal tx_half_full : std_logic;
signal reg_re_uart_rx : std_logic;
signal reg_uart_rx : std_logic_vector(7 downto 0);
signal rx_data_present : std_logic;
signal rx_full : std_logic;
signal rx_half_full : std_logic;
signal uart_status_port : unsigned(7 downto 0);
signal reg_uart_ctrl : unsigned(7 downto 0);
signal reg_uart_baud : unsigned(7 downto 0);
-- DDR SDRAM
constant BURST_LEN : natural := 2;
subtype sdr_buf_t is unsigned(SDR_DATA_WIDTH-1 downto 0);
signal sdr_buf_in, sdr_vga_data : sdr_buf_t := (others => '0');
signal sdr_addr : user_addr_t;
signal sdr_busy_q : std_logic;
signal sdr_udata_in : unsigned(SDR_DATA_WIDTH-1 downto 0);
signal sdr_udata_req_wr : std_logic;
signal sdr_udata_out_q : unsigned(SDR_DATA_WIDTH-1 downto 0);
signal sdr_udata_vld_q : std_logic;
signal sdr_be : unsigned(SDR_DM_WIDTH-1 downto 0) := "00000000";
signal sdr_read : std_logic;
signal sdr_en : std_logic;
signal reg_data : word_t;
signal reg_data_vld : std_logic;
signal reg_en : std_logic;
signal rom_en : std_logic;
signal rom_data_vld : std_logic;
signal ram_en : std_logic;
signal ram_data_vld : std_logic;
signal urom_en : std_logic;
signal urom_data_vld : std_logic;
signal sdram_en : std_logic;
signal sd_counter : word_t;
signal mem_re_r : std_logic;
signal mem_we_r : unsigned(3 downto 0);
signal mem_dout_r : word_t;
signal mem_addr_r : word_t;
-- attribute rom_style: string;
-- attribute rom_style of cmd_fifo_dout: signal is "DISTRIBUTED";
-- attribute rom_style of cpu_cpu_write_fifo_dout: signal is "DISTRIBUTED";
-- attribute rom_style of cpu_read_fifo_dout: signal is "DISTRIBUTED";
type sd_ctrl_state_t is (s_sd_idle, s_sd_cpu_read, s_sd_cpu_read_fin, s_sd_cpu_write, s_sd_cpu_write_fin);
signal st, stn : sd_ctrl_state_t;
BEGIN
int <= "0000" & rx_data_present & btn_ps2_reg(4);
rst_in <= not (started_up and sys_rst_n_in);
en_mux:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
sdram_en <= '0';
else
urom_en <= '0';
reg_en <= '0';
rom_en <= '0';
ram_en <= '0';
-- sdram_en <= '0';
if mem_en = '1' then
mem_re_r <= mem_re;
mem_we_r <= mem_we;
mem_dout_r <= mem_dout;
mem_addr_r <= mem_addr;
if mem_addr(31 downto 28) = X"0" then
urom_en <= '1';
elsif mem_addr(31 downto 28) = X"A" then
reg_en <= '1';
elsif (mem_addr(31 downto 28) = X"B" and mem_addr(15) = '0') then
rom_en <= '1';
elsif (mem_addr(31 downto 28) = X"B" and mem_addr(15) = '1') then
ram_en <= '1';
elsif (mem_addr(31 downto 28) = X"8" or mem_addr(30) = '1') then
sdram_en <= '1';
end if;
elsif sdr_en = '1' then
sdram_en <= '0';
end if;
end if;
end if;
end process;
sys_user_rom_addr <= mem_addr_r;
sys_user_rom_clk <= clk;
sys_user_rom_en <= urom_en;
sdr_addr <= mem_addr_r(24 downto 2) & "0";
sdr_udata_in <= mem_dout_r & mem_dout_r;
sdr_be <= mem_we_r & mem_we_r;
sdr_read <= '1';
sdr_en <= sdram_en and not sdr_busy_q;
------------------------------------------------------------------
led_out:
process(rst, clk)
begin
if rst = '1' then
sys_led <= (others => '0');
sys_error <= (others => '0');
elsif rising_edge(clk) then
sys_led <= not mem_rdy & led_reg;
sys_error <= err_led_reg;
end if;
end process;
------------------------------------------------------------------
btn_ps2_register:
process(clk)
begin
if rising_edge(clk) then
btn_ps2_reg <= "000" & unsigned(sys_btn);
end if;
end process;
proc_sd_counter:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
sd_counter <= (others => '0');
elsif sdr_udata_vld_q = '1' then
sd_counter <= sd_counter + 1;
end if;
end if;
end process;
mem_valid <= sdr_udata_vld_q or reg_data_vld or rom_data_vld or urom_data_vld or ram_data_vld;
mem_din <= sdr_udata_out_q(mem_din'left downto mem_din'right) when sdr_udata_vld_q = '1' else
reg_data when reg_data_vld = '1' else
rom_data when rom_data_vld = '1' else
sys_user_rom_din when urom_data_vld = '1' else
ram_data when ram_data_vld = '1';
------------------------------------------------------------------
inst_rom: rom
PORT MAP
(
clk => clk,
ce => rom_en,
addr => mem_addr_r,
dout => rom_data
);
inst_ram: ram
PORT MAP
(
clk => clk,
ce => ram_en,
we => mem_we_r,
addr => mem_addr_r,
din => mem_dout_r,
dout => ram_data
);
ram_read:
process(clk)
begin
if rising_edge(clk) then
ram_data_vld <= '0';
if ram_en = '1' and mem_re_r = '1' then
ram_data_vld <= '1';
end if;
end if;
end process;
rom_read:
process(clk)
begin
if rising_edge(clk) then
rom_data_vld <= '0';
if rom_en = '1' and mem_re_r = '1' then
rom_data_vld <= '1';
end if;
end if;
end process;
urom_read:
process(clk)
begin
if rising_edge(clk) then
urom_data_vld <= '0';
if urom_en = '1' then
urom_data_vld <= '1';
end if;
end if;
end process;
registers_read:
process(clk)
begin
if rising_edge(clk) then
reg_data_vld <= '0';
reg_re_uart_rx <= '0';
if reg_en = '1' and mem_re_r = '1' then
reg_data_vld <= '1';
reg_data <= (others => '0');
case mem_addr_r(5 downto 2) is
when "0000" => null;
when "0001" =>
reg_re_uart_rx <= mem_re_r;
reg_data(7 downto 0) <= unsigned(reg_uart_rx);
when "0010" =>
reg_data(7 downto 0) <= uart_status_port;
reg_data(15 downto 8) <= reg_uart_baud;
reg_data(23 downto 16) <= btn_ps2_reg;
reg_data(31 downto 24) <= cpu_lcd_in_reg;
when "0100" =>
reg_data <= cnt_usec;
when "0101" =>
reg_data <= cnt_sec;
when others => null;
end case;
end if;
end if;
end process;
------------------------------------------------------------------
registers_write:
process(clk)
begin
if rising_edge(clk) then
cpu_lcd_we <= '0';
reg_we_uart_tx <= '0';
cnt_usec_we <= '0';
cnt_sec_we <= '0';
if rst = '1' then
led_reg <= (others => '0');
err_led_reg <= (others => '0');
cpu_lcd_out_reg <= (others => '0');
reg_uart_baud <= to_unsigned(53, 8);
reg_uart_ctrl <= to_unsigned(0, 8);
elsif reg_en = '1' then
case mem_addr_r(5 downto 2) is
when "0000" =>
if mem_we_r(0) = '1' then
led_reg(7 downto 0) <= mem_dout_r(7 downto 0);
end if;
if mem_we_r(3) = '1' then
err_led_reg <= mem_dout_r(31 downto 30);
end if;
when "0001" =>
if mem_we_r(0) = '1' then
reg_we_uart_tx <= '1';
reg_uart_tx <= mem_dout_r(7 downto 0);
end if;
when "0010" =>
if mem_we_r(0) = '1' then
reg_uart_ctrl <= mem_dout_r(7 downto 0);
end if;
if mem_we_r(1) = '1' then
reg_uart_baud <= mem_dout_r(15 downto 8);
end if;
if mem_we_r(3) = '1' then
cpu_lcd_we <= '1';
cpu_lcd_out_reg <= mem_dout_r(31 downto 24);
end if;
when "0100" =>
if mem_we_r(3) = '1' then
cnt_usec_we <= '1';
cnt_usec_preset <= mem_dout_r;
end if;
when "0101" =>
if mem_we_r(3) = '1' then
cnt_sec_we <= '1';
cnt_sec_preset <= mem_dout_r;
end if;
when others => null;
end case;
end if;
end if;
end process;
------------------------------------------------------------------
mem_rdy <= not sdr_busy_q;
------------------------------------------------------------------
inst_mips_top: mips_top
PORT MAP
(
rst => rst,
clk => clk,
int => int,
mem_valid => mem_valid,
mem_rdy => mem_rdy,
mem_en => mem_en,
mem_re => mem_re,
mem_we => mem_we,
mem_din => mem_din,
mem_dout => mem_dout,
mem_addr => mem_addr
);
inst_lcd_port: lcd_port
PORT MAP
(
rst => rst,
clk => clk,
we => cpu_lcd_we,
din => cpu_lcd_out_reg,
dout => cpu_lcd_in_reg,
lcd_d => sys_lcd_d,
lcd_e => sys_lcd_e,
lcd_rs => sys_lcd_rs,
lcd_rw => sys_lcd_rw
);
inst_uart_tx: uart_tx
port map
(
data_in => std_logic_vector(reg_uart_tx),
write_buffer => reg_we_uart_tx,
reset_buffer => rst,
en_16_x_baud => en_16_x_baud,
serial_out => sys_tx,
buffer_full => tx_full,
buffer_half_full => tx_half_full,
clk => clk
);
inst_uart_rx: uart_rx
port map
(
serial_in => sys_rx,
data_out => reg_uart_rx,
read_buffer => reg_re_uart_rx,
reset_buffer => rst,
en_16_x_baud => en_16_x_baud,
buffer_data_present => rx_data_present,
buffer_full => rx_full,
buffer_half_full => rx_half_full,
clk => clk
);
uart_status_port <= (7 downto 5 => '0') & rx_data_present & rx_full & rx_half_full & tx_full & tx_half_full;
tick_usec_timer:
process(clk)
begin
if clk'event and clk='1' then
cnt_usec_en <= '0';
if rst = '1' then
tick_usec <= 0;
cnt_usec_en <= '0';
elsif tick_usec = tick_usec_t'high then
tick_usec <= 0;
cnt_usec_en <= '1';
else
tick_usec <= tick_usec + 1;
end if;
end if;
end process;
cnt_usec_timer:
process(clk)
begin
if clk'event and clk='1' then
cnt_sec_en <= '0';
if rst = '1' then
cnt_usec <= (others => '0');
cnt_sec_en <= '0';
elsif cnt_usec_we = '1' then
cnt_usec <= cnt_usec_preset;
elsif cnt_usec_en = '1' then
if cnt_usec = to_unsigned(1E6 - 1, word_t'length) then
cnt_usec <= (others => '0');
cnt_sec_en <= '1';
else
cnt_usec <= cnt_usec + 1;
end if;
end if;
end if;
end process;
cnt_sec_timer:
process(clk)
begin
if clk'event and clk='1' then
if rst = '1' then
cnt_sec <= (others => '0');
elsif cnt_sec_we = '1' then
cnt_sec <= cnt_sec_preset;
elsif cnt_sec_en = '1' then
cnt_sec <= cnt_sec + 1;
end if;
end if;
end process;
baud_timer:
process(clk)
begin
if clk'event and clk='1' then
if rst = '1' then
baud_count <= (others => '0');
elsif baud_count = reg_uart_baud then
baud_count <= (others => '0');
en_16_x_baud <= '1';
else
baud_count <= baud_count + 1;
en_16_x_baud <= '0';
end if;
end if;
end process;
-- DDR SDRAM Controller Core
inst_sdram_ctrl_frontend : entity work.sdram_ctrl_frontend
Generic map
(
BL => BURST_LEN,
read_phaseshift => ddr_phaseshift,
f_sysclk => ddr_frequency_hz,
fifo_depth => 4
)
Port map
(
sys_rst_in => rst_in,
sys_clk_in => sys_clk_in,
sys_rst_out => rst,
sys_clk_out => clk,
sys_clk_fb => sys_sdr_clk_fb,
busy => sdr_busy_q,
en => sdr_en,
r_wn => mem_re_r,
be => sdr_be,
addr => sdr_addr,
din => sdr_udata_in,
dout => sdr_udata_out_q,
dout_re => sdr_read,
dout_vld => sdr_udata_vld_q,
-- SDRAM signals
sd_clk_p => sys_sdr_clk_p,
sd_clk_n => sys_sdr_clk_n,
sd_cke => sys_sdr_cke_q,
sd_cs_n => sys_sdr_cs_qn,
sd_cas_n => sys_sdr_cas_qn,
sd_ras_n => sys_sdr_ras_qn,
sd_we_n => sys_sdr_we_qn,
sd_addr => sys_sdr_a_q,
sd_ba => sys_sdr_ba_q,
sd_dm => sys_sdr_dm_q,
sd_dqs => sys_sdr_dqs_q,
sd_data => sys_sdr_data
);
STARTUP_VIRTEX4_inst : STARTUP_VIRTEX4
port map (
EOS => started_up, -- End of Startup 1-bit output
CLK => open, -- Clock input for start-up sequence
GSR => '0', -- Global Set/Reset input (GSR cannot be used for the port name)
GTS => '0', -- Global 3-state input (GTS cannot be used for the port name)
USRCCLKO => '0', -- USRCCLKO 1-bit input
USRCCLKTS => '0', -- USRCCLKTS 1-bit input
USRDONEO => '0', -- USRDONEO 1-bit input
USRDONETS => '0' -- USRDONETS 1-bit input
);
------------------------------------------------------------------
END;
+173
View File
@@ -0,0 +1,173 @@
-------------------------------------------------------------------------
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
-- This file: The ROM file for use in your VHDL design
--
-- 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 UNISIM;
use UNISIM.VComponents.all;
ENTITY ram IS
Port
(
clk : in STD_LOGIC;
ce : in STD_LOGIC;
we : in unsigned(3 downto 0);
addr : in unsigned(31 downto 0);
din : in unsigned(31 downto 0);
dout : out unsigned(31 downto 0)
);
END ram;
ARCHITECTURE behavior OF ram IS
COMPONENT dpram_2w2r
Generic
(
addr_width : integer;
data_width : integer
);
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;
signal jtag_clk : STD_LOGIC;
signal jtag_we : unsigned(3 downto 0);
signal jtag_addr : unsigned (15 downto 0);
signal jtag_dout : unsigned (31 downto 0);
signal jtag_din : unsigned (31 downto 0);
signal bs_rst, bs_sel, bs_shift, bs_tdi, bs_tdo : std_logic;
signal bs_capture, bs_clk0, bs_clk1, bs_update0, bs_update1 : std_logic;
signal user_regi, user_rego : unsigned (47 downto 0);
BEGIN
gen_sram:
for i in 0 to 3 generate
begin
inst_dpram_2w2r : dpram_2w2r
GENERIC MAP
(
addr_width => 11,
data_width => 8
)
PORT MAP
(
clk_a => clk,
en_a => ce,
we_a => we(i),
addr_a => addr(12 downto 2),
din_a => din((i+1)*8-1 downto i*8),
dout_a => dout((i+1)*8-1 downto i*8),
clk_b => jtag_clk,
en_b => jtag_we(i),
we_b => jtag_we(i),
addr_b => jtag_addr(10 downto 0),
din_b => jtag_din((i+1)*8-1 downto i*8),
dout_b => jtag_dout((i+1)*8-1 downto i*8)
);
end generate;
--------------------------------------------------------------------------
-- Virtex-4: JTAG Loader
--------------------------------------------------------------------------
i00_BUFG : BUFG
port map
(
O => bs_clk1,
I => bs_clk0
);
i01_BUFG : BUFG
port map
(
O => bs_update1,
I => bs_update0
);
BSCAN_VIRTEX4_inst2 : BSCAN_VIRTEX4
generic map
(
JTAG_CHAIN => 2 -- Value to set BSCAN site of device. Possible values: (1,2,3 or 4)
)
port map
(
CAPTURE => bs_capture, -- CAPTURE output from TAP controller
DRCK => bs_clk0, -- Data register output for USER functions
RESET => bs_rst, -- Reset output from TAP controller
SEL => bs_sel, -- USER active output
SHIFT => bs_shift, -- SHIFT output from TAP controller
TDI => bs_tdi, -- TDI output from TAP controller
UPDATE => bs_update0, -- UPDATE output from TAP controller
TDO => bs_tdo -- Data input for USER function
);
jtag_addr <= user_regi(user_regi'left downto jtag_dout'length);
jtag_din <= user_regi(jtag_dout'length-1 downto 0);
jtag_clk <= bs_update1;
jtag_we <= (3 downto 0 => bs_sel);
sipo:
process (bs_rst, bs_clk1, bs_tdi, bs_shift)
begin
if bs_rst = '1' then
user_regi <= (others => '0');
elsif rising_edge(bs_clk1) then
if bs_shift = '1' then
user_regi <= bs_tdi & user_regi(user_regi'left downto 1);
end if;
end if;
end process;
piso:
process (bs_rst, bs_clk1, bs_shift, user_rego)
begin
bs_tdo <= user_rego(0);
if bs_rst = '1' then
user_rego <= (others => '0');
elsif rising_edge(bs_clk1) then
if bs_shift = '1' then
user_rego <= user_rego(0) & user_rego(user_rego'left downto 1);
else
user_rego <= (user_rego'left downto jtag_dout'length => '0') & jtag_dout;
end if;
end if;
end process;
--------------------------------------------------------------------------
end behavior;
+88
View File
@@ -0,0 +1,88 @@
-------------------------------------------------------------------------
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
-- This file: The ROM file for use in your VHDL design
--
-- 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;
ENTITY ram IS
Generic
(
word_addr_width : integer := 6
);
Port
(
clk : in STD_LOGIC;
ce : in STD_LOGIC;
we : in unsigned(3 downto 0);
addr : in unsigned(31 downto 0);
din : in unsigned(31 downto 0);
dout : out unsigned(31 downto 0)
);
END ram;
ARCHITECTURE behavior OF ram IS
constant depth : natural := 2**word_addr_width;
type sram_t is array (0 to depth-1) of unsigned(31 downto 0);
function sram_clear return sram_t is
variable result : sram_t;
begin
for i in 0 to sram_t'length-1 loop
result(i) := (others => '0');
end loop;
return result;
end sram_clear;
signal sram : sram_t := sram_clear;
BEGIN
SRAM_RW:
process(clk)
variable index : natural range 0 to depth-1;
begin
if rising_edge(clk) and ce = '1' then
index := to_integer(addr(word_addr_width+1 downto 2));
if we(0) = '1' then
sram(index)(7 downto 0) <= din(7 downto 0);
end if;
if we(1) = '1' then
sram(index)(15 downto 8) <= din(15 downto 8);
end if;
if we(2) = '1' then
sram(index)(23 downto 16) <= din(23 downto 16);
end if;
if we(3) = '1' then
sram(index)(31 downto 24) <= din(31 downto 24);
end if;
dout <= sram(index);
end if;
end process;
end behavior;
+74
View File
@@ -0,0 +1,74 @@
-------------------------------------------------------------------------
-- Project: SDRAM controller
-- This file: User SDRAM component adjustments
--
-- 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;
package sdram_config is
constant DDR_DATA_WIDTH : positive := 32; -- External DDR-SDRAM Module data bus width
constant DDR_ADDR_WIDTH : positive := 13; -- number of address lines to DDR-SDRAM Device/Module
constant DDR_BANK_WIDTH : positive := 2; -- Number of BANK address lines of external DDR-SDRAM
constant DDR_ROW_ADDR_WIDTH : positive := 13; --
constant DDR_COL_ADDR_WIDTH : positive := 9; --
constant LMR_REG_BASE : natural := 0;
constant LMR_REG_EXTENDED : natural := 1;
constant LMR_OP_NORMAL : natural := 0;
constant LMR_OP_RES_DLL : natural := 2;
constant LMR_BT_SEQ : natural := 0;
constant LMR_BT_ILVD : natural := 1;
constant LMR_BL2 : natural := 1;
constant LMR_BL4 : natural := 2;
constant LMR_BL8 : natural := 3;
constant LMR_CL2 : natural := 2;
constant LMR_CL3 : natural := 3;
constant LMR_CL2_5 : natural := 6;
-- DDR SDRAM Hardware defined constants
constant BIT_AUTO_PRE : positive := 10; -- bit-position in column address for auto precharge (see Data Sheet)
constant BIT_PRE_ALL : positive := 10; -- bit-position in column address for precharge all (see Data Sheet)
constant ENABLE_PRE_ALL : std_logic := '1';
constant ENABLE_AUTO_PRE : std_logic := '0';
-- DDR-SDR TIMING constants ------------------------------------------------------------------
-- After REFRESH_CLOCKS a refresh cycle is necessary, 64ms / 8192 = max every 7.8125 us refesh
constant REFRESH_INTERVAL : real := 7.8125; -- us
-- These values are for your SDRAM part (see datasheet)
constant TCAS : positive := 2; -- CAS latency [clocks]
constant TRP : positive := 2; -- precharge command period
constant TRAS : positive := 5; -- active to precharge delay
constant TRFC : positive := 8; -- auto refresh command period
constant TMRD : positive := 2; -- load mode register command cylce time
constant TRCD : positive := 2; -- active to read or write delay !
constant TWR : positive := 2; -- write recovery time
constant PWR_UP_WAIT : natural := 222; -- µs
subtype user_tag_t is unsigned(3 downto 0);
----------------------------------------------------------------------------------------------
end sdram_config;
@@ -0,0 +1,74 @@
-------------------------------------------------------------------------
-- Project: SDRAM controller
-- This file: User SDRAM component adjustments
--
-- 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;
package sdram_config is
constant DDR_DATA_WIDTH : positive := 32; -- External DDR-SDRAM Module data bus width
constant DDR_ADDR_WIDTH : positive := 13; -- number of address lines to DDR-SDRAM Device/Module
constant DDR_BANK_WIDTH : positive := 2; -- Number of BANK address lines of external DDR-SDRAM
constant DDR_ROW_ADDR_WIDTH : positive := 13; --
constant DDR_COL_ADDR_WIDTH : positive := 9; --
constant LMR_REG_BASE : natural := 0;
constant LMR_REG_EXTENDED : natural := 1;
constant LMR_OP_NORMAL : natural := 0;
constant LMR_OP_RES_DLL : natural := 2;
constant LMR_BT_SEQ : natural := 0;
constant LMR_BT_ILVD : natural := 1;
constant LMR_BL2 : natural := 1;
constant LMR_BL4 : natural := 2;
constant LMR_BL8 : natural := 3;
constant LMR_CL2 : natural := 2;
constant LMR_CL3 : natural := 3;
constant LMR_CL2_5 : natural := 6;
-- DDR SDRAM Hardware defined constants
constant BIT_AUTO_PRE : positive := 10; -- bit-position in column address for auto precharge (see Data Sheet)
constant BIT_PRE_ALL : positive := 10; -- bit-position in column address for precharge all (see Data Sheet)
constant ENABLE_PRE_ALL : std_logic := '1';
constant ENABLE_AUTO_PRE : std_logic := '0';
-- DDR-SDR TIMING constants ------------------------------------------------------------------
-- After REFRESH_CLOCKS a refresh cycle is necessary, 64ms / 8192 = max every 7.8125 us refesh
constant REFRESH_INTERVAL : real := 7.8125; -- us
-- These values are for your SDRAM part (see datasheet)
constant TCAS : positive := 2; -- CAS latency [clocks]
constant TRP : positive := 2; -- precharge command period
constant TRAS : positive := 5; -- active to precharge delay
constant TRFC : positive := 8; -- auto refresh command period
constant TMRD : positive := 2; -- load mode register command cylce time
constant TRCD : positive := 2; -- active to read or write delay !
constant TWR : positive := 2; -- write recovery time
constant PWR_UP_WAIT : natural := 22; -- µs
subtype user_tag_t is unsigned(3 downto 0);
----------------------------------------------------------------------------------------------
end sdram_config;
+208
View File
@@ -0,0 +1,208 @@
-------------------------------------------------------------------------
-- 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;
use std.textio.all; -- Imports the standard textio package.
library work;
use work.mips_types.all;
use work.sdram_config.all;
use work.sdram_types.all;
ENTITY tb_mips_sys IS
END tb_mips_sys;
ARCHITECTURE behavior OF tb_mips_sys IS
constant CLK_PERIOD : time := 10 ns;
signal sys_rst_n_in : std_logic := '0';
signal sys_clk_in : std_logic := '1';
signal dip : unsigned(7 downto 0) := (others => '0');
signal btn : unsigned(4 downto 0) := (others => '0');
signal led : unsigned(8 downto 0);
signal sys_rx : std_logic := '1';
signal sys_tx : std_logic;
signal sys_lcd_d : unsigned(3 downto 0);
signal sys_lcd_e : std_logic;
signal sys_lcd_rs : std_logic;
signal sys_lcd_rw : std_logic;
signal refresh : boolean:= true;
signal sys_sdr_clk_p : std_logic; -- ddr_sdram_clock
signal sys_sdr_clk_n : std_logic; -- /ddr_sdram_clock
signal sys_sdr_cke_q : std_logic; -- clock enable
signal sys_sdr_cs_qn : std_logic; -- /chip select
signal sys_sdr_ras_qn : std_logic; -- /ras
signal sys_sdr_cas_qn : std_logic; -- /cas
signal sys_sdr_we_qn : std_logic; -- /write enable
signal sys_sdr_dm_q : unsigned(DDR_DM_WIDTH-1 downto 0); -- data mask bits, set to "00"
signal sys_sdr_dqs_q : unsigned(DDR_DQS_WIDTH-1 downto 0); -- data strobe, only for write
signal sys_sdr_ba_q : unsigned(DDR_BANK_WIDTH-1 downto 0); -- bank select
signal sys_sdr_a_q : unsigned(DDR_ADDR_WIDTH-1 downto 0); -- address bus
signal sys_sdr_data : unsigned(DDR_DATA_WIDTH-1 downto 0); -- bidir data bus
signal sys_error : unsigned(1 downto 0); -- indicates DCM Errors
signal sys_sdr_clk_fb : std_logic;
constant UROM_ADDR_WIDTH : integer := 18;
signal sys_user_rom_clk : std_logic;
signal sys_user_rom_en : std_logic;
signal sys_user_rom_din : word_t;
signal sys_user_rom_addr : word_t;
type urom_data_t is array (natural range 0 to 2**(UROM_ADDR_WIDTH-2)-1) of word_t;
signal urom_data : urom_data_t;
BEGIN
uut: entity work.mips_sys
-- GENERIC MAP
-- (
-- ddr_phaseshift => 90,
-- ddr_frequency_hz => 100E6
-- )
PORT MAP
(
sys_rst_n_in => sys_rst_n_in,
sys_clk_in => sys_clk_in,
sys_btn => btn,
sys_dip => dip,
sys_led => led,
sys_rx => sys_rx,
sys_tx => sys_tx,
sys_lcd_d => sys_lcd_d,
sys_lcd_e => sys_lcd_e,
sys_lcd_rs => sys_lcd_rs,
sys_lcd_rw => sys_lcd_rw,
sys_user_rom_addr => sys_user_rom_addr,
sys_user_rom_din => sys_user_rom_din,
sys_user_rom_en => sys_user_rom_en,
sys_user_rom_clk => sys_user_rom_clk,
sys_sdr_clk_p => sys_sdr_clk_p,
sys_sdr_clk_n => sys_sdr_clk_n,
sys_sdr_cke_q => sys_sdr_cke_q,
sys_sdr_clk_fb => sys_sdr_clk_fb,
sys_sdr_cs_qn => sys_sdr_cs_qn,
sys_sdr_ras_qn => sys_sdr_ras_qn,
sys_sdr_cas_qn => sys_sdr_cas_qn,
sys_sdr_we_qn => sys_sdr_we_qn,
sys_sdr_dm_q => sys_sdr_dm_q,
sys_sdr_dqs_q => sys_sdr_dqs_q,
sys_sdr_ba_q => sys_sdr_ba_q,
sys_sdr_a_q => sys_sdr_a_q,
sys_sdr_data => sys_sdr_data,
sys_error => sys_error
);
-- MICRON DDR SDRAM Simulation Model
i_mt46v16m16_0 : entity work.mt46v16m16
port map (
dq => std_logic_vector(sys_sdr_data(15 downto 0)),
dqs => std_logic_vector(sys_sdr_dqs_q(1 downto 0)),
addr => std_logic_vector(sys_sdr_a_q),
ba => std_logic_vector(sys_sdr_ba_q),
clk => sys_sdr_clk_p,
clk_n => sys_sdr_clk_n,
cke => sys_sdr_cke_q,
cs_n => sys_sdr_cs_qn,
ras_n => sys_sdr_ras_qn,
cas_n => sys_sdr_cas_qn,
we_n => sys_sdr_we_qn,
dm => std_logic_vector(sys_sdr_dm_q(1 downto 0))
);
-- MICRON DDR SDRAM Simulation Model
i_mt46v16m16_1 : entity work.mt46v16m16
port map (
dq => std_logic_vector(sys_sdr_data(31 downto 16)),
dqs => std_logic_vector(sys_sdr_dqs_q(3 downto 2)),
addr => std_logic_vector(sys_sdr_a_q),
ba => std_logic_vector(sys_sdr_ba_q),
clk => sys_sdr_clk_p,
clk_n => sys_sdr_clk_n,
cke => sys_sdr_cke_q,
cs_n => sys_sdr_cs_qn,
ras_n => sys_sdr_ras_qn,
cas_n => sys_sdr_cas_qn,
we_n => sys_sdr_we_qn,
dm => std_logic_vector(sys_sdr_dm_q(3 downto 2))
);
sys_sdr_clk_fb <= sys_sdr_clk_p after 2300 ps;
refresh <= true when falling_edge(sys_sdr_ras_qn) and falling_edge(sys_sdr_cas_qn) and sys_sdr_we_qn='1' else false;
CLK_GEN: process
begin
wait for CLK_PERIOD/2;
sys_clk_in <= not sys_clk_in;
end process;
UROM_READ: process(sys_rst_n_in, sys_user_rom_clk)
type file_t is file of integer;
file load_urom : file_t open read_mode is "test_dcache.bin";
variable instr : integer;
variable index : natural;
variable temp : signed(31 downto 0);
begin
if sys_rst_n_in = '0' then
index := 0;
while not endfile(load_urom) loop
read(load_urom, instr);
temp := to_signed(instr, word_t'length);
urom_data(index) <= unsigned(temp);
index := index + 1;
end loop;
elsif rising_edge(sys_user_rom_clk) and sys_user_rom_en = '1' then
index := to_integer(sys_user_rom_addr(UROM_ADDR_WIDTH+1 downto 2));
sys_user_rom_din <= urom_data(index);
end if;
end process;
STIMULUS: process
begin
wait for 3*CLK_PERIOD;
sys_rst_n_in <= '1';
wait for 200000*CLK_PERIOD;
loop
wait for 251*CLK_PERIOD;
btn(4) <= '1';
wait for 311*CLK_PERIOD;
btn(4) <= '0';
end loop;
wait;
end process;
END;