Advertisement
kirill_76rus

mipsmulti

Jun 10th, 2021
1,376
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- still need to update this
  2. -- mipsmulti.vhd
  3. -- Updated to VHDL 2008 26 July 2011
  4. -- David_Harris@hmc.edu and Sarah_Harris@hmc.edu
  5.  
  6. library IEEE;
  7. use IEEE.STD_LOGIC_1164.all; use IEEE.NUMERIC_STD_UNSIGNED.all;
  8.  
  9. entity testbench is
  10. end;
  11.  
  12. architecture test of testbench is
  13.   component top
  14.     port(clk, reset:           in  STD_LOGIC;
  15.          writedata, dataadr:   out STD_LOGIC_VECTOR(31 downto 0);
  16.          memwrite:             out STD_LOGIC);
  17.   end component;
  18.   signal writedata, dataadr:    STD_LOGIC_VECTOR(31 downto 0);
  19.   signal clk, reset,  memwrite: STD_LOGIC;
  20. begin
  21.  
  22.   -- instantiate device to be tested
  23.   dut: top port map(clk, reset, writedata, dataadr, memwrite);
  24.  
  25.   -- Generate clock with 10 ns period
  26.   process begin
  27.     clk <= '1';
  28.     wait for 5 ns;
  29.     clk <= '0';
  30.     wait for 5 ns;
  31.   end process;
  32.  
  33.   -- Generate reset for first two clock cycles
  34.   process begin
  35.     reset <= '1';
  36.     wait for 22 ns;
  37.     reset <= '0';
  38.     wait;
  39.   end process;
  40.  
  41.   -- check that 7 gets written to address 84 at end of program
  42.   process (clk) begin
  43.     if (clk'event and clk = '0' and memwrite = '1') then
  44.       if (to_integer(dataadr) = 84 and to_integer(writedata) = 7) then
  45.         report "NO ERRORS: Simulation succeeded" severity failure;
  46.       elsif (dataadr /= 80) then
  47.         report "Simulation failed" severity failure;
  48.       end if;
  49.     end if;
  50.   end process;
  51. end;
  52.  
  53. library IEEE;
  54. use IEEE.STD_LOGIC_1164.all; use IEEE.NUMERIC_STD_UNSIGNED.all;
  55.  
  56. entity top is -- top-level design for testing
  57.   port(clk, reset:           in     STD_LOGIC;
  58.        writedata, dataadr:   buffer STD_LOGIC_VECTOR(31 downto 0);
  59.        memwrite:             buffer STD_LOGIC);
  60. end;
  61.  
  62. architecture test of top is
  63.   component mipsmulti
  64.     port(clk, reset:        in  STD_LOGIC;
  65.          adr:               out STD_LOGIC_VECTOR(31 downto 0);
  66.          writedata:         out STD_LOGIC_VECTOR(31 downto 0);
  67.          memwrite:          out STD_LOGIC;
  68.          readdata:          in  STD_LOGIC_VECTOR(31 downto 0));
  69.   end component;
  70.   component mem
  71.     port(clk, we:  in STD_LOGIC;
  72.          a, wd:    in STD_LOGIC_VECTOR(31 downto 0);
  73.          rd:       out STD_LOGIC_VECTOR(31 downto 0));
  74.   end component;
  75. *** start here.
  76.   signal pc, instr,
  77.          readdata: STD_LOGIC_VECTOR(31 downto 0);
  78. begin
  79.   -- instantiate processor and memories
  80.   mips1: mips port map(clk, reset, pc, instr, memwrite, dataadr,
  81.                        writedata, readdata);
  82.   imem1: imem port map(pc(7 downto 2), instr);
  83.   dmem1: dmem port map(clk, memwrite, dataadr, writedata, readdata);
  84. end;
  85.  
  86. library IEEE;
  87. use IEEE.STD_LOGIC_1164.all; use STD.TEXTIO.all;
  88. use IEEE.NUMERIC_STD_UNSIGNED.all;
  89.  
  90. entity dmem is -- data memory
  91.   port(clk, we:  in STD_LOGIC;
  92.        a, wd:    in STD_LOGIC_VECTOR(31 downto 0);
  93.        rd:       out STD_LOGIC_VECTOR(31 downto 0));
  94. end;
  95.  
  96. architecture behave of dmem is
  97. begin
  98.   process is
  99.     type ramtype is array (63 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
  100.     variable mem: ramtype;
  101.   begin
  102.     -- read or write memory
  103.     loop
  104.       if clk'event and clk = '1' then
  105.           if (we = '1') then mem(to_integer(a(7 downto 2))) := wd;
  106.           end if;
  107.       end if;
  108.       rd <= mem(to_integer(a(7 downto 2)));
  109.       wait on clk, a;
  110.     end loop;
  111.  
  112.   end process;
  113. end;
  114.  
  115. library IEEE;
  116. use IEEE.STD_LOGIC_1164.all; use STD.TEXTIO.all;
  117. use IEEE.NUMERIC_STD_UNSIGNED.all;  
  118.  
  119. entity imem is -- instruction memory
  120.   port(a:  in  STD_LOGIC_VECTOR(5 downto 0);
  121.        rd: out STD_LOGIC_VECTOR(31 downto 0));
  122. end;
  123.  
  124. architecture behave of imem is
  125. begin
  126.   process is
  127.     file mem_file: TEXT;
  128.     variable L: line;
  129.     variable ch: character;
  130.     variable i, index, result: integer;
  131.     type ramtype is array (63 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
  132.     variable mem: ramtype;
  133.   begin
  134.     -- initialize memory from file
  135.     for i in 0 to 63 loop -- set all contents low
  136.       mem(i) := (others => '0');
  137.     end loop;
  138.     index := 0;
  139.     FILE_OPEN(mem_file, "C:/docs/DDCA2e/hdl/memfile.dat", READ_MODE);
  140.     while not endfile(mem_file) loop
  141.       readline(mem_file, L);
  142.       result := 0; 
  143.       for i in 1 to 8 loop
  144.         read(L, ch);
  145.         if '0' <= ch and ch <= '9' then
  146.             result := character'pos(ch) - character'pos('0');
  147.         elsif 'a' <= ch and ch <= 'f' then
  148.            result := character'pos(ch) - character'pos('a')+10;
  149.         else report "Format error on line " & integer'image(index)
  150.              severity error;
  151.         end if;
  152.         mem(index)(35-i*4 downto 32-i*4) :=to_std_logic_vector(result,4);
  153.       end loop;
  154.       index := index + 1;
  155.     end loop;
  156.  
  157.     -- read memory
  158.     loop
  159.       rd <= mem(to_integer(a));
  160.       wait on a;
  161.     end loop;
  162.   end process;
  163. end;
  164.  
  165. library IEEE; use IEEE.STD_LOGIC_1164.all;
  166.  
  167. entity mips is -- single cycle MIPS processor
  168.   port(clk, reset:        in  STD_LOGIC;
  169.        pc:                out STD_LOGIC_VECTOR(31 downto 0);
  170.        instr:             in  STD_LOGIC_VECTOR(31 downto 0);
  171.        memwrite:          out STD_LOGIC;
  172.        aluout, writedata: out STD_LOGIC_VECTOR(31 downto 0);
  173.        readdata:          in  STD_LOGIC_VECTOR(31 downto 0));
  174. end;
  175.  
  176. architecture struct of mips is
  177.   component controller
  178.     port(op, funct:          in  STD_LOGIC_VECTOR(5 downto 0);
  179.          zero:               in  STD_LOGIC;
  180.          memtoreg, memwrite: out STD_LOGIC;
  181.          pcsrc, alusrc:      out STD_LOGIC;
  182.          regdst, regwrite:   out STD_LOGIC;
  183.          jump:               out STD_LOGIC;
  184.          alucontrol:         out STD_LOGIC_VECTOR(2 downto 0));
  185.   end component;
  186.   component datapath
  187.     port(clk, reset:        in  STD_LOGIC;
  188.          memtoreg, pcsrc:   in  STD_LOGIC;
  189.          alusrc, regdst:    in  STD_LOGIC;
  190.          regwrite, jump:    in  STD_LOGIC;
  191.          alucontrol:        in  STD_LOGIC_VECTOR(2 downto 0);
  192.          zero:              out STD_LOGIC;
  193.          pc:                buffer STD_LOGIC_VECTOR(31 downto 0);
  194.          instr:             in STD_LOGIC_VECTOR(31 downto 0);
  195.          aluout, writedata: buffer STD_LOGIC_VECTOR(31 downto 0);
  196.          readdata:          in  STD_LOGIC_VECTOR(31 downto 0));
  197.   end component;
  198.   signal memtoreg, alusrc, regdst, regwrite, jump, pcsrc: STD_LOGIC;
  199.   signal zero: STD_LOGIC;
  200.   signal alucontrol: STD_LOGIC_VECTOR(2 downto 0);
  201. begin
  202.   cont: controller port map(instr(31 downto 26), instr(5 downto 0),
  203.                             zero, memtoreg, memwrite, pcsrc, alusrc,
  204.                             regdst, regwrite, jump, alucontrol);
  205.   dp: datapath port map(clk, reset, memtoreg, pcsrc, alusrc, regdst,
  206.                         regwrite, jump, alucontrol, zero, pc, instr,
  207.                         aluout, writedata, readdata);
  208. end;
  209.  
  210. library IEEE; use IEEE.STD_LOGIC_1164.all;
  211.  
  212. entity controller is -- single cycle control decoder
  213.   port(op, funct:          in  STD_LOGIC_VECTOR(5 downto 0);
  214.        zero:               in  STD_LOGIC;
  215.        memtoreg, memwrite: out STD_LOGIC;
  216.        pcsrc, alusrc:      out STD_LOGIC;
  217.        regdst, regwrite:   out STD_LOGIC;
  218.        jump:               out STD_LOGIC;
  219.        alucontrol:         out STD_LOGIC_VECTOR(2 downto 0));
  220. end;
  221.  
  222.  
  223. architecture struct of controller is
  224.   component maindec
  225.     port(op:                 in  STD_LOGIC_VECTOR(5 downto 0);
  226.          memtoreg, memwrite: out STD_LOGIC;
  227.          branch, alusrc:     out STD_LOGIC;
  228.          regdst, regwrite:   out STD_LOGIC;
  229.          jump:               out STD_LOGIC;
  230.          aluop:              out STD_LOGIC_VECTOR(1 downto 0));
  231.   end component;
  232.   component aludec
  233.     port(funct:      in  STD_LOGIC_VECTOR(5 downto 0);
  234.          aluop:      in  STD_LOGIC_VECTOR(1 downto 0);
  235.          alucontrol: out STD_LOGIC_VECTOR(2 downto 0));
  236.   end component;
  237.   signal aluop:  STD_LOGIC_VECTOR(1 downto 0);
  238.   signal branch: STD_LOGIC;
  239. begin
  240.   md: maindec port map(op, memtoreg, memwrite, branch,
  241.                        alusrc, regdst, regwrite, jump, aluop);
  242.   ad: aludec port map(funct, aluop, alucontrol);
  243.  
  244.   pcsrc <= branch and zero;
  245. end;
  246.  
  247. library IEEE; use IEEE.STD_LOGIC_1164.all;
  248.  
  249. entity maindec is -- main control decoder
  250.   port(op:                 in  STD_LOGIC_VECTOR(5 downto 0);
  251.        memtoreg, memwrite: out STD_LOGIC;
  252.        branch, alusrc:     out STD_LOGIC;
  253.        regdst, regwrite:   out STD_LOGIC;
  254.        jump:               out STD_LOGIC;
  255.        aluop:              out STD_LOGIC_VECTOR(1 downto 0));
  256. end;
  257.  
  258. architecture behave of maindec is
  259.   signal controls: STD_LOGIC_VECTOR(8 downto 0);
  260. begin
  261.   process(all) begin
  262.     case op is
  263.       when "000000" => controls <= "110000010"; -- RTYPE
  264.       when "100011" => controls <= "101001000"; -- LW
  265.       when "101011" => controls <= "001010000"; -- SW
  266.       when "000100" => controls <= "000100001"; -- BEQ
  267.       when "001000" => controls <= "101000000"; -- ADDI
  268.       when "000010" => controls <= "000000100"; -- J
  269.       when others   => controls <= "---------"; -- illegal op
  270.     end case;
  271.   end process;
  272.  
  273.   (regwrite, regdst, alusrc, branch, memwrite,
  274.    memtoreg, jump, aluop(1 downto 0)) <= controls;
  275. end;
  276.  
  277. library IEEE; use IEEE.STD_LOGIC_1164.all;
  278.  
  279. entity aludec is -- ALU control decoder
  280.   port(funct:      in  STD_LOGIC_VECTOR(5 downto 0);
  281.        aluop:      in  STD_LOGIC_VECTOR(1 downto 0);
  282.        alucontrol: out STD_LOGIC_VECTOR(2 downto 0));
  283. end;
  284.  
  285. architecture behave of aludec is
  286. begin
  287.   process(all) begin
  288.     case aluop is
  289.       when "00" => alucontrol <= "010"; -- add (for lw/sw/addi)
  290.       when "01" => alucontrol <= "110"; -- sub (for beq)
  291.       when others => case funct is      -- R-type instructions
  292.                          when "100000" => alucontrol <= "010"; -- add
  293.                          when "100010" => alucontrol <= "110"; -- sub
  294.                          when "100100" => alucontrol <= "000"; -- and
  295.                          when "100101" => alucontrol <= "001"; -- or
  296.                          when "101010" => alucontrol <= "111"; -- slt
  297.                          when others   => alucontrol <= "---"; -- ???
  298.                      end case;
  299.     end case;
  300.   end process;
  301. end;
  302.  
  303. library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all;
  304.  
  305. entity datapath is  -- MIPS datapath
  306.   port(clk, reset:        in  STD_LOGIC;
  307.        memtoreg, pcsrc:   in  STD_LOGIC;
  308.        alusrc, regdst:    in  STD_LOGIC;
  309.        regwrite, jump:    in  STD_LOGIC;
  310.        alucontrol:        in  STD_LOGIC_VECTOR(2 downto 0);
  311.        zero:              out STD_LOGIC;
  312.        pc:                buffer STD_LOGIC_VECTOR(31 downto 0);
  313.        instr:             in  STD_LOGIC_VECTOR(31 downto 0);
  314.        aluout, writedata: buffer STD_LOGIC_VECTOR(31 downto 0);
  315.        readdata:          in  STD_LOGIC_VECTOR(31 downto 0));
  316. end;
  317.  
  318. architecture struct of datapath is
  319.   component alu
  320.     port(a, b:       in  STD_LOGIC_VECTOR(31 downto 0);
  321.          alucontrol: in  STD_LOGIC_VECTOR(2 downto 0);
  322.          result:     buffer STD_LOGIC_VECTOR(31 downto 0);
  323.          zero:       out STD_LOGIC);
  324.   end component;
  325.   component regfile
  326.     port(clk:           in  STD_LOGIC;
  327.          we3:           in  STD_LOGIC;
  328.          ra1, ra2, wa3: in  STD_LOGIC_VECTOR(4 downto 0);
  329.          wd3:           in  STD_LOGIC_VECTOR(31 downto 0);
  330.          rd1, rd2:      out STD_LOGIC_VECTOR(31 downto 0));
  331.   end component;
  332.   component adder
  333.     port(a, b: in  STD_LOGIC_VECTOR(31 downto 0);
  334.          y:    out STD_LOGIC_VECTOR(31 downto 0));
  335.   end component;
  336.   component sl2
  337.     port(a: in  STD_LOGIC_VECTOR(31 downto 0);
  338.          y: out STD_LOGIC_VECTOR(31 downto 0));
  339.   end component;
  340.   component signext
  341.     port(a: in  STD_LOGIC_VECTOR(15 downto 0);
  342.          y: out STD_LOGIC_VECTOR(31 downto 0));
  343.   end component;
  344.   component flopr generic(width: integer);
  345.     port(clk, reset: in  STD_LOGIC;
  346.          d:          in  STD_LOGIC_VECTOR(width-1 downto 0);
  347.          q:          out STD_LOGIC_VECTOR(width-1 downto 0));
  348.   end component;
  349.   component mux2 generic(width: integer);
  350.     port(d0, d1: in  STD_LOGIC_VECTOR(width-1 downto 0);
  351.          s:      in  STD_LOGIC;
  352.          y:      out STD_LOGIC_VECTOR(width-1 downto 0));
  353.   end component;
  354.   signal writereg:           STD_LOGIC_VECTOR(4 downto 0);
  355.   signal pcjump, pcnext,
  356.          pcnextbr, pcplus4,
  357.          pcbranch:           STD_LOGIC_VECTOR(31 downto 0);
  358.   signal signimm, signimmsh: STD_LOGIC_VECTOR(31 downto 0);
  359.   signal srca, srcb, result: STD_LOGIC_VECTOR(31 downto 0);
  360. begin
  361.   -- next PC logic
  362.   pcjump <= pcplus4(31 downto 28) & instr(25 downto 0) & "00";
  363.   pcreg: flopr generic map(32) port map(clk, reset, pcnext, pc);
  364.   pcadd1: adder port map(pc, X"00000004", pcplus4);
  365.   immsh: sl2 port map(signimm, signimmsh);
  366.   pcadd2: adder port map(pcplus4, signimmsh, pcbranch);
  367.   pcbrmux: mux2 generic map(32) port map(pcplus4, pcbranch,
  368.                                          pcsrc, pcnextbr);
  369.   pcmux: mux2 generic map(32) port map(pcnextbr, pcjump, jump, pcnext);
  370.  
  371.   -- register file logic
  372.   rf: regfile port map(clk, regwrite, instr(25 downto 21),
  373.                        instr(20 downto 16), writereg, result, srca,
  374.                 writedata);
  375.   wrmux: mux2 generic map(5) port map(instr(20 downto 16),
  376.                                       instr(15 downto 11),
  377.                                       regdst, writereg);
  378.   resmux: mux2 generic map(32) port map(aluout, readdata,
  379.                                         memtoreg, result);
  380.   se: signext port map(instr(15 downto 0), signimm);
  381.  
  382.   -- ALU logic
  383.   srcbmux: mux2 generic map(32) port map(writedata, signimm, alusrc,
  384.                                          srcb);
  385.   mainalu: alu port map(srca, srcb, alucontrol, aluout, zero);
  386. end;
  387.  
  388. library IEEE; use IEEE.STD_LOGIC_1164.all;
  389. use IEEE.NUMERIC_STD_UNSIGNED.all;
  390.  
  391. entity regfile is -- three-port register file
  392.   port(clk:           in  STD_LOGIC;
  393.        we3:           in  STD_LOGIC;
  394.        ra1, ra2, wa3: in  STD_LOGIC_VECTOR(4 downto 0);
  395.        wd3:           in  STD_LOGIC_VECTOR(31 downto 0);
  396.        rd1, rd2:      out STD_LOGIC_VECTOR(31 downto 0));
  397. end;
  398.  
  399. architecture behave of regfile is
  400.   type ramtype is array (31 downto 0) of STD_LOGIC_VECTOR(31 downto 0);
  401.   signal mem: ramtype;
  402. begin
  403.   -- three-ported register file
  404.   -- read two ports combinationally
  405.   -- write third port on rising edge of clock
  406.   -- register 0 hardwired to 0
  407.   -- note: for pipelined processor, write third port
  408.   -- on falling edge of clk
  409.   process(clk) begin
  410.     if rising_edge(clk) then
  411.        if we3 = '1' then mem(to_integer(wa3)) <= wd3;
  412.        end if;
  413.     end if;
  414.   end process;
  415.   process(all) begin
  416.     if (to_integer(ra1) = 0) then rd1 <= X"00000000"; -- register 0 holds 0
  417.     else rd1 <= mem(to_integer(ra1));
  418.     end if;
  419.     if (to_integer(ra2) = 0) then rd2 <= X"00000000";
  420.     else rd2 <= mem(to_integer(ra2));
  421.     end if;
  422.   end process;
  423. end;
  424.  
  425. library IEEE; use IEEE.STD_LOGIC_1164.all;
  426. use IEEE.NUMERIC_STD_UNSIGNED.all;
  427.  
  428. entity adder is -- adder
  429.   port(a, b: in  STD_LOGIC_VECTOR(31 downto 0);
  430.        y:    out STD_LOGIC_VECTOR(31 downto 0));
  431. end;
  432.  
  433. architecture behave of adder is
  434. begin
  435.   y <= a + b;
  436. end;
  437.  
  438.  
  439. library IEEE; use IEEE.STD_LOGIC_1164.all;
  440.  
  441. entity sl2 is -- shift left by 2
  442.   port(a: in  STD_LOGIC_VECTOR(31 downto 0);
  443.        y: out STD_LOGIC_VECTOR(31 downto 0));
  444. end;
  445.  
  446. architecture behave of sl2 is
  447. begin
  448.   y <= a(29 downto 0) & "00";
  449. end;
  450.  
  451. library IEEE; use IEEE.STD_LOGIC_1164.all;
  452.  
  453. entity signext is -- sign extender
  454.   port(a: in  STD_LOGIC_VECTOR(15 downto 0);
  455.        y: out STD_LOGIC_VECTOR(31 downto 0));
  456. end;
  457.  
  458. architecture behave of signext is
  459. begin
  460.   y <= X"ffff" & a when a(15) else X"0000" & a;
  461. end;
  462.  
  463. library IEEE; use IEEE.STD_LOGIC_1164.all;  use IEEE.STD_LOGIC_ARITH.all;
  464.  
  465. entity flopr is -- flip-flop with synchronous reset
  466.   generic(width: integer);
  467.   port(clk, reset: in  STD_LOGIC;
  468.        d:          in  STD_LOGIC_VECTOR(width-1 downto 0);
  469.        q:          out STD_LOGIC_VECTOR(width-1 downto 0));
  470. end;
  471.  
  472. architecture asynchronous of flopr is
  473. begin
  474.   process(clk, reset) begin
  475.     if reset then  q <= (others => '0');
  476.     elsif rising_edge(clk) then
  477.       q <= d;
  478.     end if;
  479.   end process;
  480. end;
  481.  
  482. library IEEE; use IEEE.STD_LOGIC_1164.all;
  483.  
  484. entity mux2 is -- two-input multiplexer
  485.   generic(width: integer);
  486.   port(d0, d1: in  STD_LOGIC_VECTOR(width-1 downto 0);
  487.        s:      in  STD_LOGIC;
  488.        y:      out STD_LOGIC_VECTOR(width-1 downto 0));
  489. end;
  490.  
  491. architecture behave of mux2 is
  492. begin
  493.   y <= d1 when s else d0;
  494. end;
  495.  
  496.  
  497. library IEEE; use IEEE.STD_LOGIC_1164.all;
  498. use IEEE.NUMERIC_STD_UNSIGNED.all;
  499.  
  500. entity alu is
  501.   port(a, b:       in  STD_LOGIC_VECTOR(31 downto 0);
  502.        alucontrol: in  STD_LOGIC_VECTOR(2 downto 0);
  503.        result:     buffer STD_LOGIC_VECTOR(31 downto 0);
  504.        zero:       out STD_LOGIC);
  505. end;
  506.  
  507. architecture behave of alu is
  508.   signal condinvb, sum: STD_LOGIC_VECTOR(31 downto 0);
  509. begin
  510.   condinvb <= not b when alucontrol(2) else b;
  511.   sum <= a + condinvb + alucontrol(2);
  512.  
  513.   process(all) begin
  514.     case alucontrol(1 downto 0) is
  515.       when "00"   => result <= a and b;
  516.       when "01"   => result <= a or b;
  517.       when "10"   => result <= sum;
  518.       when "11"   => result <= (0 => sum(31), others => '0');
  519.       when others => result <= (others => 'X');
  520.     end case;
  521.   end process;
  522.  
  523.   zero <= '1' when result = X"00000000" else '0';
  524. end;
  525.  
Advertisement
RAW Paste Data Copied
Advertisement