Line 6... |
Line 6... |
entity datapath is
|
entity datapath is
|
port ( clock: in std_logic;
|
port ( clock: in std_logic;
|
reset: in std_logic;
|
reset: in std_logic;
|
|
|
stall: in std_logic;
|
stall: in std_logic;
|
busy: in std_logic;
|
|
|
|
irq_vector: in std_logic_vector(31 downto 0);
|
irq_vector: in std_logic_vector(31 downto 0);
|
irq: in std_logic;
|
irq: in std_logic;
|
irq_ack: out std_logic;
|
irq_ack: out std_logic;
|
|
|
inst_addr: out std_logic_vector(31 downto 0);
|
address: out std_logic_vector(31 downto 0);
|
inst_in: in std_logic_vector(31 downto 0);
|
|
|
|
data_addr: out std_logic_vector(31 downto 0);
|
|
data_in: in std_logic_vector(31 downto 0);
|
data_in: in std_logic_vector(31 downto 0);
|
data_out: out std_logic_vector(31 downto 0);
|
data_out: out std_logic_vector(31 downto 0);
|
data_w: out std_logic_vector(3 downto 0);
|
data_w: out std_logic_vector(3 downto 0);
|
data_access: out std_logic
|
data_access: out std_logic
|
);
|
);
|
Line 30... |
Line 26... |
signal data_in_s, pc, pc_last, pc_plus4, pc_next, result, branch, jump, ext32, ext32b, ext32h, alu_src: std_logic_vector(31 downto 0);
|
signal data_in_s, pc, pc_last, pc_plus4, pc_next, result, branch, jump, ext32, ext32b, ext32h, alu_src: std_logic_vector(31 downto 0);
|
signal opcode, funct: std_logic_vector(5 downto 0);
|
signal opcode, funct: std_logic_vector(5 downto 0);
|
signal read_reg1, read_reg2, write_reg, rs, rt, rd, target: std_logic_vector(4 downto 0);
|
signal read_reg1, read_reg2, write_reg, rs, rt, rd, target: std_logic_vector(4 downto 0);
|
signal write_data, read_data1, read_data2: std_logic_vector(31 downto 0);
|
signal write_data, read_data1, read_data2: std_logic_vector(31 downto 0);
|
signal imm: std_logic_vector(15 downto 0);
|
signal imm: std_logic_vector(15 downto 0);
|
signal wreg, zero, less_than, br_link_ctl, branch_taken, jump_taken, stall_reg: std_logic;
|
signal wreg, zero, less_than, br_link_ctl, branch_taken, jump_taken, mwait, stall_reg: std_logic;
|
signal irq_ack_s, irq_ack_s_dly, bds: std_logic;
|
signal irq_ack_s, irq_ack_s_dly, bds, data_access_s, data_access_s_dly: std_logic;
|
|
|
-- control signals
|
-- control signals
|
signal reg_dst_ctl, reg_write_ctl, alu_src_ctl, reg_to_mem_ctl, mem_to_reg_ctl, mem_to_reg_ctl_dly, signed_imm_ctl, signed_rd_ctl, shift_ctl: std_logic;
|
signal reg_dst_ctl, reg_write_ctl, alu_src_ctl, reg_to_mem_ctl, mem_to_reg_ctl, mem_to_reg_ctl_dly, signed_imm_ctl, signed_rd_ctl, shift_ctl: std_logic;
|
signal jump_ctl, mem_read_ctl, mem_write_ctl: std_logic_vector(1 downto 0);
|
signal jump_ctl, mem_read_ctl, mem_write_ctl: std_logic_vector(1 downto 0);
|
signal branch_ctl: std_logic_vector(2 downto 0);
|
signal branch_ctl: std_logic_vector(2 downto 0);
|
Line 54... |
Line 50... |
-- FETCH STAGE
|
-- FETCH STAGE
|
--
|
--
|
-- 1st stage, instruction memory access, PC update, interrupt acknowledge logic
|
-- 1st stage, instruction memory access, PC update, interrupt acknowledge logic
|
|
|
-- program counter logic
|
-- program counter logic
|
process(clock, reset, reg_to_mem_ctl_r, mem_to_reg_ctl_r, busy, stall)
|
process(clock, reset, reg_to_mem_ctl_r, mem_to_reg_ctl_r, mwait, stall)
|
begin
|
begin
|
if reset = '1' then
|
if reset = '1' then
|
pc <= (others => '0');
|
pc <= (others => '0');
|
pc_last <= (others => '0');
|
pc_last <= (others => '0');
|
elsif clock'event and clock = '1' then
|
elsif clock'event and clock = '1' then
|
if stall = '0' then
|
if stall = '0' then
|
if busy = '0' then
|
if mwait = '0' then
|
pc <= pc_next;
|
pc <= pc_next;
|
pc_last <= pc;
|
pc_last <= pc;
|
else
|
else
|
if (reg_to_mem_ctl_r = '1' or mem_to_reg_ctl_r = '1') and bds = '0' then
|
if (reg_to_mem_ctl_r = '1' or mem_to_reg_ctl_r = '1') and bds = '0' then
|
pc <= pc_last;
|
pc <= pc_last;
|
Line 87... |
Line 83... |
bds = '0' and branch_taken = '0' and jump_taken = '0' and
|
bds = '0' and branch_taken = '0' and jump_taken = '0' and
|
reg_to_mem_ctl_r = '0' and mem_to_reg_ctl_r = '0' else '0';
|
reg_to_mem_ctl_r = '0' and mem_to_reg_ctl_r = '0' else '0';
|
|
|
irq_ack <= irq_ack_s_dly;
|
irq_ack <= irq_ack_s_dly;
|
|
|
process(clock, reset, irq, irq_ack_s, mem_to_reg_ctl_r, busy, stall)
|
process(clock, reset, irq, irq_ack_s, mem_to_reg_ctl_r, mwait, stall)
|
begin
|
begin
|
if reset = '1' then
|
if reset = '1' then
|
irq_ack_s_dly <= '0';
|
irq_ack_s_dly <= '0';
|
bds <= '0';
|
bds <= '0';
|
mem_to_reg_ctl_dly <= '0';
|
mem_to_reg_ctl_dly <= '0';
|
stall_reg <= '0';
|
stall_reg <= '0';
|
|
data_access_s_dly <= '0';
|
elsif clock'event and clock = '1' then
|
elsif clock'event and clock = '1' then
|
stall_reg <= stall;
|
stall_reg <= stall;
|
if stall = '0' then
|
if stall = '0' then
|
mem_to_reg_ctl_dly <= mem_to_reg_ctl_r;
|
mem_to_reg_ctl_dly <= mem_to_reg_ctl_r;
|
if busy = '0' then
|
data_access_s_dly <= data_access_s;
|
|
if mwait = '0' then
|
irq_ack_s_dly <= irq_ack_s;
|
irq_ack_s_dly <= irq_ack_s;
|
if branch_taken = '1' or jump_taken = '1' then
|
if branch_taken = '1' or jump_taken = '1' then
|
bds <= '1';
|
bds <= '1';
|
else
|
else
|
bds <= '0';
|
bds <= '0';
|
Line 116... |
Line 114... |
-- DECODE STAGE
|
-- DECODE STAGE
|
--
|
--
|
-- 2nd stage, instruction decode, control unit operation, pipeline bubble insertion logic on load/store and 2nd branch delay slot
|
-- 2nd stage, instruction decode, control unit operation, pipeline bubble insertion logic on load/store and 2nd branch delay slot
|
|
|
-- instruction decode
|
-- instruction decode
|
opcode <= inst_in(31 downto 26);
|
opcode <= data_in(31 downto 26);
|
rs <= inst_in(25 downto 21);
|
rs <= data_in(25 downto 21);
|
rt <= inst_in(20 downto 16);
|
rt <= data_in(20 downto 16);
|
rd <= "11111" when br_link_ctl = '1' else inst_in(15 downto 11); -- FIXME: this will not work for the 'jalr rd, rs' format
|
rd <= "11111" when br_link_ctl = '1' else data_in(15 downto 11); -- FIXME: this will not work for the 'jalr rd, rs' format
|
funct <= inst_in(5 downto 0);
|
funct <= data_in(5 downto 0);
|
imm <= inst_in(15 downto 0);
|
imm <= data_in(15 downto 0);
|
|
|
-- control unit
|
-- control unit
|
control_hellfire: entity work.control
|
control_unit: entity work.control
|
port map( opcode => opcode,
|
port map( opcode => opcode,
|
funct => funct,
|
funct => funct,
|
rtx => rt,
|
rtx => rt,
|
reg_dst => reg_dst_ctl,
|
reg_dst => reg_dst_ctl,
|
reg_write => reg_write_ctl,
|
reg_write => reg_write_ctl,
|
Line 144... |
Line 142... |
mem_read => mem_read_ctl,
|
mem_read => mem_read_ctl,
|
signed_rd => signed_rd_ctl,
|
signed_rd => signed_rd_ctl,
|
shift => shift_ctl
|
shift => shift_ctl
|
);
|
);
|
|
|
process(clock, reset, busy, stall)
|
process(clock, reset, mwait, stall)
|
begin
|
begin
|
if reset = '1' then
|
if reset = '1' then
|
rs_r <= (others => '0');
|
rs_r <= (others => '0');
|
rt_r <= (others => '0');
|
rt_r <= (others => '0');
|
rd_r <= (others => '0');
|
rd_r <= (others => '0');
|
Line 187... |
Line 185... |
mem_write_ctl_r <= "00";
|
mem_write_ctl_r <= "00";
|
mem_read_ctl_r <= "00";
|
mem_read_ctl_r <= "00";
|
signed_rd_ctl_r <= '0';
|
signed_rd_ctl_r <= '0';
|
shift_ctl_r <= '0';
|
shift_ctl_r <= '0';
|
else
|
else
|
if busy = '0' then
|
if mwait = '0' then
|
if reg_to_mem_ctl_r = '1' or mem_to_reg_ctl_r = '1' or bds = '1' then
|
if reg_to_mem_ctl_r = '1' or mem_to_reg_ctl_r = '1' or bds = '1' then
|
rs_r <= (others => '0');
|
rs_r <= (others => '0');
|
rt_r <= (others => '0');
|
rt_r <= (others => '0');
|
rd_r <= (others => '0');
|
rd_r <= (others => '0');
|
imm_r <= (others => '0');
|
imm_r <= (others => '0');
|
Line 257... |
Line 255... |
read_reg2 <= "00000" when branch_ctl_r > "010" else -- source for branch and link (for zero operations)
|
read_reg2 <= "00000" when branch_ctl_r > "010" else -- source for branch and link (for zero operations)
|
rs_r when shift_ctl_r = '1' else rt_r; -- source for register based shifts or normal operations
|
rs_r when shift_ctl_r = '1' else rt_r; -- source for register based shifts or normal operations
|
write_reg <= target when mem_to_reg_ctl_r = '0' else rt_r;
|
write_reg <= target when mem_to_reg_ctl_r = '0' else rt_r;
|
ext32 <= x"0000" & imm_r when (imm_r(15) = '0' or signed_imm_ctl_r = '0') else x"ffff" & imm_r;
|
ext32 <= x"0000" & imm_r when (imm_r(15) = '0' or signed_imm_ctl_r = '0') else x"ffff" & imm_r;
|
target <= rt_r when reg_dst_ctl_r = '0' else rd_r; -- target register selection
|
target <= rt_r when reg_dst_ctl_r = '0' else rd_r; -- target register selection
|
wreg <= (reg_write_ctl_r or mem_to_reg_ctl_dly) and not busy and not stall_reg; -- enable the register bank for write back also
|
wreg <= (reg_write_ctl_r or mem_to_reg_ctl_dly) and not mwait and not stall_reg; -- enable the register bank for write back also
|
|
|
-- 3rd stage (b) ALU operation
|
-- 3rd stage (b) ALU operation
|
alu: entity work.alu
|
alu: entity work.alu
|
port map( op1 => read_data1,
|
port map( op1 => read_data1,
|
op2 => alu_src,
|
op2 => alu_src,
|
Line 283... |
Line 281... |
((zero = '0' and less_than = '1') and branch_ctl_r = "101") or -- BLTZ, BLTZAL
|
((zero = '0' and less_than = '1') and branch_ctl_r = "101") or -- BLTZ, BLTZAL
|
((zero = '1' or less_than = '0') and branch_ctl_r = "110") -- BGEZ, BGEZAL
|
((zero = '1' or less_than = '0') and branch_ctl_r = "110") -- BGEZ, BGEZAL
|
else '0';
|
else '0';
|
jump_taken <= '1' when jump_ctl_r /= "00" else '0'; -- J, JAL, JR, JALR
|
jump_taken <= '1' when jump_ctl_r /= "00" else '0'; -- J, JAL, JR, JALR
|
|
|
inst_addr <= pc;
|
address <= result when data_access_s = '1' and mwait = '1' else pc;
|
data_addr <= result; --result(31 downto 2) & "00";
|
data_access_s <= '1' when reg_to_mem_ctl_r = '1' or mem_to_reg_ctl_r = '1' else '0';
|
data_access <= '1' when reg_to_mem_ctl_r = '1' or mem_to_reg_ctl_r = '1' else '0';
|
mwait <= '1' when data_access_s = '1' and data_access_s_dly = '0' else '0';
|
|
data_access <= mwait;
|
|
|
|
|
-- 3rd stage (c) data memory / write back operation, register file access (write)
|
-- 3rd stage (c) data memory / write back operation, register file access (write)
|
-- memory access, store operations
|
-- memory access, store operations
|
process(mem_write_ctl_r, result, read_data2)
|
process(mem_write_ctl_r, result, read_data2)
|