📄 mips.vhd
字号:
if clk'event and clk = '1' then
if reset = '1' then state <= FETCH1;
else state <= nextstate;
end if;
end if;
end process;
process (state, op) begin -- next state logic
case state is
when FETCH1 => nextstate <= FETCH2;
when FETCH2 => nextstate <= FETCH3;
when FETCH3 => nextstate <= FETCH4;
when FETCH4 => nextstate <= DECODE;
when DECODE => case op is
when LB | SB => nextstate <= MEMADR;
when RTYPE => nextstate <= RTYPEEX;
when BEQ => nextstate <= BEQEX;
when J => nextstate <= JEX;
when others => nextstate <= FETCH1; -- should never happen
end case;
when MEMADR => case op is
when LB => nextstate <= LBRD;
when SB => nextstate <= SBWR;
when others => nextstate <= FETCH1; -- should never happen
end case;
when LBRD => nextstate <= LBWR;
when LBWR => nextstate <= FETCH1;
when SBWR => nextstate <= FETCH1;
when RTYPEEX => nextstate <= RTYPEWR;
when RTYPEWR => nextstate <= FETCH1;
when BEQEX => nextstate <= FETCH1;
when JEX => nextstate <= FETCH1;
when others => nextstate <= FETCH1; -- should never happen
end case;
end process;
process (state) begin
-- set all outputs to zero, then conditionally assert just the appropriate ones
irwrite <= "0000";
pcwrite <= '0'; pcwritecond <= '0';
regwrite <= '0'; regdst <= '0';
memread <= '0'; memwrite <= '0';
alusrca <= '0'; alusrcb <= "00"; aluop <= "00";
pcsource <= "00";
iord <= '0'; memtoreg <= '0';
case state is
when FETCH1 => memread <= '1';
irwrite <= "1000";
alusrcb <= "01";
pcwrite <= '1';
when FETCH2 => memread <= '1';
irwrite <= "0100";
alusrcb <= "01";
pcwrite <= '1';
when FETCH3 => memread <= '1';
irwrite <= "0010";
alusrcb <= "01";
pcwrite <= '1';
when FETCH4 => memread <= '1';
irwrite <= "0001";
alusrcb <= "01";
pcwrite <= '1';
when DECODE => alusrcb <= "11";
when MEMADR => alusrca <= '1';
alusrcb <= "10";
when LBRD => memread <= '1';
iord <= '1';
when LBWR => regwrite <= '1';
memtoreg <= '1';
when SBWR => memwrite <= '1';
iord <= '1';
when RTYPEEX => alusrca <= '1';
aluop <= "10";
when RTYPEWR => regdst <= '1';
regwrite <= '1';
when BEQEX => alusrca <= '1';
aluop <= "01";
pcwritecond <= '1';
pcsource <= "01";
when JEX => pcwrite <= '1';
pcsource <= "10";
end case;
end process;
pcen <= pcwrite or (pcwritecond and zero); -- program counter enable
end;
architecture behave of alucontrol is
begin
process(aluop, funct)begin
case aluop is
when "00" => alucont <= "010"; -- add (for lb/sb/addi)
when "01" => alucont <= "110"; -- sub (for beq)
when others => case funct is -- R-type instructions
when "100000" => alucont <= "010"; -- add (for add)
when "100010" => alucont <= "110"; -- subtract (for sub)
when "100100" => alucont <= "000"; -- logical and (for and)
when "100101" => alucont <= "001"; -- logical or (for or)
when "101010" => alucont <= "111"; -- set on less (for slt)
when others => alucont <= "---"; -- should never happen
end case;
end case;
end process;
end;
architecture struct of datapath is
component alu generic(width: integer);
port(a, b: in STD_LOGIC_VECTOR(width-1 downto 0);
alucont: in STD_LOGIC_VECTOR(2 downto 0);
result: out STD_LOGIC_VECTOR(width-1 downto 0));
end component;
component regfile generic(width, regbits: integer);
port(clk: in STD_LOGIC;
write: in STD_LOGIC;
ra1, ra2, wa: in STD_LOGIC_VECTOR(regbits-1 downto 0);
wd: in STD_LOGIC_VECTOR(width-1 downto 0);
rd1, rd2: out STD_LOGIC_VECTOR(width-1 downto 0));
end component;
component zerodetect generic(width: integer);
port(a: in STD_LOGIC_VECTOR(width-1 downto 0);
y: out STD_LOGIC);
end component;
component flop generic(width: integer);
port(clk: in STD_LOGIC;
d: in STD_LOGIC_VECTOR(width-1 downto 0);
q: out STD_LOGIC_VECTOR(width-1 downto 0));
end component;
component flopen generic(width: integer);
port(clk, en: in STD_LOGIC;
d: in STD_LOGIC_VECTOR(width-1 downto 0);
q: out STD_LOGIC_VECTOR(width-1 downto 0));
end component;
component flopenr generic(width: integer);
port(clk, reset, en: 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;
component mux4 generic(width: integer);
port(d0, d1, d2, d3: in STD_LOGIC_VECTOR(width-1 downto 0);
s: in STD_LOGIC_VECTOR(1 downto 0);
y: out STD_LOGIC_VECTOR(width-1 downto 0));
end component;
constant CONST_ONE: STD_LOGIC_VECTOR(width-1 downto 0) := conv_std_logic_vector(1, width);
constant CONST_ZERO: STD_LOGIC_VECTOR(width-1 downto 0) := conv_std_logic_vector(0, width);
signal ra1, ra2, wa: STD_LOGIC_VECTOR(regbits-1 downto 0);
signal pc, nextpc, md, rd1, rd2, wd, a,
src1, src2, aluresult, aluout, dp_writedata, constx4: STD_LOGIC_VECTOR(width-1 downto 0);
signal dp_instr: STD_LOGIC_VECTOR(31 downto 0);
begin
-- shift left constant field by 2
constx4 <= dp_instr(width-3 downto 0) & "00";
-- register file addrss fields
ra1 <= dp_instr(regbits+20 downto 21);
ra2 <= dp_instr(regbits+15 downto 16);
regmux: mux2 generic map(regbits) port map(dp_instr(regbits+15 downto 16),
dp_instr(regbits+10 downto 11), regdst, wa);
-- independent of bit width, load dp_instruction into four 8-bit registers over four cycles
ir0: flopen generic map(8) port map(clk, irwrite(0), memdata(7 downto 0), dp_instr(7 downto 0));
ir1: flopen generic map(8) port map(clk, irwrite(1), memdata(7 downto 0), dp_instr(15 downto 8));
ir2: flopen generic map(8) port map(clk, irwrite(2), memdata(7 downto 0), dp_instr(23 downto 16));
ir3: flopen generic map(8) port map(clk, irwrite(3), memdata(7 downto 0), dp_instr(31 downto 24));
-- datapath
pcreg: flopenr generic map(width) port map(clk, reset, pcen, nextpc, pc);
mdr: flop generic map(width) port map(clk, memdata, md);
areg: flop generic map(width) port map(clk, rd1, a);
wrd: flop generic map(width) port map(clk, rd2, dp_writedata);
res: flop generic map(width) port map(clk, aluresult, aluout);
adrmux: mux2 generic map(width) port map(pc, aluout, iord, adr);
src1mux: mux2 generic map(width) port map(pc, a, alusrca, src1);
src2mux: mux4 generic map(width) port map(dp_writedata, CONST_ONE,
dp_instr(width-1 downto 0), constx4, alusrcb, src2);
pcmux: mux4 generic map(width) port map(aluresult, aluout, constx4, CONST_ZERO, pcsource, nextpc);
wdmux: mux2 generic map(width) port map(aluout, md, memtoreg, wd);
rf: regfile generic map(width, regbits) port map(clk, regwrite, ra1, ra2, wa, wd, rd1, rd2);
alunit: alu generic map(width) port map(src1, src2, alucont, aluresult);
zd: zerodetect generic map(width) port map(aluresult, zero);
-- drive outputs
instr <= dp_instr; writedata <= dp_writedata;
end;
architecture behave of alu is
signal b2, sum, slt: STD_LOGIC_VECTOR(width-1 downto 0);
begin
b2 <= not b when alucont(2) = '1' else b;
sum <= a + b2 + alucont(2);
-- slt should be 1 if most significant bit of sum is 1
slt <= conv_std_logic_vector(1, width) when sum(width-1) = '1'
else conv_std_logic_vector(0, width);
with alucont(1 downto 0) select result <=
a and b when "00",
a or b when "01",
sum when "10",
slt when others;
end;
architecture behave of regfile is
type ramtype is array (2**regbits-1 downto 0) of STD_LOGIC_VECTOR(width-1 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 write = '1' then mem(conv_integer(wa)) <= wd;
end if;
end if;
end process;
process(ra1, ra2) begin
if (conv_integer(ra1) = 0) then rd1 <= conv_std_logic_vector(0, width); -- register 0 holds 0
else rd1 <= mem(conv_integer(ra1));
end if;
if (conv_integer(ra2) = 0) then rd2 <= conv_std_logic_vector(0, width);
else rd2 <= mem(conv_integer(ra2));
end if;
end process;
end;
architecture behave of zerodetect is
signal i: integer;
signal x: STD_LOGIC_VECTOR(width-1 downto 1);
begin -- N-bit AND of inverted inputs
AllBits: for i in width-1 downto 1 generate
LowBit: if i = 1 generate
A1: x(1) <= not a(0) and not a(1);
end generate;
OtherBits: if i /= 1 generate
Ai: x(i) <= not a(i) and x(i-1);
end generate;
end generate;
y <= x(width-1);
end;
architecture behave of flop is
begin
process(clk) begin
if clk'event and clk = '1' then -- or use "if RISING_EDGE(clk) then"
q <= d;
end if;
end process;
end;
architecture behave of flopen is
begin
process(clk) begin
if clk'event and clk = '1' then
if en = '1' then q <= d;
end if;
end if;
end process;
end;
architecture synchronous of flopenr is
begin
process(clk) begin
if clk'event and clk = '1' then
if reset = '1' then
q <= CONV_STD_LOGIC_VECTOR(0, width); -- produce a vector of all zeros
elsif en = '1' then q <= d;
end if;
end if;
end process;
end;
architecture behave of mux2 is
begin
y <= d0 when s = '0' else d1;
end;
architecture behave of mux4 is
begin
y <= d0 when s = "00" else
d1 when s = "01" else
d2 when s = "10" else
d3;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -