kirill_76rus

Untitled

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