URL
https://opencores.org/ocsvn/plasma/plasma/trunk
Subversion Repositories plasma
Compare Revisions
- This comparison shows the changes necessary to convert path
/plasma/tags/arelease/vhdl
- from Rev 350 to Rev 352
- ↔ Reverse comparison
Rev 350 → Rev 352
/mips_cpu.vhd
0,0 → 1,302
--------------------------------------------------------------------- |
-- TITLE: MIPS CPU core |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 2/15/01 |
-- FILENAME: mips_cpu.vhd |
-- PROJECT: MIPS CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Top level VHDL document that ties the eight other entities together. |
-- Implements a MIPS CPU. Based on information found in: |
-- "MIPS RISC Architecture" by Gerry Kane and Joe Heinrich |
-- and "The Designer's Guide to VHDL" by Peter J. Ashenden |
-- An add instruction would take the following steps (see cpu.gif): |
-- 1. The "pc_next" entity would have previously passed the program |
-- counter (PC) to the "mem_ctrl" entity. |
-- 2. "Mem_ctrl" passes the opcode to the "control" entity. |
-- 3. "Control" converts the 32-bit opcode to a 60-bit VLWI opcode |
-- and sends control signals to the other entities. |
-- 4. Based on the rs_index and rt_index control signals, "reg_bank" |
-- sends the 32-bit reg_source and reg_target to "bus_mux". |
-- 5. Based on the a_source and b_source control signals, "bus_mux" |
-- multiplexes reg_source onto a_bus and reg_target onto b_bus. |
-- 6. Based on the alu_func control signals, "alu" adds the values |
-- from a_bus and b_bus and places the result on c_bus. |
-- 7. Based on the c_source control signals, "bus_bux" multiplexes |
-- c_bus onto reg_dest. |
-- 8. Based on the rd_index control signal, "reg_bank" saves |
-- reg_dest into the correct register. |
-- The CPU is implemented as a two stage pipeline with step #1 in the |
-- first stage and steps #2-8 occuring the second stage. |
-- |
-- The CPU core was synthesized for 0.13 um line widths with an area |
-- of 0.2 millimeters squared. The maximum latency was less than 6 ns |
-- for a maximum clock speed of 150 MHz. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mips_pack.all; |
|
entity mips_cpu is |
port(clk : in std_logic; |
reset_in : in std_logic; |
intr_in : in std_logic; |
|
mem_address : out std_logic_vector(31 downto 0); |
mem_data_w : out std_logic_vector(31 downto 0); |
mem_data_r : in std_logic_vector(31 downto 0); |
mem_sel : out std_logic_vector(3 downto 0); |
mem_write : out std_logic; |
mem_pause : in std_logic; |
|
t_pc : out std_logic_vector(31 downto 0); |
t_opcode : out std_logic_vector(31 downto 0); |
t_r_dest : out std_logic_vector(31 downto 0) |
); |
end; --entity mips_cpu |
|
architecture logic of mips_cpu is |
|
component pc_next |
port(clk : in std_logic; |
reset_in : in std_logic; |
pc_new : in std_logic_vector(31 downto 2); |
take_branch : in std_logic; |
pause_in : in std_logic; |
opcode25_0 : in std_logic_vector(25 downto 0); |
pc_source : in pc_source_type; |
pc_out : out std_logic_vector(31 downto 0)); |
end component; |
|
component mem_ctrl |
port(clk : in std_logic; |
reset_in : in std_logic; |
pause_in : in std_logic; |
nullify_op : in std_logic; |
address_pc : in std_logic_vector(31 downto 0); |
opcode_out : out std_logic_vector(31 downto 0); |
|
address_data : in std_logic_vector(31 downto 0); |
mem_source : in mem_source_type; |
data_write : in std_logic_vector(31 downto 0); |
data_read : out std_logic_vector(31 downto 0); |
pause_out : out std_logic; |
|
mem_address : out std_logic_vector(31 downto 0); |
mem_data_w : out std_logic_vector(31 downto 0); |
mem_data_r : in std_logic_vector(31 downto 0); |
mem_byte_sel : out std_logic_vector(3 downto 0); |
mem_write : out std_logic; |
mem_pause : in std_logic); |
end component; |
|
component control |
port(opcode : in std_logic_vector(31 downto 0); |
intr_signal : in std_logic; |
rs_index : out std_logic_vector(5 downto 0); |
rt_index : out std_logic_vector(5 downto 0); |
rd_index : out std_logic_vector(5 downto 0); |
imm_out : out std_logic_vector(15 downto 0); |
alu_func : out alu_function_type; |
shift_func : out shift_function_type; |
mult_func : out mult_function_type; |
branch_func : out branch_function_type; |
a_source_out : out a_source_type; |
b_source_out : out b_source_type; |
c_source_out : out c_source_type; |
pc_source_out: out pc_source_type; |
mem_source_out:out mem_source_type); |
end component; |
|
component reg_bank |
port(clk : in std_logic; |
rs_index : in std_logic_vector(5 downto 0); |
rt_index : in std_logic_vector(5 downto 0); |
rd_index : in std_logic_vector(5 downto 0); |
reg_source_out : out std_logic_vector(31 downto 0); |
reg_target_out : out std_logic_vector(31 downto 0); |
reg_dest_new : in std_logic_vector(31 downto 0); |
intr_enable : out std_logic); |
end component; |
|
component bus_mux |
port(imm_in : in std_logic_vector(15 downto 0); |
reg_source : in std_logic_vector(31 downto 0); |
a_mux : in a_source_type; |
a_out : out std_logic_vector(31 downto 0); |
|
reg_target : in std_logic_vector(31 downto 0); |
b_mux : in b_source_type; |
b_out : out std_logic_vector(31 downto 0); |
|
c_bus : in std_logic_vector(31 downto 0); |
c_memory : in std_logic_vector(31 downto 0); |
c_pc : in std_logic_vector(31 downto 0); |
c_mux : in c_source_type; |
reg_dest_out : out std_logic_vector(31 downto 0); |
|
branch_func : in branch_function_type; |
take_branch : out std_logic); |
end component; |
|
component alu |
port(a_in : in std_logic_vector(31 downto 0); |
b_in : in std_logic_vector(31 downto 0); |
alu_function : in alu_function_type; |
c_alu : out std_logic_vector(31 downto 0)); |
end component; |
|
component shifter |
port(value : in std_logic_vector(31 downto 0); |
shift_amount : in std_logic_vector(4 downto 0); |
shift_func : in shift_function_type; |
c_shift : out std_logic_vector(31 downto 0)); |
end component; |
|
component mult |
port(clk : in std_logic; |
a, b : in std_logic_vector(31 downto 0); |
mult_func : in mult_function_type; |
c_mult : out std_logic_vector(31 downto 0); |
pause_out : out std_logic); |
end component; |
|
signal opcode : std_logic_vector(31 downto 0); |
signal rs_index, rt_index, rd_index : std_logic_vector(5 downto 0); |
signal reg_source, reg_target, reg_dest : std_logic_vector(31 downto 0); |
signal a_bus, b_bus, c_bus : std_logic_vector(31 downto 0); |
signal c_alu, c_shift, c_mult, c_memory |
: std_logic_vector(31 downto 0); |
signal imm : std_logic_vector(15 downto 0); |
signal pc : std_logic_vector(31 downto 0); |
signal alu_function : alu_function_type; |
signal shift_function : shift_function_type; |
signal mult_function : mult_function_type; |
signal branch_function: branch_function_type; |
signal take_branch : std_logic; |
signal a_source : a_source_type; |
signal b_source : b_source_type; |
signal c_source : c_source_type; |
signal pc_source : pc_source_type; |
signal mem_source : mem_source_type; |
signal pause_mult : std_logic; |
signal pause_memory : std_logic; |
signal pause : std_logic; |
signal nullify_op : std_logic; |
signal intr_enable : std_logic; |
signal intr_signal : std_logic; |
-- signal mem_byte_sel : std_logic_vector(3 downto 0); |
-- signal mem_write : std_logic; |
begin --architecture |
|
pause <= pause_mult or pause_memory; |
--nulify_op = pc_source==from_lbranch && take_branch=='0' |
nullify_op <= pc_source(1) and pc_source(0) and not take_branch; |
c_bus <= c_alu or c_shift or c_mult; |
intr_signal <= (intr_in and intr_enable) and |
(not pc_source(0) and not pc_source(1)); --from_inc4 |
|
u1: pc_next PORT MAP ( |
clk => clk, |
reset_in => reset_in, |
take_branch => take_branch, |
pause_in => pause, |
pc_new => c_alu(31 downto 2), |
opcode25_0 => opcode(25 downto 0), |
pc_source => pc_source, |
pc_out => pc); |
|
u2: mem_ctrl PORT MAP ( |
clk => clk, |
reset_in => reset_in, |
pause_in => pause, |
nullify_op => nullify_op, |
address_pc => pc, |
opcode_out => opcode, |
|
address_data => c_alu, |
mem_source => mem_source, |
data_write => reg_target, |
data_read => c_memory, |
pause_out => pause_memory, |
|
mem_address => mem_address, |
mem_data_w => mem_data_w, |
mem_data_r => mem_data_r, |
mem_byte_sel => mem_sel, |
mem_write => mem_write, |
mem_pause => mem_pause); |
|
u3: control PORT MAP ( |
opcode => opcode, |
intr_signal => intr_signal, |
rs_index => rs_index, |
rt_index => rt_index, |
rd_index => rd_index, |
imm_out => imm, |
alu_func => alu_function, |
shift_func => shift_function, |
mult_func => mult_function, |
branch_func => branch_function, |
a_source_out => a_source, |
b_source_out => b_source, |
c_source_out => c_source, |
pc_source_out=> pc_source, |
mem_source_out=> mem_source); |
|
u4: reg_bank port map ( |
clk => clk, |
rs_index => rs_index, |
rt_index => rt_index, |
rd_index => rd_index, |
reg_source_out => reg_source, |
reg_target_out => reg_target, |
reg_dest_new => reg_dest, |
intr_enable => intr_enable); |
|
u5: bus_mux port map ( |
imm_in => imm, |
reg_source => reg_source, |
a_mux => a_source, |
a_out => a_bus, |
|
reg_target => reg_target, |
b_mux => b_source, |
b_out => b_bus, |
|
c_bus => c_bus, |
c_memory => c_memory, |
c_pc => pc, |
c_mux => c_source, |
reg_dest_out => reg_dest, |
|
branch_func => branch_function, |
take_branch => take_branch); |
|
u6: alu port map ( |
a_in => a_bus, |
b_in => b_bus, |
alu_function => alu_function, |
c_alu => c_alu); |
|
u7: shifter port map ( |
value => b_bus, |
shift_amount => a_bus(4 downto 0), |
shift_func => shift_function, |
c_shift => c_shift); |
|
u8: mult port map ( |
clk => clk, |
a => a_bus, |
b => b_bus, |
mult_func => mult_function, |
c_mult => c_mult, |
pause_out => pause_mult); |
|
t_pc <= pc; |
t_opcode <= opcode; |
t_r_dest <= reg_dest; |
|
end; --architecture logic |
|
/ram.vhd
0,0 → 1,113
--------------------------------------------------------------------- |
-- TITLE: Random Access Memory |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 4/21/01 |
-- FILENAME: ram.vhd |
-- PROJECT: MIPS CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Implements the RAM, reads the executable from "code.txt", |
-- and saves a character to "output.txt" upon a write to 0xffff. |
-- Modified from "The Designer's Guide to VHDL" by Peter J. Ashenden |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_misc.all; |
use ieee.std_logic_arith.all; |
use ieee.std_logic_textio.all; |
use std.textio.all; |
|
use ieee.std_logic_unsigned.all; |
use work.mips_pack.all; |
|
entity ram is |
generic(load_file_name : string); |
port(clk : in std_logic; |
mem_byte_sel : in std_logic_vector(3 downto 0); |
mem_write : in std_logic; |
mem_address : in std_logic_vector; |
mem_data_w : in std_logic_vector(31 downto 0); |
mem_data_r : out std_logic_vector(31 downto 0)); |
end; --entity ram |
|
architecture logic of ram is |
begin |
|
ram_proc: process |
variable data : std_logic_vector(31 downto 0); |
variable d : std_logic_vector(31 downto 0); |
variable datab : std_logic_vector(31 downto 0); |
variable value : natural; |
subtype word is std_logic_vector(mem_data_w'length-1 downto 0); |
type storage_array is |
array(natural range 0 to 2**mem_address'length-1) of word; |
variable storage : storage_array; |
variable index : natural; |
file load_file : text is in load_file_name; |
file store_file : text is out "output.txt"; |
variable hex_file_line : line; |
variable c : character; |
variable line_length : natural := 0; |
begin |
--load in the ram executable image |
index := 0; |
while not endfile(load_file) loop |
readline(load_file, hex_file_line); |
hread(hex_file_line, data); |
storage(index) := data; |
index := index + 1; |
end loop; |
assert false report "done reading code" severity note; |
|
wait on clk; --wait for line noise to go away |
|
loop |
wait on clk, mem_address, mem_write; |
|
--support putchar() when writing to address 0xffff |
if rising_edge(clk) then |
if mem_write = '1' and mem_address = ONES(15 downto 0) then |
index := conv_integer(mem_data_w(6 downto 0)); |
if index /= 10 then |
c := character'val(index); |
write(hex_file_line, c); |
line_length := line_length + 1; |
end if; |
if index = 10 or line_length >= 72 then |
writeline(store_file, hex_file_line); |
line_length := 0; |
end if; |
end if; |
end if; |
|
index := conv_integer(mem_address(mem_address'length-1 downto 2)); |
data := storage(index); |
|
if mem_write = '0' then |
mem_data_r <= data; |
end if; |
if mem_byte_sel(0) = '1' then |
data(7 downto 0) := mem_data_w(7 downto 0); |
end if; |
if mem_byte_sel(1) = '1' then |
data(15 downto 8) := mem_data_w(15 downto 8); |
end if; |
if mem_byte_sel(2) = '1' then |
data(23 downto 16) := mem_data_w(23 downto 16); |
end if; |
if mem_byte_sel(3) = '1' then |
data(31 downto 24) := mem_data_w(31 downto 24); |
end if; |
|
if rising_edge(clk) then |
if mem_write = '1' then |
storage(index) := data; |
end if; |
end if; |
end loop; |
end process; |
|
end; --architecture logic |
|
|
/control.vhd
0,0 → 1,440
--------------------------------------------------------------------- |
-- TITLE: Controller / Opcode Decoder |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 2/8/01 |
-- FILENAME: control.vhd |
-- PROJECT: MIPS CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Controls the CPU by decoding the opcode and generating control |
-- signals to the rest of the CPU. |
-- This entity decodes the MIPS opcode into a Very-Long-Word-Instruction. |
-- The 32-bit opcode is converted to a |
-- 6+6+6+16+5+2+3+3+2+2+3+2+4 = 60 bit VLWI opcode. |
-- Based on information found in: |
-- "MIPS RISC Architecture" by Gerry Kane and Joe Heinrich |
-- and "The Designer's Guide to VHDL" by Peter J. Ashenden |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mips_pack.all; |
|
entity control is |
port(opcode : in std_logic_vector(31 downto 0); |
intr_signal : in std_logic; |
rs_index : out std_logic_vector(5 downto 0); |
rt_index : out std_logic_vector(5 downto 0); |
rd_index : out std_logic_vector(5 downto 0); |
imm_out : out std_logic_vector(15 downto 0); |
alu_func : out alu_function_type; |
shift_func : out shift_function_type; |
mult_func : out mult_function_type; |
branch_func : out branch_function_type; |
a_source_out : out a_source_type; |
b_source_out : out b_source_type; |
c_source_out : out c_source_type; |
pc_source_out: out pc_source_type; |
mem_source_out:out mem_source_type); |
end; --entity control |
|
architecture logic of control is |
-- type alu_function_type is (alu_nothing, alu_add, alu_subtract, |
-- alu_less_than, alu_less_than_signed, alu_equal, alu_not_equal, |
-- alu_ltz, alu_lez, alu_eqz, alu_nez, alu_gez, alu_gtz, |
-- alu_or, alu_and, alu_xor, alu_nor); |
-- type shift_function_type is ( |
-- shift_nothing, shift_left_unsigned, |
-- shift_right_signed, shift_right_unsigned); |
-- type mult_function_type is ( |
-- mult_nothing, mult_read_lo, mult_read_hi, mult_write_lo, |
-- mult_write_hi, mult_mult, mult_divide, mult_signed_divide); |
-- type a_source_type is (from_reg_source, from_imm10_6); |
-- type b_source_type is (from_reg_target, from_imm, from_signed_imm); |
-- type c_source_type is (from_null, from_alu, from_shift, |
-- from_mult, from_memory, from_pc, from_imm_shift16, |
-- from_reg_source_nez, from_reg_source_eqz); |
-- type pc_source_type is (from_inc4, from_inc8, from_reg_source, |
-- from_opcode25_0, from_branch, from_lbranch); |
begin |
|
control_proc: process(opcode, intr_signal) |
variable op, func : std_logic_vector(5 downto 0); |
variable rs, rt, rd : std_logic_vector(5 downto 0); |
variable re, rtx : std_logic_vector(4 downto 0); |
variable imm : std_logic_vector(15 downto 0); |
variable alu_function : alu_function_type; |
variable shift_function : shift_function_type; |
variable mult_function : mult_function_type; |
variable a_source : a_source_type; |
variable b_source : b_source_type; |
variable c_source : c_source_type; |
variable pc_source : pc_source_type; |
variable branch_function: branch_function_type; |
variable mem_source : mem_source_type; |
begin |
alu_function := alu_nothing; |
shift_function := shift_nothing; |
mult_function := mult_nothing; |
a_source := a_from_reg_source; |
b_source := b_from_reg_target; |
c_source := c_from_null; |
pc_source := from_inc4; |
branch_function := branch_eq; |
mem_source := mem_none; |
op := opcode(31 downto 26); |
rs := '0' & opcode(25 downto 21); |
rt := '0' & opcode(20 downto 16); |
rtx := opcode(20 downto 16); |
rd := '0' & opcode(15 downto 11); |
re := opcode(10 downto 6); |
func := opcode(5 downto 0); |
imm := opcode(15 downto 0); |
|
case op is |
when "000000" => --00 SPECIAL |
case func is |
when "000000" => --00 SLL r[rd]=r[rt]<<re; |
a_source := a_from_imm10_6; |
c_source := c_from_shift; |
shift_function := shift_left_unsigned; |
when "000010" => --02 SRL r[rd]=u[rt]>>re; |
a_source := a_from_imm10_6; |
c_source := c_from_shift; |
shift_function := shift_right_unsigned; |
when "000011" => --03 SRA r[rd]=r[rt]>>re; |
a_source := a_from_imm10_6; |
c_source := c_from_shift; |
shift_function := shift_right_signed; |
when "000100" => --04 SLLV r[rd]=r[rt]<<r[rs]; |
c_source := c_from_shift; |
shift_function := shift_left_unsigned; |
when "000110" => --06 SRLV r[rd]=u[rt]>>r[rs]; |
c_source := c_from_shift; |
shift_function := shift_right_unsigned; |
when "000111" => --07 SRAV r[rd]=r[rt]>>r[rs]; |
c_source := c_from_shift; |
shift_function := shift_right_signed; |
when "001000" => --08 JR s->pc_next=r[rs]; |
pc_source := from_branch; |
alu_function := alu_add; |
branch_function := branch_yes; |
when "001001" => --09 JALR r[rd]=s->pc_next; s->pc_next=r[rs]; |
c_source := c_from_pc; |
pc_source := from_branch; |
alu_function := alu_add; |
branch_function := branch_yes; |
when "001010" => --0a MOVZ if(!r[rt]) r[rd]=r[rs]; /*IV*/ |
-- c_source := c_from_reg_source_eqz; |
when "001011" => --0b MOVN if(r[rt]) r[rd]=r[rs]; /*IV*/ |
-- c_source := from_reg_source_nez; |
when "001100" => --0c SYSCALL |
-- if(r[4]==0) printf("0x%8.8lx ",r[5]); |
when "001101" => --0d BREAK s->wakeup=1; |
when "001111" => --0f SYNC s->wakeup=1; |
when "010000" => --10 MFHI r[rd]=s->hi; |
c_source := c_from_mult; |
mult_function := mult_read_hi; |
when "010001" => --11 FTHI s->hi=r[rs]; |
mult_function := mult_write_hi; |
when "010010" => --12 MFLO r[rd]=s->lo; |
c_source := c_from_mult; |
mult_function := mult_read_lo; |
when "010011" => --13 MTLO s->lo=r[rs]; |
mult_function := mult_write_lo; |
when "011000" => --18 MULT s->lo=r[rs]*r[rt]; s->hi=0; |
mult_function := mult_mult; |
when "011001" => --19 MULTU s->lo=r[rs]*r[rt]; s->hi=0; |
mult_function := mult_mult; |
when "011010" => --1a DIV s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; |
mult_function := mult_signed_divide; |
when "011011" => --1b DIVU s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; |
mult_function := mult_divide; |
when "100000" => --20 ADD r[rd]=r[rs]+r[rt]; |
c_source := c_from_alu; |
alu_function := alu_add; |
when "100001" => --21 ADDU r[rd]=r[rs]+r[rt]; |
c_source := c_from_alu; |
alu_function := alu_add; |
when "100010" => --22 SUB r[rd]=r[rs]-r[rt]; |
c_source := c_from_alu; |
alu_function := alu_subtract; |
when "100011" => --23 SUBU r[rd]=r[rs]-r[rt]; |
c_source := c_from_alu; |
alu_function := alu_subtract; |
when "100100" => --24 AND r[rd]=r[rs]&r[rt]; |
c_source := c_from_alu; |
alu_function := alu_and; |
when "100101" => --25 OR r[rd]=r[rs]|r[rt]; |
c_source := c_from_alu; |
alu_function := alu_or; |
when "100110" => --26 XOR r[rd]=r[rs]^r[rt]; |
c_source := c_from_alu; |
alu_function := alu_xor; |
when "100111" => --27 NOR r[rd]=~(r[rs]|r[rt]); |
c_source := c_from_alu; |
alu_function := alu_nor; |
when "101010" => --2a SLT r[rd]=r[rs]<r[rt]; |
c_source := c_from_alu; |
alu_function := alu_less_than_signed; |
when "101011" => --2b SLTU r[rd]=u[rs]<u[rt]; |
c_source := c_from_alu; |
alu_function := alu_less_than; |
when "101101" => --2d DADDU r[rd]=r[rs]+u[rt]; |
c_source := c_from_alu; |
alu_function := alu_add; |
when "110001" => --31 TGEU |
when "110010" => --32 TLT |
when "110011" => --33 TLTU |
when "110100" => --34 TEQ |
when "110110" => --36 TNE |
when others => |
end case; |
when "000001" => --00 REGIMM |
rt := "000000"; |
rd := "011111"; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_branch; |
branch_function := branch_gtz; |
--if(test) pc=pc+imm*4 |
case rtx is |
when "10000" => --10 BLTZAL r[31]=s->pc_next; branch=r[rs]<0; |
c_source := c_from_pc; |
branch_function := branch_ltz; |
when "00000" => --00 BLTZ branch=r[rs]<0; |
branch_function := branch_ltz; |
when "10001" => --11 BGEZAL r[31]=s->pc_next; branch=r[rs]>=0; |
c_source := c_from_pc; |
branch_function := branch_gez; |
when "00001" => --01 BGEZ branch=r[rs]>=0; |
branch_function := branch_gez; |
when "10010" => --12 BLTZALL r[31]=s->pc_next; lbranch=r[rs]<0; |
c_source := c_from_pc; |
pc_source := from_lbranch; |
branch_function := branch_ltz; |
when "00010" => --02 BLTZL lbranch=r[rs]<0; |
pc_source := from_lbranch; |
branch_function := branch_ltz; |
when "10011" => --13 BGEZALL r[31]=s->pc_next; lbranch=r[rs]>=0; |
c_source := c_from_pc; |
pc_source := from_lbranch; |
branch_function := branch_gez; |
when "00011" => --03 BGEZL lbranch=r[rs]>=0; |
pc_source := from_lbranch; |
branch_function := branch_gez; |
when others => |
end case; |
when "000011" => --03 JAL r[31]=s->pc_next; s->pc_next=(s->pc&0xf0000000)|target; |
c_source := c_from_pc; |
rd := "011111"; |
pc_source := from_opcode25_0; |
when "000010" => --02 J s->pc_next=(s->pc&0xf0000000)|target; |
pc_source := from_opcode25_0; |
when "000100" => --04 BEQ branch=r[rs]==r[rt]; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_branch; |
branch_function := branch_eq; |
when "000101" => --05 BNE branch=r[rs]!=r[rt]; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_branch; |
branch_function := branch_ne; |
when "000110" => --06 BLEZ branch=r[rs]<=0; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_branch; |
branch_function := branch_ltz; |
when "000111" => --07 BGTZ branch=r[rs]>0; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_branch; |
branch_function := branch_gtz; |
when "001000" => --08 ADDI r[rt]=r[rs]+(short)imm; |
b_source := b_from_signed_imm; |
c_source := c_from_alu; |
rd := rt; |
alu_function := alu_add; |
when "001001" => --09 ADDIU u[rt]=u[rs]+(short)imm; |
b_source := b_from_signed_imm; |
c_source := c_from_alu; |
rd := rt; |
alu_function := alu_add; |
when "001010" => --0a SLTI r[rt]=r[rs]<(short)imm; |
b_source := b_from_signed_imm; |
c_source := c_from_alu; |
rd := rt; |
alu_function := alu_less_than; |
when "001011" => --0b SLTIU u[rt]=u[rs]<(unsigned long)(short)imm; |
b_source := b_from_imm; |
c_source := c_from_alu; |
rd := rt; |
alu_function := alu_less_than; |
when "001100" => --0c ANDI r[rt]=r[rs]&imm; |
b_source := b_from_imm; |
c_source := c_from_alu; |
rd := rt; |
alu_function := alu_and; |
when "001101" => --0d ORI r[rt]=r[rs]|imm; |
b_source := b_from_imm; |
c_source := c_from_alu; |
rd := rt; |
alu_function := alu_or; |
when "001110" => --0e XORI r[rt]=r[rs]^imm; |
b_source := b_from_imm; |
c_source := c_from_alu; |
rd := rt; |
alu_function := alu_xor; |
when "001111" => --0f LUI r[rt]=(imm<<16); |
c_source := c_from_imm_shift16; |
rd := rt; |
when "010000" => --10 COP0 |
alu_function := alu_or; |
c_source := c_from_alu; |
if opcode(23) = '0' then --move from CP0 |
rs := '1' & opcode(15 downto 11); |
rt := "000000"; |
rd := '0' & opcode(20 downto 16); |
else --move to CP0 |
rs := "000000"; |
rd(5) := '1'; |
end if; |
when "010001" => --11 COP1 |
when "010010" => --12 COP2 |
when "010011" => --13 COP3 |
when "010100" => --14 BEQL lbranch=r[rs]==r[rt]; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_lbranch; |
branch_function := branch_eq; |
when "010101" => --15 BNEL lbranch=r[rs]!=r[rt]; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_lbranch; |
branch_function := branch_ne; |
when "010110" => --16 BLEZL lbranch=r[rs]<=0; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_lbranch; |
branch_function := branch_lez; |
when "010111" => --17 BGTZL lbranch=r[rs]>0; |
a_source := a_from_pc; |
b_source := b_from_immX4; |
alu_function := alu_add; |
pc_source := from_lbranch; |
branch_function := branch_gtz; |
when "100000" => --20 LB r[rt]=*(signed char*)ptr; |
a_source := a_from_reg_source; |
b_source := b_from_imm; |
alu_function := alu_add; |
rd := rt; |
c_source := c_from_memory; |
mem_source := mem_read8s; --address=(short)imm+r[rs]; |
when "100001" => --21 LH r[rt]=*(signed short*)ptr; |
a_source := a_from_reg_source; |
b_source := b_from_imm; |
alu_function := alu_add; |
rd := rt; |
c_source := c_from_memory; |
mem_source := mem_read16s; --address=(short)imm+r[rs]; |
when "100010" => --22 LWL //fixme |
when "100011" => --23 LW r[rt]=*(long*)ptr; |
a_source := a_from_reg_source; |
b_source := b_from_imm; |
alu_function := alu_add; |
rd := rt; |
c_source := c_from_memory; |
mem_source := mem_read32; |
when "100100" => --24 LBU r[rt]=*(unsigned char*)ptr; |
a_source := a_from_reg_source; |
b_source := b_from_imm; |
alu_function := alu_add; |
rd := rt; |
c_source := c_from_memory; |
mem_source := mem_read8; --address=(short)imm+r[rs]; |
when "100101" => --25 LHU r[rt]=*(unsigned short*)ptr; |
a_source := a_from_reg_source; |
b_source := b_from_imm; |
alu_function := alu_add; |
rd := rt; |
c_source := c_from_memory; |
mem_source := mem_read16; --address=(short)imm+r[rs]; |
when "100110" => --26 LWR //fixme |
when "101000" => --28 SB *(char*)ptr=(char)r[rt]; |
a_source := a_from_reg_source; |
b_source := b_from_imm; |
alu_function := alu_add; |
mem_source := mem_write8; --address=(short)imm+r[rs]; |
when "101001" => --29 SH *(short*)ptr=(short)r[rt]; |
a_source := a_from_reg_source; |
b_source := b_from_imm; |
alu_function := alu_add; |
mem_source := mem_write16; |
when "101010" => --2a SWL //fixme |
when "101011" => --2b SW *(long*)ptr=r[rt]; |
a_source := a_from_reg_source; |
b_source := b_from_imm; |
alu_function := alu_add; |
mem_source := mem_write32; --address=(short)imm+r[rs]; |
when "101110" => --2e SWR //fixme |
when "101111" => --2f CACHE |
when "110000" => --30 LL r[rt]=*(long*)ptr; |
when "110001" => --31 LWC1 |
when "110010" => --32 LWC2 |
when "110011" => --33 LWC3 |
when "110101" => --35 LDC1 |
when "110110" => --36 LDC2 |
when "110111" => --37 LDC3 |
when "111000" => --38 SC *(long*)ptr=r[rt]; r[rt]=1; |
when "111001" => --39 SWC1 |
when "111010" => --3a SWC2 |
when "111011" => --3b SWC3 |
when "111101" => --3d SDC1 |
when "111110" => --3e SDC2 |
when "111111" => --3f SDC3 |
when others => |
end case; |
|
if c_source = c_from_null then |
rd := "000000"; |
end if; |
|
if intr_signal = '1' then |
rd := "101110"; --EPC |
c_source := c_from_pc; |
rs := "111111"; --interrupt vector |
rt := "000000"; |
a_source := a_from_reg_source; |
b_source := b_from_reg_target; |
alu_function := alu_or; |
pc_source := from_branch; |
branch_function := branch_yes; |
end if; |
|
rs_index <= rs; |
rt_index <= rt; |
rd_index <= rd; |
imm_out <= imm; |
alu_func <= alu_function; |
shift_func <= shift_function; |
mult_func <= mult_function; |
branch_func <= branch_function; |
a_source_out <= a_source; |
b_source_out <= b_source; |
c_source_out <= c_source; |
pc_source_out <= pc_source; |
mem_source_out <= mem_source; |
|
end process; |
|
end; --logic |
|
/pc_next.vhd
0,0 → 1,67
--------------------------------------------------------------------- |
-- TITLE: Program Counter Next |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 2/8/01 |
-- FILENAME: pc_next.vhd |
-- PROJECT: MIPS CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Implements the Program Counter logic. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mips_pack.all; |
|
entity pc_next is |
port(clk : in std_logic; |
reset_in : in std_logic; |
pc_new : in std_logic_vector(31 downto 2); |
take_branch : in std_logic; |
pause_in : in std_logic; |
opcode25_0 : in std_logic_vector(25 downto 0); |
pc_source : in pc_source_type; |
pc_out : out std_logic_vector(31 downto 0)); |
end; --pc_next |
|
architecture logic of pc_next is |
-- type pc_source_type is (from_inc4, from_opcode25_0, from_branch, |
-- from_lbranch); |
signal pc_reg : std_logic_vector(31 downto 2); --:= ZERO(31 downto 2); |
begin |
|
pc_next: process(clk, reset_in, pc_new, take_branch, pause_in, |
opcode25_0, pc_source, |
pc_reg) |
variable pc_inc, pc_next : std_logic_vector(31 downto 2); |
begin |
pc_inc := bv_increment(pc_reg); --pc_reg+1 |
pc_next := pc_reg; |
case pc_source is |
when from_inc4 => |
if pause_in = '0' then |
pc_next := pc_inc; |
end if; |
when from_opcode25_0 => |
pc_next := pc_reg(31 downto 28) & opcode25_0; |
when from_branch | from_lbranch => |
if take_branch = '1' then |
pc_next := pc_new; |
else |
pc_next := pc_inc; |
end if; |
when others => |
end case; |
if reset_in = '1' then |
pc_next := ZERO(31 downto 2); |
end if; |
|
if rising_edge(clk) then |
pc_reg <= pc_next; |
end if; |
|
pc_out <= pc_reg & "00"; |
end process; |
|
end; --logic |
|
/alu.vhd
0,0 → 1,106
--------------------------------------------------------------------- |
-- TITLE: Arithmetic Logic Unit |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 2/8/01 |
-- FILENAME: alu.vhd |
-- PROJECT: MIPS CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Implements the ALU. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mips_pack.all; |
|
entity alu is |
port(a_in : in std_logic_vector(31 downto 0); |
b_in : in std_logic_vector(31 downto 0); |
alu_function : in alu_function_type; |
c_alu : out std_logic_vector(31 downto 0)); |
end; --alu |
|
architecture logic of alu is |
-- type alu_function_type is (alu_nothing, alu_add, alu_subtract, |
-- alu_less_than, alu_less_than_signed, alu_equal, alu_not_equal, |
-- alu_ltz, alu_lez, alu_eqz, alu_nez, alu_gez, alu_gtz, |
-- alu_or, alu_and, alu_xor, alu_nor); |
begin |
|
alu_proc: process(a_in, b_in, alu_function) |
variable c : std_logic_vector(31 downto 0); |
variable aa, bb, sum : std_logic_vector(32 downto 0); |
variable do_sub : std_logic; |
variable a_eq_b : std_logic; |
variable a_zero : std_logic; |
variable sign_ext : std_logic; |
begin |
c := ZERO; |
if alu_function = alu_add then |
do_sub := '0'; |
else |
do_sub := '1'; |
end if; |
if alu_function = alu_less_than then |
sign_ext := '0'; |
else |
sign_ext := '1'; |
end if; |
aa := (a_in(31) and sign_ext) & a_in; |
bb := (b_in(31) and sign_ext) & b_in; |
sum := bv_adder(aa, bb, do_sub); |
-- sum := bv_adder_lookahead(aa, bb, do_sub); |
if a_in = b_in then |
a_eq_b := '1'; |
else |
a_eq_b := '0'; |
end if; |
if a_in = ZERO then |
a_zero := '1'; |
else |
a_zero := '0'; |
end if; |
case alu_function is |
when alu_add | alu_subtract => --c=a+b |
c := sum(31 downto 0); |
when alu_less_than => --c=a<b |
c(0) := sum(32); |
when alu_less_than_signed => --c=a<b; |
c(0) := sum(32); |
when alu_equal => --c=a==b |
c(0) := a_eq_b; |
when alu_not_equal => --c=a!=b |
c(0) := not a_eq_b; |
when alu_ltz => --c=a<0 |
c(0) := a_in(31); |
when alu_lez => --c=a<=0 |
c(0) := a_in(31) or a_zero; |
when alu_eqz => --c=a==0 |
c(0) := a_zero; |
when alu_nez => --c=a!=0 |
c(0) := not a_zero; |
when alu_gez => --c=a>=0 |
c(0) := not a_in(31); |
when alu_gtz => --c=a>0 |
c(0) := not a_zero and not a_in(31); |
when alu_or => --c=a|b |
c := a_in or b_in; |
when alu_and => --c=a&b |
c := a_in and b_in; |
when alu_xor => --c=a^b |
c := a_in xor b_in; |
when alu_nor => --c=~(a|b) |
c := a_in nor b_in; |
when others => --alu_function = alu_nothing |
c := ZERO; |
end case; |
|
-- if alu_function = alu_nothing then |
-- c_alu <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; |
-- else |
c_alu <= c; |
-- end if; |
end process; |
|
end; --architecture logic |
|
/mult.vhd
0,0 → 1,185
--------------------------------------------------------------------- |
-- TITLE: Multiplication and Division Unit |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 1/31/01 |
-- FILENAME: mult.vhd |
-- PROJECT: MIPS CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Implements the multiplication and division unit. |
-- Normally takes 32 clock cycles. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mips_pack.all; |
|
entity mult is |
port(clk : in std_logic; |
a, b : in std_logic_vector(31 downto 0); |
mult_func : in mult_function_type; |
c_mult : out std_logic_vector(31 downto 0); |
pause_out : out std_logic); |
end; --entity mult |
|
architecture logic of mult is |
-- type mult_function_type is ( |
-- mult_nothing, mult_read_lo, mult_read_hi, mult_write_lo, |
-- mult_write_hi, mult_mult, mult_divide, mult_signed_divide); |
signal do_div_reg : std_logic; |
signal do_signed_reg : std_logic; |
signal count_reg : std_logic_vector(5 downto 0); |
signal reg_a : std_logic_vector(31 downto 0); |
signal reg_b : std_logic_vector(63 downto 0); |
signal answer_reg : std_logic_vector(31 downto 0); |
begin |
|
--multiplication/division unit |
mult_proc: process(clk, a, b, mult_func, |
do_div_reg, do_signed_reg, count_reg, |
reg_a, reg_b, answer_reg) |
variable do_div_temp : std_logic; |
variable do_signed_temp : std_logic; |
variable count_temp : std_logic_vector(5 downto 0); |
variable a_temp : std_logic_vector(31 downto 0); |
variable b_temp : std_logic_vector(63 downto 0); |
variable answer_temp : std_logic_vector(31 downto 0); |
|
variable sign_extension : std_logic; |
variable aa, bb : std_logic_vector(32 downto 0); |
variable sum : std_logic_vector(32 downto 0); |
variable start : std_logic; |
variable do_write : std_logic; |
variable do_hi : std_logic; |
|
begin |
do_div_temp := do_div_reg; |
do_signed_temp := do_signed_reg; |
count_temp := count_reg; |
a_temp := reg_a; |
b_temp := reg_b; |
answer_temp := answer_reg; |
|
sign_extension := '0'; |
aa := '0' & ZERO; |
bb := '0' & ZERO; |
sum := '0' & ZERO; |
start := '0'; |
do_write := '0'; |
do_hi := '0'; |
|
case mult_func is |
when mult_read_lo => |
when mult_read_hi => |
do_hi := '1'; |
when mult_write_lo => |
do_write := '1'; |
when mult_write_hi => |
do_write := '1'; |
do_hi := '1'; |
when mult_mult => |
start := '1'; |
do_div_temp := '0'; |
when mult_divide => |
start := '1'; |
do_div_temp := '1'; |
do_signed_temp := '0'; |
when mult_signed_divide => |
start := '1'; |
do_div_temp := '1'; |
do_signed_temp := '1'; |
when others => |
end case; |
|
if start = '1' then |
count_temp := "000000"; |
a_temp := a; |
answer_temp := ZERO; |
if do_div_temp = '1' then |
if do_signed_temp = '0' or b(31) = '0' then |
b_temp(62 downto 31) := b; |
else |
b_temp(62 downto 31) := bv_negate(b); |
a_temp := bv_negate(a); |
end if; |
b_temp(30 downto 0) := ZERO(30 downto 0); |
else --multiply |
b_temp := zero & b; |
end if; |
elsif do_write = '1' then |
if do_hi = '0' then |
b_temp(31 downto 0) := a; |
else |
b_temp(63 downto 32) := a; |
end if; |
end if; |
|
if do_div_reg = '1' then |
bb := reg_b(32 downto 0); |
else |
bb := '0' & reg_b(63 downto 32); |
end if; |
sign_extension := reg_a(31) and do_signed_reg; |
aa := sign_extension & reg_a; |
sum := bv_adder(aa, bb, do_div_reg); |
-- sum := bv_adder_lookahead(aa, bb, do_div_reg); |
|
if count_reg(5) = '0' and start = '0' then |
count_temp := bv_inc6(count_reg); |
if do_div_reg = '1' then |
answer_temp(31 downto 1) := answer_reg(30 downto 0); |
if reg_b(63 downto 32) = ZERO and sum(32) = '0' then |
a_temp := sum(31 downto 0); --aa=aa-bb; |
answer_temp(0) := '1'; |
else |
answer_temp(0) := '0'; |
end if; |
if count_reg /= "011111" then |
b_temp(62 downto 0) := reg_b(63 downto 1); |
else |
b_temp(63 downto 32) := a_temp; |
b_temp(31 downto 0) := answer_temp; |
end if; |
else -- mult_mode |
if reg_b(0) = '1' then |
b_temp(63 downto 31) := sum; |
else |
b_temp(63 downto 31) := '0' & reg_b(63 downto 32); |
end if; |
b_temp(30 downto 0) := reg_b(31 downto 1); |
if count_reg = "010000" and --early stop |
reg_b(15 downto 0) = zero(15 downto 0) then |
count_temp := "111111"; |
b_temp(31 downto 0) := reg_b(47 downto 16); |
end if; |
end if; |
end if; |
|
if rising_edge(clk) then |
do_div_reg <= do_div_temp; |
do_signed_reg <= do_signed_temp; |
count_reg <= count_temp; |
reg_a <= a_temp; |
reg_b <= b_temp; |
answer_reg <= answer_temp; |
end if; |
|
if count_reg(5) = '0' and mult_func/= mult_nothing and start = '0' then |
pause_out <= '1'; |
else |
pause_out <= '0'; |
end if; |
if mult_func = mult_read_lo then |
c_mult <= reg_b(31 downto 0); |
elsif mult_func = mult_read_hi then |
c_mult <= reg_b(63 downto 32); |
else |
-- c_mult <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; |
c_mult <= ZERO; |
end if; |
|
end process; |
|
end; --architecture logic |
|
|
/bus_mux.vhd
0,0 → 1,135
--------------------------------------------------------------------- |
-- TITLE: Bus Multiplexer / Signal Router |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 2/8/01 |
-- FILENAME: bus_mux.vhd |
-- PROJECT: MIPS CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- This entity is the main signal router. |
-- It multiplexes signals from multiple sources to the correct location. |
-- The outputs are as follows: |
-- a_bus : goes to the ALU |
-- b_bus : goes to the ALU |
-- reg_dest_out : goes to the register bank |
-- take_branch : a signal to pc_next |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mips_pack.all; |
|
entity bus_mux is |
port(imm_in : in std_logic_vector(15 downto 0); |
reg_source : in std_logic_vector(31 downto 0); |
a_mux : in a_source_type; |
a_out : out std_logic_vector(31 downto 0); |
|
reg_target : in std_logic_vector(31 downto 0); |
b_mux : in b_source_type; |
b_out : out std_logic_vector(31 downto 0); |
|
c_bus : in std_logic_vector(31 downto 0); |
c_memory : in std_logic_vector(31 downto 0); |
c_pc : in std_logic_vector(31 downto 0); |
c_mux : in c_source_type; |
reg_dest_out : out std_logic_vector(31 downto 0); |
|
branch_func : in branch_function_type; |
take_branch : out std_logic); |
end; --entity bus_mux |
|
architecture logic of bus_mux is |
begin |
-- type a_source_type is (a_from_reg_source, a_from_imm10_6); |
-- type b_source_type is (b_from_reg_target, b_from_imm, b_from_signed_imm); |
-- type c_source_type is (c_from_null, c_from_alu, c_from_shift, |
-- c_from_mult, c_from_memory, c_from_pc, c_from_imm_shift16, |
-- c_from_reg_source_nez, c_from_reg_source_eqz); |
amux: process(reg_source, imm_in, a_mux, c_pc) |
begin |
a_out(31 downto 5) <= reg_source(31 downto 5); |
case a_mux is |
when a_from_reg_source => |
a_out(4 downto 0) <= reg_source(4 downto 0); |
when a_from_imm10_6 => |
a_out(4 downto 0) <= imm_in(10 downto 6); |
when others => --a_from_pc |
a_out <= c_pc; |
end case; |
end process; |
|
bmux: process(reg_target, imm_in, b_mux) |
begin |
case b_mux is |
when b_from_reg_target => |
b_out <= reg_target; |
when b_from_imm => |
b_out <= ZERO(31 downto 16) & imm_in; |
when b_from_signed_imm => |
if imm_in(15) = '0' then |
b_out(31 downto 16) <= ZERO(31 downto 16); |
else |
b_out(31 downto 16) <= "1111111111111111"; |
end if; |
b_out(15 downto 0) <= imm_in; |
when others => --b_from_immX4 |
if imm_in(15) = '0' then |
b_out(31 downto 18) <= "00000000000000"; |
else |
b_out(31 downto 18) <= "11111111111111"; |
end if; |
b_out(17 downto 0) <= imm_in & "00"; |
end case; |
end process; |
|
cmux: process(c_bus, c_memory, c_pc, imm_in, c_mux) |
begin |
case c_mux is |
when c_from_alu | c_from_shift | c_from_mult => |
reg_dest_out <= c_bus; |
when c_from_memory => |
reg_dest_out <= c_memory; |
when c_from_pc => |
reg_dest_out <= c_pc; |
when c_from_imm_shift16 => |
reg_dest_out <= imm_in & ZERO(15 downto 0); |
-- when from_reg_source_nez => |
--???? |
-- when from_reg_source_eqz => |
--???? |
when others => |
reg_dest_out <= c_bus; |
end case; |
end process; |
|
pc_mux: process(branch_func, reg_source, reg_target) |
variable is_equal : std_logic; |
begin |
if reg_source = reg_target then |
is_equal := '1'; |
else |
is_equal := '0'; |
end if; |
case branch_func is |
when branch_ltz => |
take_branch <= reg_source(31); |
when branch_lez => |
take_branch <= reg_source(31) or is_equal; |
when branch_eq => |
take_branch <= is_equal; |
when branch_ne => |
take_branch <= not is_equal; |
when branch_gez => |
take_branch <= not reg_source(31); |
when branch_gtz => |
take_branch <= not reg_source(31) and not is_equal; |
when branch_yes => |
take_branch <= '1'; |
when others => |
take_branch <= is_equal; |
end case; |
end process; |
|
end; --architecture logic |
|
/mem_ctrl.vhd
0,0 → 1,178
--------------------------------------------------------------------- |
-- TITLE: Memory Controller |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 1/31/01 |
-- FILENAME: mem_ctrl.vhd |
-- PROJECT: MIPS CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Memory controller for the MIPS CPU. |
-- Supports Big or Little Endian mode. |
-- This entity could implement interfaces to: |
-- Data cache |
-- Address cache |
-- Memory management unit (MMU) |
-- DRAM controller |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mips_pack.all; |
|
entity mem_ctrl is |
port(clk : in std_logic; |
reset_in : in std_logic; |
pause_in : in std_logic; |
nullify_op : in std_logic; |
address_pc : in std_logic_vector(31 downto 0); |
opcode_out : out std_logic_vector(31 downto 0); |
|
address_data : in std_logic_vector(31 downto 0); |
mem_source : in mem_source_type; |
data_write : in std_logic_vector(31 downto 0); |
data_read : out std_logic_vector(31 downto 0); |
pause_out : out std_logic; |
|
mem_address : out std_logic_vector(31 downto 0); |
mem_data_w : out std_logic_vector(31 downto 0); |
mem_data_r : in std_logic_vector(31 downto 0); |
mem_byte_sel : out std_logic_vector(3 downto 0); |
mem_write : out std_logic; |
mem_pause : in std_logic); |
end; --entity mem_ctrl |
|
architecture logic of mem_ctrl is |
--"00" = big_endian; "11" = little_endian |
constant little_endian : std_logic_vector(1 downto 0) := "00"; |
signal opcode_reg : std_logic_vector(31 downto 0); |
signal next_opcode_reg : std_logic_vector(31 downto 0); |
signal setup_done : std_logic; |
begin |
|
mem_proc: process(clk, reset_in, pause_in, nullify_op, address_pc, |
address_data, mem_source, data_write, mem_data_r, |
mem_pause, |
opcode_reg, next_opcode_reg, setup_done) |
variable data, datab : std_logic_vector(31 downto 0); |
variable opcode_temp : std_logic_vector(31 downto 0); |
variable byte_sel_temp : std_logic_vector(3 downto 0); |
variable write_temp : std_logic; |
variable setup_done_var : std_logic; |
variable pause : std_logic; |
variable address_temp : std_logic_vector(31 downto 0); |
variable bits : std_logic_vector(1 downto 0); |
variable mem_data_w_v : std_logic_vector(31 downto 0); |
begin |
byte_sel_temp := "0000"; |
write_temp := '0'; |
pause := '0'; |
setup_done_var := setup_done; |
|
address_temp := address_pc; |
data := mem_data_r; |
datab := ZERO; |
mem_data_w_v := ZERO; --"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; |
|
case mem_source is |
when mem_read32 => |
datab := data; |
when mem_read16 | mem_read16s => |
if address_data(1) = little_endian(1) then |
datab(15 downto 0) := data(31 downto 16); |
else |
datab(15 downto 0) := data(15 downto 0); |
end if; |
if mem_source = mem_read16 or datab(15) = '0' then |
datab(31 downto 16) := ZERO(31 downto 16); |
else |
datab(31 downto 16) := ONES(31 downto 16); |
end if; |
when mem_read8 | mem_read8s => |
bits := address_data(1 downto 0) xor little_endian; |
case bits is |
when "00" => datab(7 downto 0) := data(31 downto 24); |
when "01" => datab(7 downto 0) := data(23 downto 16); |
when "10" => datab(7 downto 0) := data(15 downto 8); |
when others => datab(7 downto 0) := data(7 downto 0); |
end case; |
if mem_source = mem_read8 or datab(7) = '0' then |
datab(31 downto 8) := ZERO(31 downto 8); |
else |
datab(31 downto 8) := ONES(31 downto 8); |
end if; |
when mem_write32 => |
write_temp := '1'; |
mem_data_w_v := data_write; |
byte_sel_temp := "1111"; |
when mem_write16 => |
write_temp := '1'; |
mem_data_w_v := data_write(15 downto 0) & data_write(15 downto 0); |
if address_data(1) = little_endian(1) then |
byte_sel_temp := "1100"; |
else |
byte_sel_temp := "0011"; |
end if; |
when mem_write8 => |
write_temp := '1'; |
mem_data_w_v := data_write(7 downto 0) & data_write(7 downto 0) & |
data_write(7 downto 0) & data_write(7 downto 0); |
bits := address_data(1 downto 0) xor little_endian; |
case bits is |
when "00" => |
byte_sel_temp := "1000"; |
when "01" => |
byte_sel_temp := "0100"; |
when "10" => |
byte_sel_temp := "0010"; |
when others => |
byte_sel_temp := "0001"; |
end case; |
when others => |
end case; |
|
opcode_temp := opcode_reg; |
if mem_source = mem_none then |
setup_done_var := '0'; |
if pause_in = '0' and mem_pause = '0' then |
if nullify_op = '0' then |
opcode_temp := data; |
else |
opcode_temp := ZERO; --NOP |
end if; |
end if; |
else |
pause := not setup_done; |
setup_done_var := '1'; |
if setup_done = '1' then |
address_temp := address_data; |
if mem_pause = '0' then |
opcode_temp := next_opcode_reg; |
setup_done_var := '0'; |
end if; |
end if; |
end if; |
if reset_in = '1' then |
setup_done_var := '0'; |
opcode_temp := ZERO; |
end if; |
|
if rising_edge(clk) then |
opcode_reg <= opcode_temp; |
if setup_done = '0' then |
next_opcode_reg <= data; |
end if; |
setup_done <= setup_done_var; |
end if; |
|
opcode_out <= opcode_reg; |
data_read <= datab; |
pause_out <= mem_pause or pause; |
mem_byte_sel <= byte_sel_temp; |
mem_address <= address_temp; |
mem_write <= write_temp and setup_done; |
mem_data_w <= mem_data_w_v; |
|
end process; --data_proc |
|
end; --architecture logic |
|
/tbench.vhd
0,0 → 1,99
--------------------------------------------------------------------- |
-- TITLE: Test Bench |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 4/21/01 |
-- FILENAME: tbench.vhd |
-- PROJECT: MIPS CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- This entity provides a test bench for testing the MIPS CPU core. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mips_pack.all; |
|
entity tbench is |
port(clk_out : out std_logic; |
pc : out std_logic_vector(31 downto 0) |
); |
end; --entity tbench |
|
architecture logic of tbench is |
|
component mips_cpu |
port(clk : in std_logic; |
reset_in : in std_logic; |
intr_in : in std_logic; |
|
mem_address : out std_logic_vector(31 downto 0); |
mem_data_w : out std_logic_vector(31 downto 0); |
mem_data_r : in std_logic_vector(31 downto 0); |
mem_sel : out std_logic_vector(3 downto 0); |
mem_write : out std_logic; |
mem_pause : in std_logic; |
|
t_pc : out std_logic_vector(31 downto 0); |
t_opcode : out std_logic_vector(31 downto 0); |
t_r_dest : out std_logic_vector(31 downto 0) |
); |
end component; |
|
component ram |
generic(load_file_name : string); |
port(clk : in std_logic; |
mem_byte_sel : in std_logic_vector(3 downto 0); |
mem_write : in std_logic; |
mem_address : in std_logic_vector; |
mem_data_w : in std_logic_vector(31 downto 0); |
mem_data_r : out std_logic_vector(31 downto 0)); |
end component; |
|
signal clk : std_logic := '0'; |
signal reset : std_logic := '1'; --, '0' after 100 ns; |
signal interrupt : std_logic := '0'; |
signal mem_sel : std_logic_vector(3 downto 0); |
signal mem_write : std_logic; |
signal mem_address : std_logic_vector(31 downto 0); |
signal mem_data_w : std_logic_vector(31 downto 0); |
signal mem_data_r : std_logic_vector(31 downto 0); |
signal mem_pause : std_logic; |
signal t_pc : std_logic_vector(31 downto 0); |
signal t_opcode : std_logic_vector(31 downto 0); |
signal t_r_dest : std_logic_vector(31 downto 0); |
signal mem_byte_sel: std_logic_vector(3 downto 0); |
begin --architecture |
clk <= not clk after 50 ns; |
reset <= '0' after 100 ns; |
mem_pause <= '0'; |
|
u1: mips_cpu PORT MAP ( |
clk => clk, |
reset_in => reset, |
intr_in => interrupt, |
|
mem_address => mem_address, |
mem_data_w => mem_data_w, |
mem_data_r => mem_data_r, |
mem_sel => mem_byte_sel, |
mem_write => mem_write, |
mem_pause => mem_pause, |
|
t_pc => t_pc, |
t_opcode => t_opcode, |
t_r_dest => t_r_dest); |
|
u2: ram generic map ("code.txt") |
PORT MAP ( |
clk => clk, |
mem_byte_sel => mem_byte_sel, |
mem_write => mem_write, |
mem_address => mem_address(15 downto 0), |
mem_data_w => mem_data_w, |
mem_data_r => mem_data_r); |
|
clk_out <= clk; |
pc <= t_pc; |
|
end; --architecture logic |
|
/shifter.vhd
0,0 → 1,107
--------------------------------------------------------------------- |
-- TITLE: Shifter Unit |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 2/2/01 |
-- FILENAME: shifter.vhd |
-- PROJECT: MIPS CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Implements the 32-bit shifter unit. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mips_pack.all; |
|
entity shifter is |
port(value : in std_logic_vector(31 downto 0); |
shift_amount : in std_logic_vector(4 downto 0); |
shift_func : in shift_function_type; |
c_shift : out std_logic_vector(31 downto 0)); |
end; --entity shifter |
|
architecture logic of shifter is |
-- type shift_function_type is ( |
-- shift_nothing, shift_left_unsigned, |
-- shift_left_signed, shift_right_unsigned); |
begin |
|
shift_proc: process(value, shift_amount, shift_func) --barrel shifter unit |
variable shift1, shift2, shift4, |
shift8, shift16 : std_logic_vector(31 downto 0); |
variable fills : std_logic_vector(31 downto 16); |
variable go_right : std_logic; |
begin |
if shift_func = shift_right_unsigned or shift_func = shift_right_signed then |
go_right := '1'; |
else |
go_right := '0'; |
end if; |
if shift_func = shift_right_signed and value(31) = '1' then |
fills := "1111111111111111"; |
else |
fills := "0000000000000000"; |
end if; |
if go_right = '0' then --shift left |
if shift_amount(0) = '1' then |
shift1 := value(30 downto 0) & '0'; |
else |
shift1 := value; |
end if; |
if shift_amount(1) = '1' then |
shift2 := shift1(29 downto 0) & "00"; |
else |
shift2 := shift1; |
end if; |
if shift_amount(2) = '1' then |
shift4 := shift2(27 downto 0) & "0000"; |
else |
shift4 := shift2; |
end if; |
if shift_amount(3) = '1' then |
shift8 := shift4(23 downto 0) & "00000000"; |
else |
shift8 := shift4; |
end if; |
if shift_amount(4) = '1' then |
shift16 := shift8(15 downto 0) & ZERO(15 downto 0); |
else |
shift16 := shift8; |
end if; |
else --shift right |
if shift_amount(0) = '1' then |
shift1 := fills(31) & value(31 downto 1); |
else |
shift1 := value; |
end if; |
if shift_amount(1) = '1' then |
shift2 := fills(31 downto 30) & shift1(31 downto 2); |
else |
shift2 := shift1; |
end if; |
if shift_amount(2) = '1' then |
shift4 := fills(31 downto 28) & shift2(31 downto 4); |
else |
shift4 := shift2; |
end if; |
if shift_amount(3) = '1' then |
shift8 := fills(31 downto 24) & shift4(31 downto 8); |
else |
shift8 := shift4; |
end if; |
if shift_amount(4) = '1' then |
shift16 := fills(31 downto 16) & shift8(31 downto 16); |
else |
shift16 := shift8; |
end if; |
end if; --shift_dir |
if shift_func = shift_nothing then |
-- c_shift <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; |
c_shift <= ZERO; |
else |
c_shift <= shift16; |
end if; |
end process; |
|
end; --architecture logic |
|
/mips_pack.vhd
0,0 → 1,274
--------------------------------------------------------------------- |
-- TITLE: MIPS Misc. Package |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 2/15/01 |
-- FILENAME: mips_pack.vhd |
-- PROJECT: MIPS CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Data types, constants, and add functions needed for the MIPS CPU. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
|
package mips_pack is |
constant ZERO : std_logic_vector(31 downto 0) := |
"00000000000000000000000000000000"; |
constant ONES : std_logic_vector(31 downto 0) := |
"11111111111111111111111111111111"; |
|
-- type alu_function_type is (alu_nothing, alu_add, alu_subtract, |
-- alu_less_than, alu_less_than_signed, alu_equal, alu_not_equal, |
-- alu_ltz, alu_lez, alu_eqz, alu_nez, alu_gez, alu_gtz, |
-- alu_or, alu_and, alu_xor, alu_nor); |
subtype alu_function_type is std_logic_vector(4 downto 0); |
constant alu_nothing : alu_function_type := "00000"; |
constant alu_add : alu_function_type := "00010"; |
constant alu_subtract : alu_function_type := "00011"; |
constant alu_less_than : alu_function_type := "00100"; |
constant alu_less_than_signed : alu_function_type := "00101"; |
constant alu_equal : alu_function_type := "00110"; |
constant alu_not_equal : alu_function_type := "00111"; |
constant alu_ltz : alu_function_type := "01000"; |
constant alu_lez : alu_function_type := "01001"; |
constant alu_eqz : alu_function_type := "01010"; |
constant alu_nez : alu_function_type := "01011"; |
constant alu_gez : alu_function_type := "01100"; |
constant alu_gtz : alu_function_type := "01101"; |
constant alu_or : alu_function_type := "01110"; |
constant alu_and : alu_function_type := "01111"; |
constant alu_xor : alu_function_type := "10001"; |
constant alu_nor : alu_function_type := "10010"; |
|
-- type shift_function_type is ( |
-- shift_nothing, shift_left_unsigned, |
-- shift_right_signed, do_right_unsigned); |
subtype shift_function_type is std_logic_vector(1 downto 0); |
constant shift_nothing : shift_function_type := "00"; |
constant shift_left_unsigned : shift_function_type := "01"; |
constant shift_right_signed : shift_function_type := "11"; |
constant shift_right_unsigned : shift_function_type := "10"; |
|
-- type mult_function_type is ( |
-- mult_nothing, mult_read_lo, mult_read_hi, mult_write_lo, |
-- mult_write_hi, mult_mult, mult_divide, mult_signed_divide); |
subtype mult_function_type is std_logic_vector(2 downto 0); |
constant mult_nothing : mult_function_type := "000"; |
constant mult_read_lo : mult_function_type := "001"; |
constant mult_read_hi : mult_function_type := "010"; |
constant mult_write_lo : mult_function_type := "011"; |
constant mult_write_hi : mult_function_type := "100"; |
constant mult_mult : mult_function_type := "101"; |
constant mult_divide : mult_function_type := "110"; |
constant mult_signed_divide : mult_function_type := "111"; |
|
-- type a_source_type is (from_reg_source, from_imm10_6); |
subtype a_source_type is std_logic_vector(1 downto 0); |
constant a_from_reg_source : a_source_type := "00"; |
constant a_from_imm10_6 : a_source_type := "01"; |
constant a_from_pc : a_source_type := "10"; |
|
-- type b_source_type is (from_reg_target, from_imm, from_signed_imm); |
subtype b_source_type is std_logic_vector(1 downto 0); |
constant b_from_reg_target : b_source_type := "00"; |
constant b_from_imm : b_source_type := "01"; |
constant b_from_signed_imm : b_source_type := "10"; |
constant b_from_immX4 : b_source_type := "11"; |
|
-- type c_source_type is (from_null, from_alu, from_shift, |
-- from_mult, from_memory, from_pc, from_imm_shift16, |
-- from_reg_source_nez, from_reg_source_eqz); |
subtype c_source_type is std_logic_vector(2 downto 0); |
constant c_from_alu : c_source_type := "000"; |
constant c_from_shift : c_source_type := "001"; |
constant c_from_mult : c_source_type := "010"; |
constant c_from_memory : c_source_type := "011"; |
constant c_from_pc : c_source_type := "100"; |
constant c_from_imm_shift16: c_source_type := "101"; |
constant c_from_reg_sourcen: c_source_type := "110"; |
constant c_from_null : c_source_type := "111"; |
|
-- type pc_source_type is (from_inc4, from_inc8, from_reg_source, |
-- from_opcode25_0, from_branch, from_lbranch); |
subtype pc_source_type is std_logic_vector(1 downto 0); |
constant from_inc4 : pc_source_type := "00"; |
constant from_opcode25_0 : pc_source_type := "01"; |
constant from_branch : pc_source_type := "10"; |
constant from_lbranch : pc_source_type := "11"; |
|
subtype branch_function_type is std_logic_vector(2 downto 0); |
constant branch_ltz : branch_function_type := "000"; |
constant branch_lez : branch_function_type := "001"; |
constant branch_eq : branch_function_type := "010"; |
constant branch_ne : branch_function_type := "011"; |
constant branch_gez : branch_function_type := "100"; |
constant branch_gtz : branch_function_type := "101"; |
constant branch_yes : branch_function_type := "110"; |
|
-- mode(32=1,16=2,8=3), signed, write |
subtype mem_source_type is std_logic_vector(3 downto 0); |
constant mem_none : mem_source_type := "0000"; |
constant mem_read32 : mem_source_type := "0100"; |
constant mem_write32 : mem_source_type := "0101"; |
constant mem_read16 : mem_source_type := "1000"; |
constant mem_read16s : mem_source_type := "1010"; |
constant mem_write16 : mem_source_type := "1001"; |
constant mem_read8 : mem_source_type := "1100"; |
constant mem_read8s : mem_source_type := "1110"; |
constant mem_write8 : mem_source_type := "1101"; |
|
function bv_to_integer(bv: in std_logic_vector) return integer; |
function bv_adder(a : in std_logic_vector(32 downto 0); |
b : in std_logic_vector(32 downto 0); |
do_sub: in std_logic) return std_logic_vector; |
function bv_adder_lookahead( |
a : in std_logic_vector(32 downto 0); |
b : in std_logic_vector(32 downto 0); |
do_sub: in std_logic) return std_logic_vector; |
function bv_negate(a : in std_logic_vector) return std_logic_vector; |
function bv_increment(a : in std_logic_vector(31 downto 2) |
) return std_logic_vector; |
function bv_inc6(a : in std_logic_vector |
) return std_logic_vector; |
end; --package mips_pack |
|
package body mips_pack is |
|
function add_1(a:integer) return integer is |
begin |
return a+1; |
end; --function |
|
function bv_to_integer(bv: in std_logic_vector) return integer is |
variable result : integer; |
variable b : integer; |
begin |
result := 0; |
b := 0; |
for index in bv'range loop |
if bv(index) = '1' then |
b := 1; |
else |
b := 0; |
end if; |
result := result * 2 + b; |
end loop; |
return result; |
end; --function bv_to_integer |
|
function bv_adder(a : in std_logic_vector(32 downto 0); |
b : in std_logic_vector(32 downto 0); |
do_sub: in std_logic) return std_logic_vector is |
variable carry_in : std_logic; |
variable bb : std_logic_vector(32 downto 0); |
variable result : std_logic_vector(32 downto 0); |
begin |
result := "000000000000000000000000000000000"; |
if do_sub = '0' then |
bb := b; |
carry_in := '0'; |
else |
bb := not b; |
carry_in := '1'; |
end if; |
for index in 0 to 32 loop |
result(index) := a(index) xor bb(index) xor carry_in; |
carry_in := (carry_in and (a(index) or bb(index))) or |
(a(index) and bb(index)); |
end loop; |
return result; |
end; --function |
|
function bv_adder_lookahead( |
a : in std_logic_vector(32 downto 0); |
b : in std_logic_vector(32 downto 0); |
do_sub: in std_logic) return std_logic_vector is |
variable carry : std_logic_vector(32 downto 0); |
variable p, g : std_logic_vector(32 downto 0); |
variable bb : std_logic_vector(32 downto 0); |
variable result : std_logic_vector(32 downto 0); |
variable i : natural; |
begin |
carry := "000000000000000000000000000000000"; |
if do_sub = '0' then |
bb := b; |
carry(0) := '0'; |
else |
bb := not b; |
carry(0) := '1'; |
end if; |
|
p := a or bb; --propogate |
g := a and bb; --generate |
for index in 0 to 7 loop |
i := index*4; |
carry(i+1) := g(i) or |
(p(i) and carry(i)); |
i := index*4+1; |
carry(i+1) := g(i) or |
(p(i) and g(i-1)) or |
((p(i) and p(i-1)) and carry(i-1)); |
i := index*4+2; |
carry(i+1) := g(i) or |
(p(i) and g(i-1)) or |
(p(i) and p(i-1) and g(i-2)) or |
((p(i) and p(i-1) and p(i-2)) and carry(i-2)); |
i := index*4+3; |
carry(i+1) := g(i) or |
(p(i) and g(i-1)) or |
(p(i) and p(i-1) and g(i-2)) or |
(p(i) and p(i-1) and p(i-2) and g(i-3)) or |
(((p(i) and p(i-1)) and (p(i-2) and p(i-3))) |
and carry(i-3)); |
end loop; |
result := (a xor bb) xor carry; |
return result; |
end; --function |
|
function bv_negate(a : in std_logic_vector) return std_logic_vector is |
variable carry_in : std_logic; |
variable not_a : std_logic_vector(31 downto 0); |
variable result : std_logic_vector(31 downto 0); |
begin |
result := ZERO; |
not_a := not a; |
carry_in := '1'; |
for index in a'reverse_range loop |
result(index) := not_a(index) xor carry_in; |
carry_in := carry_in and not_a(index); |
end loop; |
return result; |
end; --function |
|
function bv_increment(a : in std_logic_vector(31 downto 2) |
) return std_logic_vector is |
variable carry_in : std_logic; |
variable result : std_logic_vector(31 downto 2); |
begin |
result := "000000000000000000000000000000"; |
carry_in := '1'; |
for index in 2 to 31 loop |
result(index) := a(index) xor carry_in; |
carry_in := a(index) and carry_in; |
end loop; |
return result; |
end; --function |
|
function bv_inc6(a : in std_logic_vector |
) return std_logic_vector is |
variable carry_in : std_logic; |
variable result : std_logic_vector(5 downto 0); |
begin |
result := "000000"; |
carry_in := '1'; |
for index in 0 to 5 loop |
result(index) := a(index) xor carry_in; |
carry_in := a(index) and carry_in; |
end loop; |
return result; |
end; --function |
|
end; --package body |
|
|
/code.txt
0,0 → 1,640
341d8000 |
afbf0014 |
041100cb |
00000000 |
8fbf0014 |
03e00008 |
27bd0018 |
80ae0000 |
00801825 |
24840001 |
a08effff |
8082ffff |
24a50001 |
10400008 |
00000000 |
80af0000 |
24840001 |
24a50001 |
a08fffff |
8082ffff |
5440fffb |
80af0000 |
03e00008 |
00601025 |
27bdffa8 |
afb10018 |
afb00014 |
00c08025 |
00e08825 |
afbf001c |
afa40058 |
afa5005c |
240e0020 |
240f0020 |
24180020 |
a3b80042 |
a3af0041 |
a3ae0040 |
27a30043 |
27a4004f |
24020020 |
24630004 |
a062fffc |
a062fffd |
a062fffe |
1464fffb |
a062ffff |
8fb90058 |
a3a0004f |
8fa90058 |
07230005 |
24080001 |
2401000a |
12010002 |
2408ffff |
24080001 |
01280019 |
2405000e |
27a6004e |
2407000f |
00002012 |
00000000 |
00000000 |
0090001b |
16000002 |
00000000 |
0007000d |
00001010 |
00002012 |
2841000a |
54200002 |
24430030 |
24430057 |
14800006 |
a0c30000 |
8e2b0000 |
00e55023 |
014b082a |
50200005 |
2401ffff |
24a5ffff |
04a1ffed |
24c6ffff |
2401ffff |
15010004 |
240c002d |
a0ccffff |
24a5ffff |
24c6ffff |
8e220000 |
240d000f |
01a58023 |
10400003 |
0050082a |
10200006 |
8fa4005c |
8fa4005c |
0411ffa5 |
00c02825 |
10000005 |
ae300000 |
00027023 |
27af004f |
0411ff9f |
01cf2821 |
8fb00014 |
8fb10018 |
8fbf001c |
03e00008 |
27bd0058 |
27bdff58 |
afa600b0 |
00a03025 |
afbf0014 |
afa500ac |
27a50020 |
0411ffa3 |
27a700b0 |
83af0020 |
27ae0020 |
01c01025 |
51e00010 |
8fbf0014 |
81c30000 |
2406000d |
2405000a |
3404ffff |
a0830000 |
80580000 |
24420001 |
54b80004 |
80430000 |
2442ffff |
a0460000 |
80430000 |
5460fff8 |
a0830000 |
8fbf0014 |
03e00008 |
27bd00a8 |
2402001c |
3405ffff |
00441806 |
3063000f |
2c61000a |
10200004 |
2442fffc |
246e0030 |
10000003 |
a0ae0000 |
246f0057 |
a0af0000 |
0443fff6 |
00441806 |
03e00008 |
00000000 |
27bdffd8 |
afbf0024 |
afb30020 |
afb2001c |
afb10018 |
afb00014 |
24100003 |
241303e9 |
24120020 |
3411ffff |
2a010004 |
14200012 |
24020003 |
0202001a |
14400002 |
00000000 |
0007000d |
2401ffff |
14410004 |
3c018000 |
16010002 |
00000000 |
0006000d |
00007010 |
51c00005 |
00001025 |
24420002 |
0050082a |
1420fff0 |
00000000 |
50400007 |
26100002 |
02002025 |
2405000a |
0411ffaf |
00003025 |
a2320000 |
26100002 |
5613ffe4 |
2a010004 |
240f000a |
a22f0000 |
8fbf0024 |
8fb30020 |
8fb2001c |
8fb10018 |
8fb00014 |
00001025 |
03e00008 |
27bd0028 |
27bdff40 |
afbf0034 |
afb70030 |
afb6002c |
afb50028 |
afb40024 |
afb30020 |
afb2001c |
afb10018 |
afb00014 |
3c121234 |
36525678 |
00008025 |
24150020 |
3414ffff |
24110020 |
0411ffad |
02122007 |
26100001 |
1611fffc |
a2950000 |
2417000a |
3c139234 |
a2970000 |
36735678 |
00008025 |
0411ffa3 |
02132007 |
26100001 |
1611fffc |
a2950000 |
a2970000 |
00008025 |
0411ff9c |
02122004 |
26100001 |
1611fffc |
a2950000 |
a2970000 |
a2970000 |
00008825 |
2410004d |
02202025 |
2405000a |
0411ff73 |
00003025 |
26310007 |
1630fffa |
a2950000 |
3c11038f |
3c10038f |
a2970000 |
36106dab |
36315ae5 |
0411ff87 |
02202025 |
26310321 |
1630fffc |
a2950000 |
3c1105fb |
3c10061a |
a2970000 |
3610e149 |
36314e83 |
0411ff7d |
02202025 |
3c010005 |
34214321 |
02218821 |
1630fffa |
a2950000 |
3c110001 |
a2970000 |
36312345 |
24100001 |
2416000a |
0230001a |
16000002 |
00000000 |
0007000d |
2401ffff |
16010004 |
3c018000 |
16210002 |
00000000 |
0006000d |
00002012 |
0411ff66 |
00000000 |
26100001 |
1616fff1 |
a2950000 |
a2970000 |
24100001 |
0230001a |
16000002 |
00000000 |
0007000d |
2401ffff |
16010004 |
3c018000 |
16210002 |
00000000 |
0006000d |
00002010 |
0411ff54 |
00000000 |
26100001 |
1616fff1 |
a2950000 |
a2970000 |
a2970000 |
00008025 |
0411ff4c |
26041234 |
26100001 |
1616fffc |
a2950000 |
a2970000 |
00008025 |
24111234 |
0411ff44 |
02302023 |
26100001 |
1616fffc |
a2950000 |
a2970000 |
a2970000 |
0411ff3d |
24040220 |
a2950000 |
0411ff3a |
24045335 |
a2950000 |
0411ff37 |
24045115 |
a2950000 |
0411ff34 |
2404edcb |
a2950000 |
0411ff31 |
24041246 |
a2950000 |
0411ff2e |
24041222 |
a2970000 |
a2970000 |
240e0001 |
240f0001 |
24180001 |
afb8004c |
a7af008a |
a3ae00a9 |
afa00048 |
a7a00088 |
a3a000a8 |
24100002 |
27b200aa |
27b3008c |
27b10050 |
26020001 |
26030002 |
26040003 |
a2500000 |
a6700000 |
ae300000 |
26100004 |
a2440003 |
a6640006 |
ae24000c |
a2430002 |
a6630004 |
ae230008 |
a2420001 |
a6620002 |
ae220004 |
26520004 |
26730008 |
1616ffed |
26310010 |
27b200a8 |
27b30088 |
27b10048 |
27b60070 |
82440000 |
2405000a |
0411fee5 |
00003025 |
a2950000 |
86640000 |
2405000a |
0411fee0 |
00003025 |
a2950000 |
8e240000 |
2405000a |
0411fedb |
00003025 |
26310004 |
a2970000 |
26520001 |
1636ffee |
26730002 |
0411ff02 |
a2970000 |
24190064 |
a2990000 |
2408006f |
a2880000 |
2409006e |
a2890000 |
240a0065 |
a28a0000 |
a2970000 |
8fbf0034 |
8fb70030 |
8fb6002c |
8fb50028 |
8fb40024 |
8fb30020 |
8fb2001c |
8fb10018 |
8fb00014 |
03e00008 |
27bd00c0 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00001000 |
0000101c |
00000000 |
00000000 |
00001008 |
00001060 |
000011b8 |
00000000 |
00000000 |
00001080 |
000011b8 |
00001230 |
00000000 |
00000000 |
000011cc |
00001270 |
00001338 |
00000000 |
00000000 |
00001288 |
00001338 |
000016bc |
00000000 |
00000000 |
00001360 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
00000000 |
/reg_bank.vhd
0,0 → 1,169
--------------------------------------------------------------------- |
-- TITLE: Register Bank |
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
-- DATE CREATED: 2/2/01 |
-- FILENAME: reg_bank.vhd |
-- PROJECT: MIPS CPU core |
-- COPYRIGHT: Software placed into the public domain by the author. |
-- Software 'as is' without warranty. Author liable for nothing. |
-- DESCRIPTION: |
-- Implements a register bank with 32 registers that are 32-bits wide. |
-- There are two read-ports and one write port. |
--------------------------------------------------------------------- |
library ieee; |
use ieee.std_logic_1164.all; |
use work.mips_pack.all; |
|
entity reg_bank is |
port(clk : in std_logic; |
rs_index : in std_logic_vector(5 downto 0); |
rt_index : in std_logic_vector(5 downto 0); |
rd_index : in std_logic_vector(5 downto 0); |
reg_source_out : out std_logic_vector(31 downto 0); |
reg_target_out : out std_logic_vector(31 downto 0); |
reg_dest_new : in std_logic_vector(31 downto 0); |
intr_enable : out std_logic); |
end; --entity reg_bank |
|
architecture logic of reg_bank is |
signal reg31, reg01, reg02, reg03 : std_logic_vector(31 downto 0); |
--For Altera simulations, comment out reg04 through reg30 |
signal reg04, reg05, reg06, reg07 : std_logic_vector(31 downto 0); |
signal reg08, reg09, reg10, reg11 : std_logic_vector(31 downto 0); |
signal reg12, reg13, reg14, reg15 : std_logic_vector(31 downto 0); |
signal reg16, reg17, reg18, reg19 : std_logic_vector(31 downto 0); |
signal reg20, reg21, reg22, reg23 : std_logic_vector(31 downto 0); |
signal reg24, reg25, reg26, reg27 : std_logic_vector(31 downto 0); |
signal reg28, reg29, reg30 : std_logic_vector(31 downto 0); |
signal reg_epc : std_logic_vector(31 downto 0); |
signal reg_status : std_logic; |
begin |
|
reg_proc: process(clk, rs_index, rt_index, rd_index, reg_dest_new, |
reg31, reg01, reg02, reg03, reg04, reg05, reg06, reg07, |
reg08, reg09, reg10, reg11, reg12, reg13, reg14, reg15, |
reg16, reg17, reg18, reg19, reg20, reg21, reg22, reg23, |
reg24, reg25, reg26, reg27, reg28, reg29, reg30, |
reg_epc, reg_status) |
begin |
case rs_index is |
when "000000" => reg_source_out <= ZERO; |
when "000001" => reg_source_out <= reg01; |
when "000010" => reg_source_out <= reg02; |
when "000011" => reg_source_out <= reg03; |
when "000100" => reg_source_out <= reg04; |
when "000101" => reg_source_out <= reg05; |
when "000110" => reg_source_out <= reg06; |
when "000111" => reg_source_out <= reg07; |
when "001000" => reg_source_out <= reg08; |
when "001001" => reg_source_out <= reg09; |
when "001010" => reg_source_out <= reg10; |
when "001011" => reg_source_out <= reg11; |
when "001100" => reg_source_out <= reg12; |
when "001101" => reg_source_out <= reg13; |
when "001110" => reg_source_out <= reg14; |
when "001111" => reg_source_out <= reg15; |
when "010000" => reg_source_out <= reg16; |
when "010001" => reg_source_out <= reg17; |
when "010010" => reg_source_out <= reg18; |
when "010011" => reg_source_out <= reg19; |
when "010100" => reg_source_out <= reg20; |
when "010101" => reg_source_out <= reg21; |
when "010110" => reg_source_out <= reg22; |
when "010111" => reg_source_out <= reg23; |
when "011000" => reg_source_out <= reg24; |
when "011001" => reg_source_out <= reg25; |
when "011010" => reg_source_out <= reg26; |
when "011011" => reg_source_out <= reg27; |
when "011100" => reg_source_out <= reg28; |
when "011101" => reg_source_out <= reg29; |
when "011110" => reg_source_out <= reg30; |
when "011111" => reg_source_out <= reg31; |
when "101100" => reg_source_out <= ZERO(31 downto 1) & reg_status; |
when "101110" => reg_source_out <= reg_epc; --CP0 14 |
when "111111" => reg_source_out <= '1' & ZERO(30 downto 0); --intr vector |
when others => reg_source_out <= ZERO; |
end case; |
|
case rt_index is |
when "000000" => reg_target_out <= ZERO; |
when "000001" => reg_target_out <= reg01; |
when "000010" => reg_target_out <= reg02; |
when "000011" => reg_target_out <= reg03; |
when "000100" => reg_target_out <= reg04; |
when "000101" => reg_target_out <= reg05; |
when "000110" => reg_target_out <= reg06; |
when "000111" => reg_target_out <= reg07; |
when "001000" => reg_target_out <= reg08; |
when "001001" => reg_target_out <= reg09; |
when "001010" => reg_target_out <= reg10; |
when "001011" => reg_target_out <= reg11; |
when "001100" => reg_target_out <= reg12; |
when "001101" => reg_target_out <= reg13; |
when "001110" => reg_target_out <= reg14; |
when "001111" => reg_target_out <= reg15; |
when "010000" => reg_target_out <= reg16; |
when "010001" => reg_target_out <= reg17; |
when "010010" => reg_target_out <= reg18; |
when "010011" => reg_target_out <= reg19; |
when "010100" => reg_target_out <= reg20; |
when "010101" => reg_target_out <= reg21; |
when "010110" => reg_target_out <= reg22; |
when "010111" => reg_target_out <= reg23; |
when "011000" => reg_target_out <= reg24; |
when "011001" => reg_target_out <= reg25; |
when "011010" => reg_target_out <= reg26; |
when "011011" => reg_target_out <= reg27; |
when "011100" => reg_target_out <= reg28; |
when "011101" => reg_target_out <= reg29; |
when "011110" => reg_target_out <= reg30; |
when "011111" => reg_target_out <= reg31; |
when others => reg_target_out <= ZERO; |
end case; |
|
if rising_edge(clk) then |
-- assert reg_dest_new'last_event >= 10 ns |
-- report "Reg_dest timing error"; |
case rd_index is |
when "000001" => reg01 <= reg_dest_new; |
when "000010" => reg02 <= reg_dest_new; |
when "000011" => reg03 <= reg_dest_new; |
when "000100" => reg04 <= reg_dest_new; |
when "000101" => reg05 <= reg_dest_new; |
when "000110" => reg06 <= reg_dest_new; |
when "000111" => reg07 <= reg_dest_new; |
when "001000" => reg08 <= reg_dest_new; |
when "001001" => reg09 <= reg_dest_new; |
when "001010" => reg10 <= reg_dest_new; |
when "001011" => reg11 <= reg_dest_new; |
when "001100" => reg12 <= reg_dest_new; |
when "001101" => reg13 <= reg_dest_new; |
when "001110" => reg14 <= reg_dest_new; |
when "001111" => reg15 <= reg_dest_new; |
when "010000" => reg16 <= reg_dest_new; |
when "010001" => reg17 <= reg_dest_new; |
when "010010" => reg18 <= reg_dest_new; |
when "010011" => reg19 <= reg_dest_new; |
when "010100" => reg20 <= reg_dest_new; |
when "010101" => reg21 <= reg_dest_new; |
when "010110" => reg22 <= reg_dest_new; |
when "010111" => reg23 <= reg_dest_new; |
when "011000" => reg24 <= reg_dest_new; |
when "011001" => reg25 <= reg_dest_new; |
when "011010" => reg26 <= reg_dest_new; |
when "011011" => reg27 <= reg_dest_new; |
when "011100" => reg28 <= reg_dest_new; |
when "011101" => reg29 <= reg_dest_new; |
when "011110" => reg30 <= reg_dest_new; |
when "011111" => reg31 <= reg_dest_new; |
when "101100" => reg_status <= reg_dest_new(0); |
when "101110" => reg_epc <= reg_dest_new; --CP0 14 |
reg_status <= '0'; --disable interrupts |
when others => |
end case; |
end if; |
intr_enable <= reg_status; |
end process; |
|
end; --architecture logic |
|
/makefile
0,0 → 1,52
VHD = mips_pack alu bus_mux control mem_ctrl mult pc_next reg_bank shifter \ |
mips_cpu |
|
all: work/tbench/_primary.dat |
|
work/mips_pack/_primary.dat: mips_pack.vhd |
vcom -check_synthesis mips_pack.vhd |
|
work/alu/_primary.dat: mips_pack.vhd alu.vhd |
vcom -check_synthesis alu.vhd |
|
work/bus_mux/_primary.dat: mips_pack.vhd bus_mux.vhd |
vcom -check_synthesis bus_mux.vhd |
|
work/control/_primary.dat: mips_pack.vhd control.vhd |
vcom -check_synthesis control.vhd |
|
work/mem_ctrl/_primary.dat: mips_pack.vhd mem_ctrl.vhd |
vcom -check_synthesis mem_ctrl.vhd |
|
work/mult/_primary.dat: mips_pack.vhd mult.vhd |
vcom -check_synthesis mult.vhd |
|
work/pc_next/_primary.dat: mips_pack.vhd pc_next.vhd |
vcom -check_synthesis pc_next.vhd |
|
work/reg_bank/_primary.dat: mips_pack.vhd reg_bank.vhd |
vcom -check_synthesis reg_bank.vhd |
|
work/shifter/_primary.dat: mips_pack.vhd shifter.vhd |
vcom -check_synthesis shifter.vhd |
|
work/mips_cpu/_primary.dat: mips_cpu.vhd \ |
work/mips_pack/_primary.dat \ |
work/alu/_primary.dat \ |
work/bus_mux/_primary.dat \ |
work/control/_primary.dat \ |
work/mem_ctrl/_primary.dat \ |
work/mult/_primary.dat \ |
work/pc_next/_primary.dat \ |
work/reg_bank/_primary.dat \ |
work/shifter/_primary.dat |
vcom -check_synthesis mips_cpu.vhd |
|
work/ram/_primary.dat: ram.vhd |
vcom -explicit ram.vhd |
|
work/tbench/_primary.dat: tbench.vhd \ |
work/mips_cpu/_primary.dat \ |
work/ram/_primary.dat |
vcom tbench.vhd |
|