gokhan33
Newbie level 4
Who can modify the HDL code for the single-cycle MIPS processor to handle SRA(shift right arithmetic)...??
------------------------------------------------------------
-- mips.vhd
-- David_Harris@hmc.edu and Sarah_Harris@hmc.edu 30 May 2006
-- Single Cycle MIPS processor
------------------------------------------------------------
------------------------------------------------------------
-- Entity Declarations
------------------------------------------------------------
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity mips is -- single cycle MIPS processor
port(clk, reset: in STD_LOGIC;
pc: inout STD_LOGIC_VECTOR(31 downto 0);
instr: in STD_LOGIC_VECTOR(31 downto 0);
memwrite: out STD_LOGIC;
aluout, writedata: inout STD_LOGIC_VECTOR(31 downto 0);
readdata: in STD_LOGIC_VECTOR(31 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity controller is -- single cycle control decoder
port(op, funct: in STD_LOGIC_VECTOR(5 downto 0);
zero: in STD_LOGIC;
memtoreg, memwrite: out STD_LOGIC;
pcsrc, alusrc: out STD_LOGIC;
regdst, regwrite: out STD_LOGIC;
jump: out STD_LOGIC;
alucontrol: out STD_LOGIC_VECTOR(2 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity maindec is -- main control decoder
port(op: in STD_LOGIC_VECTOR(5 downto 0);
memtoreg, memwrite: out STD_LOGIC;
branch, alusrc: out STD_LOGIC;
regdst, regwrite: out STD_LOGIC;
jump: out STD_LOGIC;
aluop: out STD_LOGIC_VECTOR(1 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity aludec is -- ALU control decoder
port(funct: in STD_LOGIC_VECTOR(5 downto 0);
aluop: in STD_LOGIC_VECTOR(1 downto 0);
alucontrol: out STD_LOGIC_VECTOR(2 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all;
entity datapath is -- MIPS datapath
port(clk, reset: in STD_LOGIC;
memtoreg, pcsrc: in STD_LOGIC;
alusrc, regdst: in STD_LOGIC;
regwrite, jump: in STD_LOGIC;
alucontrol: in STD_LOGIC_VECTOR(2 downto 0);
zero: out STD_LOGIC;
pc: inout STD_LOGIC_VECTOR(31 downto 0);
instr: in STD_LOGIC_VECTOR(31 downto 0);
aluout, writedata: inout STD_LOGIC_VECTOR(31 downto 0);
readdata: in STD_LOGIC_VECTOR(31 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_UNSIGNED.all;
entity alu is -- Arithmetic/Logic unit with add/sub, AND, OR, set less than
port(a, b: in STD_LOGIC_VECTOR(31 downto 0);
alucontrol: in STD_LOGIC_VECTOR(2 downto 0);
result: inout STD_LOGIC_VECTOR(31 downto 0);
zero: out STD_LOGIC);
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity regfile is -- three-port register file
port(clk: in STD_LOGIC;
we3: in STD_LOGIC;
ra1, ra2, wa3: in STD_LOGIC_VECTOR(4 downto 0);
wd3: in STD_LOGIC_VECTOR(31 downto 0);
rd1, rd2: out STD_LOGIC_VECTOR(31 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity adder is -- adder
port(a, b: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity zerodetect is -- true if all input bits are zero
port(a: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC);
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity sl2 is -- shift left by 2
port(a: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity signext is -- sign extender
port(a: in STD_LOGIC_VECTOR(15 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all;
entity flopr is -- flip-flop with synchronous reset
generic(width: integer);
port(clk, reset: in STD_LOGIC;
d: in STD_LOGIC_VECTOR(width-1 downto 0);
q: out STD_LOGIC_VECTOR(width-1 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity mux2 is -- two-input multiplexer
generic(width: integer);
port(d0, d1: in STD_LOGIC_VECTOR(width-1 downto 0);
s: in STD_LOGIC;
y: out STD_LOGIC_VECTOR(width-1 downto 0));
end;
---------------------------------------------------------
-- Architecture Definitions
---------------------------------------------------------
architecture struct of mips is
component controller
port(op, funct: in STD_LOGIC_VECTOR(5 downto 0);
zero: in STD_LOGIC;
memtoreg, memwrite: out STD_LOGIC;
pcsrc, alusrc: out STD_LOGIC;
regdst, regwrite: out STD_LOGIC;
jump: out STD_LOGIC;
alucontrol: out STD_LOGIC_VECTOR(2 downto 0));
end component;
component datapath
port(clk, reset: in STD_LOGIC;
memtoreg, pcsrc: in STD_LOGIC;
alusrc, regdst: in STD_LOGIC;
regwrite, jump: in STD_LOGIC;
alucontrol: in STD_LOGIC_VECTOR(2 downto 0);
zero: out STD_LOGIC;
pc: inout STD_LOGIC_VECTOR(31 downto 0);
instr: in STD_LOGIC_VECTOR(31 downto 0);
aluout, writedata: inout STD_LOGIC_VECTOR(31 downto 0);
readdata: in STD_LOGIC_VECTOR(31 downto 0));
end component;
signal memtoreg, alusrc, regdst, regwrite, jump, pcsrc: STD_LOGIC;
signal zero: STD_LOGIC;
signal alucontrol: STD_LOGIC_VECTOR(2 downto 0);
begin
cont: controller port map(instr(31 downto 26), instr(5 downto 0),
zero, memtoreg, memwrite, pcsrc, alusrc,
regdst, regwrite, jump, alucontrol);
dp: datapath port map(clk, reset, memtoreg, pcsrc, alusrc, regdst,
regwrite, jump, alucontrol, zero, pc, instr,
aluout, writedata, readdata);
end;
architecture struct of controller is
component maindec
port(op: in STD_LOGIC_VECTOR(5 downto 0);
memtoreg, memwrite: out STD_LOGIC;
branch, alusrc: out STD_LOGIC;
regdst, regwrite: out STD_LOGIC;
jump: out STD_LOGIC;
aluop: out STD_LOGIC_VECTOR(1 downto 0));
end component;
component aludec
port(funct: in STD_LOGIC_VECTOR(5 downto 0);
aluop: in STD_LOGIC_VECTOR(1 downto 0);
alucontrol: out STD_LOGIC_VECTOR(2 downto 0));
end component;
signal aluop: STD_LOGIC_VECTOR(1 downto 0);
signal branch: STD_LOGIC;
begin
md: maindec port map(op, memtoreg, memwrite, branch,
alusrc, regdst, regwrite, jump, aluop);
ad: aludec port map(funct, aluop, alucontrol);
pcsrc <= branch and zero;
end;
architecture behave of maindec is
signal controls: STD_LOGIC_VECTOR(8 downto 0);
begin
process(op) begin
case op is
when "000000" => controls <= "110000010"; -- Rtype
when "100011" => controls <= "101001000"; -- LW
when "101011" => controls <= "001010000"; -- SW
when "000100" => controls <= "000100001"; -- BEQ
when "001000" => controls <= "101000000"; -- ADDI
when "000010" => controls <= "000000100"; -- J
when others => controls <= "---------"; -- illegal op
end case;
end process;
regwrite <= controls(8);
regdst <= controls(7);
alusrc <= controls(6);
branch <= controls(5);
memwrite <= controls(4);
memtoreg <= controls(3);
jump <= controls(2);
aluop <= controls(1 downto 0);
end;
architecture behave of aludec is
begin
process(aluop, funct) begin
case aluop is
when "00" => alucontrol <= "010"; -- add (for lb/sb/addi)
when "01" => alucontrol <= "110"; -- sub (for beq)
when others => case funct is -- R-type instructions
when "100000" => alucontrol <= "010"; -- add (for add)
when "100010" => alucontrol <= "110"; -- subtract (for sub)
when "100100" => alucontrol <= "000"; -- logical and (for and)
when "100101" => alucontrol <= "001"; -- logical or (for or)
when "101010" => alucontrol <= "111"; -- set on less (for slt)
when others => alucontrol <= "---"; -- should never happen
end case;
end case;
end process;
end;
architecture struct of datapath is
component alu
port(a, b: in STD_LOGIC_VECTOR(31 downto 0);
alucontrol: in STD_LOGIC_VECTOR(2 downto 0);
result: inout STD_LOGIC_VECTOR(31 downto 0);
zero: out STD_LOGIC);
end component;
component regfile
port(clk: in STD_LOGIC;
we3: in STD_LOGIC;
ra1, ra2, wa3: in STD_LOGIC_VECTOR(4 downto 0);
wd3: in STD_LOGIC_VECTOR(31 downto 0);
rd1, rd2: out STD_LOGIC_VECTOR(31 downto 0));
end component;
component zerodetect
port(a: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC);
end component;
component adder
port(a, b: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end component;
component sl2
port(a: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end component;
component signext
port(a: in STD_LOGIC_VECTOR(15 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end component;
component flopr generic(width: integer);
port(clk, reset: in STD_LOGIC;
d: in STD_LOGIC_VECTOR(width-1 downto 0);
q: out STD_LOGIC_VECTOR(width-1 downto 0));
end component;
component mux2 generic(width: integer);
port(d0, d1: in STD_LOGIC_VECTOR(width-1 downto 0);
s: in STD_LOGIC;
y: out STD_LOGIC_VECTOR(width-1 downto 0));
end component;
signal writereg: STD_LOGIC_VECTOR(4 downto 0);
signal pcjump, pcnext, pcnextbr, pcplus4, pcbranch: STD_LOGIC_VECTOR(31 downto 0);
signal signimm, signimmsh: STD_LOGIC_VECTOR(31 downto 0);
signal srca, srcb, result: STD_LOGIC_VECTOR(31 downto 0);
begin
-- next PC logic
pcjump <= pcplus4(31 downto 28) & instr(25 downto 0) & "00";
pcreg: flopr generic map(32) port map(clk, reset, pcnext, pc);
pcadd1: adder port map(pc, X"00000004", pcplus4);
immsh: sl2 port map(signimm, signimmsh);
pcadd2: adder port map(pcplus4, signimmsh, pcbranch);
pcbrmux: mux2 generic map(32) port map(pcplus4, pcbranch, pcsrc, pcnextbr);
pcmux: mux2 generic map(32) port map(pcnextbr, pcjump, jump, pcnext);
-- register file logic
rf: regfile port map(clk, regwrite, instr(25 downto 21), instr(20 downto 16),
writereg, result, srca, writedata);
wrmux: mux2 generic map(5) port map(instr(20 downto 16), instr(15 downto 11),
regdst, writereg);
resmux: mux2 generic map(32) port map(aluout, readdata, memtoreg, result);
se: signext port map(instr(15 downto 0), signimm);
-- ALU logic
srcbmux: mux2 generic map(32) port map(writedata, signimm, alusrc, srcb);
mainalu: alu port map(srca, srcb, alucontrol, aluout, zero);
end;
architecture behave of alu is
signal b2, sum, slt: STD_LOGIC_VECTOR(31 downto 0);
begin
b2 <= not b when alucontrol(2) = '1' else b;
sum <= a + b2 + alucontrol(2);
-- slt should be 1 if most significant bit of sum is 1
slt <= X"00000001" when sum(31) = '1' else X"00000000";
with alucontrol(1 downto 0) select result <=
a and b when "00",
a or b when "01",
sum when "10",
slt when others;
zero <= '1' when result = X"00000000" else '0';
end;
architecture behave of regfile is
type ramtype is array (31 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
signal mem: ramtype;
begin
-- three-ported register file
-- read two ports combinationally
-- write third port on rising edge of clock
process(clk) begin
if clk'event and clk = '1' then
if we3 = '1' then mem(CONV_INTEGER(wa3)) <= wd3;
end if;
end if;
end process;
process(ra1, ra2) begin
if (conv_integer(ra1) = 0) then rd1 <= X"00000000"; -- register 0 holds 0
else rd1 <= mem(CONV_INTEGER(ra1));
end if;
if (conv_integer(ra2) = 0) then rd2 <= X"00000000";
else rd2 <= mem(CONV_INTEGER(ra2));
end if;
end process;
end;
architecture behave of adder is
begin
y <= a + b;
end;
architecture behave of zerodetect is
begin
y <= '1' when a = X"00000000" else '0';
end;
architecture behave of sl2 is
begin
y <= a(29 downto 0) & "00";
end;
architecture behave of signext is
begin
y <= X"0000" & a when a(15) = '0' else X"ffff" & a;
end;
architecture asynchronous of flopr is
begin
process(clk, reset) begin
if reset = '1' then q <= CONV_STD_LOGIC_VECTOR(0, width);
elsif clk'event and clk = '1' then
q <= d;
end if;
end process;
end;
architecture behave of mux2 is
begin
y <= d0 when s = '0' else d1;
end;
--------------------------------------------------
-- mipsmem.vhd
-- Sarah_Harris@hmc.edu 27 May 2007
-- External memories used by MIPS single-cycle
-- processor
--------------------------------------------------
library IEEE; use IEEE.STD_LOGIC_1164.all;
use STD.TEXTIO.all;
use IEEE.STD_LOGIC_UNSIGNED.all; use IEEE.STD_LOGIC_ARITH.all;
entity dmem is -- data memory
port(clk, we: in STD_LOGIC;
a, wd: in STD_LOGIC_VECTOR(31 downto 0);
rd: out STD_LOGIC_VECTOR(31 downto 0));
end;
architecture behave of dmem is
begin
process is
type ramtype is array (63 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
variable mem: ramtype;
begin
-- read or write memory
loop
if clk'event and clk = '1' then
if (we = '1') then mem(CONV_INTEGER(a(7 downto 2))) := wd;
end if;
end if;
rd <= mem(CONV_INTEGER(a(7 downto 2)));
wait on clk, a;
end loop;
end process;
end;
library IEEE;
use IEEE.STD_LOGIC_1164.all; use STD.TEXTIO.all;
use IEEE.STD_LOGIC_UNSIGNED.all; use IEEE.STD_LOGIC_ARITH.all;
entity imem is -- instruction memory
port(a: in STD_LOGIC_VECTOR(5 downto 0);
rd: out STD_LOGIC_VECTOR(31 downto 0));
end;
architecture behave of imem is
begin
process is
file memfile: TEXT;
variable L: line;
variable ch: character;
variable index, result: integer;
type ramtype is array (63 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
variable mem: ramtype;
begin
-- initialize memory from file
for i in 0 to 63 loop -- set all contents low
mem(conv_integer(i)) := CONV_STD_LOGIC_VECTOR(0, 32);
end loop;
index := 0;
FILE_OPEN(memfile, "memfile.dat", READ_MODE);
while not endfile(memfile) loop
readline(memfile, L);
result := 0;
for i in 1 to 8 loop
read(L, ch);
-- debug
-- report "Reading line " & integer'image(index) &
-- " i = " & integer'image(i) & "character = " &
-- character'image(ch)
-- severity error;
if '0' <= ch and ch <= '9' then
result := result*16 + character'pos(ch) - character'pos('0');
elsif 'a' <= ch and ch <= 'f' then
result := result*16 + character'pos(ch) - character'pos('a')+10;
else report "Format error on line " & integer'image(index)
severity error;
end if;
end loop;
mem(index) := CONV_STD_LOGIC_VECTOR(result, 32);
index := index + 1;
end loop;
-- read memory
loop
rd <= mem(CONV_INTEGER(a));
wait on a;
end loop;
end process;
end;
------------------------------------------------------------
-- mips.vhd
-- David_Harris@hmc.edu and Sarah_Harris@hmc.edu 30 May 2006
-- Single Cycle MIPS processor
------------------------------------------------------------
------------------------------------------------------------
-- Entity Declarations
------------------------------------------------------------
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity mips is -- single cycle MIPS processor
port(clk, reset: in STD_LOGIC;
pc: inout STD_LOGIC_VECTOR(31 downto 0);
instr: in STD_LOGIC_VECTOR(31 downto 0);
memwrite: out STD_LOGIC;
aluout, writedata: inout STD_LOGIC_VECTOR(31 downto 0);
readdata: in STD_LOGIC_VECTOR(31 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity controller is -- single cycle control decoder
port(op, funct: in STD_LOGIC_VECTOR(5 downto 0);
zero: in STD_LOGIC;
memtoreg, memwrite: out STD_LOGIC;
pcsrc, alusrc: out STD_LOGIC;
regdst, regwrite: out STD_LOGIC;
jump: out STD_LOGIC;
alucontrol: out STD_LOGIC_VECTOR(2 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity maindec is -- main control decoder
port(op: in STD_LOGIC_VECTOR(5 downto 0);
memtoreg, memwrite: out STD_LOGIC;
branch, alusrc: out STD_LOGIC;
regdst, regwrite: out STD_LOGIC;
jump: out STD_LOGIC;
aluop: out STD_LOGIC_VECTOR(1 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity aludec is -- ALU control decoder
port(funct: in STD_LOGIC_VECTOR(5 downto 0);
aluop: in STD_LOGIC_VECTOR(1 downto 0);
alucontrol: out STD_LOGIC_VECTOR(2 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all;
entity datapath is -- MIPS datapath
port(clk, reset: in STD_LOGIC;
memtoreg, pcsrc: in STD_LOGIC;
alusrc, regdst: in STD_LOGIC;
regwrite, jump: in STD_LOGIC;
alucontrol: in STD_LOGIC_VECTOR(2 downto 0);
zero: out STD_LOGIC;
pc: inout STD_LOGIC_VECTOR(31 downto 0);
instr: in STD_LOGIC_VECTOR(31 downto 0);
aluout, writedata: inout STD_LOGIC_VECTOR(31 downto 0);
readdata: in STD_LOGIC_VECTOR(31 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_UNSIGNED.all;
entity alu is -- Arithmetic/Logic unit with add/sub, AND, OR, set less than
port(a, b: in STD_LOGIC_VECTOR(31 downto 0);
alucontrol: in STD_LOGIC_VECTOR(2 downto 0);
result: inout STD_LOGIC_VECTOR(31 downto 0);
zero: out STD_LOGIC);
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity regfile is -- three-port register file
port(clk: in STD_LOGIC;
we3: in STD_LOGIC;
ra1, ra2, wa3: in STD_LOGIC_VECTOR(4 downto 0);
wd3: in STD_LOGIC_VECTOR(31 downto 0);
rd1, rd2: out STD_LOGIC_VECTOR(31 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity adder is -- adder
port(a, b: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity zerodetect is -- true if all input bits are zero
port(a: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC);
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity sl2 is -- shift left by 2
port(a: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity signext is -- sign extender
port(a: in STD_LOGIC_VECTOR(15 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all;
entity flopr is -- flip-flop with synchronous reset
generic(width: integer);
port(clk, reset: in STD_LOGIC;
d: in STD_LOGIC_VECTOR(width-1 downto 0);
q: out STD_LOGIC_VECTOR(width-1 downto 0));
end;
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity mux2 is -- two-input multiplexer
generic(width: integer);
port(d0, d1: in STD_LOGIC_VECTOR(width-1 downto 0);
s: in STD_LOGIC;
y: out STD_LOGIC_VECTOR(width-1 downto 0));
end;
---------------------------------------------------------
-- Architecture Definitions
---------------------------------------------------------
architecture struct of mips is
component controller
port(op, funct: in STD_LOGIC_VECTOR(5 downto 0);
zero: in STD_LOGIC;
memtoreg, memwrite: out STD_LOGIC;
pcsrc, alusrc: out STD_LOGIC;
regdst, regwrite: out STD_LOGIC;
jump: out STD_LOGIC;
alucontrol: out STD_LOGIC_VECTOR(2 downto 0));
end component;
component datapath
port(clk, reset: in STD_LOGIC;
memtoreg, pcsrc: in STD_LOGIC;
alusrc, regdst: in STD_LOGIC;
regwrite, jump: in STD_LOGIC;
alucontrol: in STD_LOGIC_VECTOR(2 downto 0);
zero: out STD_LOGIC;
pc: inout STD_LOGIC_VECTOR(31 downto 0);
instr: in STD_LOGIC_VECTOR(31 downto 0);
aluout, writedata: inout STD_LOGIC_VECTOR(31 downto 0);
readdata: in STD_LOGIC_VECTOR(31 downto 0));
end component;
signal memtoreg, alusrc, regdst, regwrite, jump, pcsrc: STD_LOGIC;
signal zero: STD_LOGIC;
signal alucontrol: STD_LOGIC_VECTOR(2 downto 0);
begin
cont: controller port map(instr(31 downto 26), instr(5 downto 0),
zero, memtoreg, memwrite, pcsrc, alusrc,
regdst, regwrite, jump, alucontrol);
dp: datapath port map(clk, reset, memtoreg, pcsrc, alusrc, regdst,
regwrite, jump, alucontrol, zero, pc, instr,
aluout, writedata, readdata);
end;
architecture struct of controller is
component maindec
port(op: in STD_LOGIC_VECTOR(5 downto 0);
memtoreg, memwrite: out STD_LOGIC;
branch, alusrc: out STD_LOGIC;
regdst, regwrite: out STD_LOGIC;
jump: out STD_LOGIC;
aluop: out STD_LOGIC_VECTOR(1 downto 0));
end component;
component aludec
port(funct: in STD_LOGIC_VECTOR(5 downto 0);
aluop: in STD_LOGIC_VECTOR(1 downto 0);
alucontrol: out STD_LOGIC_VECTOR(2 downto 0));
end component;
signal aluop: STD_LOGIC_VECTOR(1 downto 0);
signal branch: STD_LOGIC;
begin
md: maindec port map(op, memtoreg, memwrite, branch,
alusrc, regdst, regwrite, jump, aluop);
ad: aludec port map(funct, aluop, alucontrol);
pcsrc <= branch and zero;
end;
architecture behave of maindec is
signal controls: STD_LOGIC_VECTOR(8 downto 0);
begin
process(op) begin
case op is
when "000000" => controls <= "110000010"; -- Rtype
when "100011" => controls <= "101001000"; -- LW
when "101011" => controls <= "001010000"; -- SW
when "000100" => controls <= "000100001"; -- BEQ
when "001000" => controls <= "101000000"; -- ADDI
when "000010" => controls <= "000000100"; -- J
when others => controls <= "---------"; -- illegal op
end case;
end process;
regwrite <= controls(8);
regdst <= controls(7);
alusrc <= controls(6);
branch <= controls(5);
memwrite <= controls(4);
memtoreg <= controls(3);
jump <= controls(2);
aluop <= controls(1 downto 0);
end;
architecture behave of aludec is
begin
process(aluop, funct) begin
case aluop is
when "00" => alucontrol <= "010"; -- add (for lb/sb/addi)
when "01" => alucontrol <= "110"; -- sub (for beq)
when others => case funct is -- R-type instructions
when "100000" => alucontrol <= "010"; -- add (for add)
when "100010" => alucontrol <= "110"; -- subtract (for sub)
when "100100" => alucontrol <= "000"; -- logical and (for and)
when "100101" => alucontrol <= "001"; -- logical or (for or)
when "101010" => alucontrol <= "111"; -- set on less (for slt)
when others => alucontrol <= "---"; -- should never happen
end case;
end case;
end process;
end;
architecture struct of datapath is
component alu
port(a, b: in STD_LOGIC_VECTOR(31 downto 0);
alucontrol: in STD_LOGIC_VECTOR(2 downto 0);
result: inout STD_LOGIC_VECTOR(31 downto 0);
zero: out STD_LOGIC);
end component;
component regfile
port(clk: in STD_LOGIC;
we3: in STD_LOGIC;
ra1, ra2, wa3: in STD_LOGIC_VECTOR(4 downto 0);
wd3: in STD_LOGIC_VECTOR(31 downto 0);
rd1, rd2: out STD_LOGIC_VECTOR(31 downto 0));
end component;
component zerodetect
port(a: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC);
end component;
component adder
port(a, b: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end component;
component sl2
port(a: in STD_LOGIC_VECTOR(31 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end component;
component signext
port(a: in STD_LOGIC_VECTOR(15 downto 0);
y: out STD_LOGIC_VECTOR(31 downto 0));
end component;
component flopr generic(width: integer);
port(clk, reset: in STD_LOGIC;
d: in STD_LOGIC_VECTOR(width-1 downto 0);
q: out STD_LOGIC_VECTOR(width-1 downto 0));
end component;
component mux2 generic(width: integer);
port(d0, d1: in STD_LOGIC_VECTOR(width-1 downto 0);
s: in STD_LOGIC;
y: out STD_LOGIC_VECTOR(width-1 downto 0));
end component;
signal writereg: STD_LOGIC_VECTOR(4 downto 0);
signal pcjump, pcnext, pcnextbr, pcplus4, pcbranch: STD_LOGIC_VECTOR(31 downto 0);
signal signimm, signimmsh: STD_LOGIC_VECTOR(31 downto 0);
signal srca, srcb, result: STD_LOGIC_VECTOR(31 downto 0);
begin
-- next PC logic
pcjump <= pcplus4(31 downto 28) & instr(25 downto 0) & "00";
pcreg: flopr generic map(32) port map(clk, reset, pcnext, pc);
pcadd1: adder port map(pc, X"00000004", pcplus4);
immsh: sl2 port map(signimm, signimmsh);
pcadd2: adder port map(pcplus4, signimmsh, pcbranch);
pcbrmux: mux2 generic map(32) port map(pcplus4, pcbranch, pcsrc, pcnextbr);
pcmux: mux2 generic map(32) port map(pcnextbr, pcjump, jump, pcnext);
-- register file logic
rf: regfile port map(clk, regwrite, instr(25 downto 21), instr(20 downto 16),
writereg, result, srca, writedata);
wrmux: mux2 generic map(5) port map(instr(20 downto 16), instr(15 downto 11),
regdst, writereg);
resmux: mux2 generic map(32) port map(aluout, readdata, memtoreg, result);
se: signext port map(instr(15 downto 0), signimm);
-- ALU logic
srcbmux: mux2 generic map(32) port map(writedata, signimm, alusrc, srcb);
mainalu: alu port map(srca, srcb, alucontrol, aluout, zero);
end;
architecture behave of alu is
signal b2, sum, slt: STD_LOGIC_VECTOR(31 downto 0);
begin
b2 <= not b when alucontrol(2) = '1' else b;
sum <= a + b2 + alucontrol(2);
-- slt should be 1 if most significant bit of sum is 1
slt <= X"00000001" when sum(31) = '1' else X"00000000";
with alucontrol(1 downto 0) select result <=
a and b when "00",
a or b when "01",
sum when "10",
slt when others;
zero <= '1' when result = X"00000000" else '0';
end;
architecture behave of regfile is
type ramtype is array (31 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
signal mem: ramtype;
begin
-- three-ported register file
-- read two ports combinationally
-- write third port on rising edge of clock
process(clk) begin
if clk'event and clk = '1' then
if we3 = '1' then mem(CONV_INTEGER(wa3)) <= wd3;
end if;
end if;
end process;
process(ra1, ra2) begin
if (conv_integer(ra1) = 0) then rd1 <= X"00000000"; -- register 0 holds 0
else rd1 <= mem(CONV_INTEGER(ra1));
end if;
if (conv_integer(ra2) = 0) then rd2 <= X"00000000";
else rd2 <= mem(CONV_INTEGER(ra2));
end if;
end process;
end;
architecture behave of adder is
begin
y <= a + b;
end;
architecture behave of zerodetect is
begin
y <= '1' when a = X"00000000" else '0';
end;
architecture behave of sl2 is
begin
y <= a(29 downto 0) & "00";
end;
architecture behave of signext is
begin
y <= X"0000" & a when a(15) = '0' else X"ffff" & a;
end;
architecture asynchronous of flopr is
begin
process(clk, reset) begin
if reset = '1' then q <= CONV_STD_LOGIC_VECTOR(0, width);
elsif clk'event and clk = '1' then
q <= d;
end if;
end process;
end;
architecture behave of mux2 is
begin
y <= d0 when s = '0' else d1;
end;
--------------------------------------------------
-- mipsmem.vhd
-- Sarah_Harris@hmc.edu 27 May 2007
-- External memories used by MIPS single-cycle
-- processor
--------------------------------------------------
library IEEE; use IEEE.STD_LOGIC_1164.all;
use STD.TEXTIO.all;
use IEEE.STD_LOGIC_UNSIGNED.all; use IEEE.STD_LOGIC_ARITH.all;
entity dmem is -- data memory
port(clk, we: in STD_LOGIC;
a, wd: in STD_LOGIC_VECTOR(31 downto 0);
rd: out STD_LOGIC_VECTOR(31 downto 0));
end;
architecture behave of dmem is
begin
process is
type ramtype is array (63 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
variable mem: ramtype;
begin
-- read or write memory
loop
if clk'event and clk = '1' then
if (we = '1') then mem(CONV_INTEGER(a(7 downto 2))) := wd;
end if;
end if;
rd <= mem(CONV_INTEGER(a(7 downto 2)));
wait on clk, a;
end loop;
end process;
end;
library IEEE;
use IEEE.STD_LOGIC_1164.all; use STD.TEXTIO.all;
use IEEE.STD_LOGIC_UNSIGNED.all; use IEEE.STD_LOGIC_ARITH.all;
entity imem is -- instruction memory
port(a: in STD_LOGIC_VECTOR(5 downto 0);
rd: out STD_LOGIC_VECTOR(31 downto 0));
end;
architecture behave of imem is
begin
process is
file memfile: TEXT;
variable L: line;
variable ch: character;
variable index, result: integer;
type ramtype is array (63 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
variable mem: ramtype;
begin
-- initialize memory from file
for i in 0 to 63 loop -- set all contents low
mem(conv_integer(i)) := CONV_STD_LOGIC_VECTOR(0, 32);
end loop;
index := 0;
FILE_OPEN(memfile, "memfile.dat", READ_MODE);
while not endfile(memfile) loop
readline(memfile, L);
result := 0;
for i in 1 to 8 loop
read(L, ch);
-- debug
-- report "Reading line " & integer'image(index) &
-- " i = " & integer'image(i) & "character = " &
-- character'image(ch)
-- severity error;
if '0' <= ch and ch <= '9' then
result := result*16 + character'pos(ch) - character'pos('0');
elsif 'a' <= ch and ch <= 'f' then
result := result*16 + character'pos(ch) - character'pos('a')+10;
else report "Format error on line " & integer'image(index)
severity error;
end if;
end loop;
mem(index) := CONV_STD_LOGIC_VECTOR(result, 32);
index := index + 1;
end loop;
-- read memory
loop
rd <= mem(CONV_INTEGER(a));
wait on a;
end loop;
end process;
end;