• 串行CPU设计


    一、概述

    串行CPU工作流程

         串行CPU的时序流程如下图所示:取指、译码、执行、回写。 其中,取指、回写是与存储器打交道;而译码与执行则是CPU内部自个儿的操作。


    我们究竟想要CPU干什么?

        CPU的最终目的不是计算,不是把计算结果存储在通用寄存器中。CPU的最终目的应该是按照次序不断的修改存储设备的存储内容。

        利用CPU来显示,来唱歌······只有CPU把计算的结果存放在存储设备中的时候(姑且把修改特殊功能寄存器的值也看做是修改存储器的内容),才能实现这些功能。正如假设霍金有个很好的头脑来思考问题,但是假如他不能将思考到的东西通过某种方式告诉别人,那么没人会注意他。

        提出这个问题,主要是想要你关注“回写”的重要性。

    二、各组成模块

        本文的所有VHDL程序摘自《开放式实验CPU设计》第二章 “16位实验CPU设计实例”。

    1、通用寄存器组成部分 (regfile)

      1 --实验6.9——实验CPU:通用寄存器组
      2 library IEEE;
      3 use IEEE.STD_LOGIC_1164.ALL;
      4 
      5 entity regfile is
      6 Port (  DR:         in std_logic_vector(1 downto 0); 
      7         SR:         in std_logic_vector(1 downto 0);   
      8         reset:      in std_logic;
      9         DRWr:       in std_logic;                           
     10         clk:         in std_logic;    
     11         d_input:     in  std_logic_vector(15 downto 0);
     12         DR_data:    out std_logic_vector(15 downto 0);        
     13         SR_data:      out std_logic_vector(15 downto 0)   
     14       );
     15 end regfile;
     16 
     17 
     18 architecture struct of regfile is
     19 -- components
     20 -- 16 bit Register for register file
     21 component reg
     22 port    (
     23         clr:     in    std_logic;
     24         D:         in    std_logic_vector(15 downto 0);
     25         clock:     in    std_logic;
     26         write:  in    std_logic;
     27         sel:     in    std_logic;
     28         Q:         out std_logic_vector(15 downto 0)
     29         );
     30 end component;
     31 
     32 -- 2 to 4 Decoder
     33 component  decoder_2_to_4 
     34     port(
     35         sel:     in  std_logic_vector(1 downto 0);
     36         sel00:     out std_logic;
     37         sel01:     out std_logic;
     38         sel02:     out std_logic;
     39         sel03:     out std_logic
     40         );
     41 end component;
     42 
     43 -- 4 to 1 line multiplexer
     44 component mux_4_to_1
     45 port (
     46     input0,
     47     input1,
     48     input2,
     49     input3:  in std_logic_vector(15 downto 0);
     50     sel:     in std_logic_vector(1 downto 0);
     51     out_put: out std_logic_vector(15 downto 0));
     52 end component;
     53 
     54 
     55 signal reg00, reg01, reg02, reg03 
     56             :std_logic_vector(15 downto 0);
     57  
     58 signal sel00 ,sel01 ,sel02 ,sel03
     59             : std_logic;
     60 
     61 begin
     62 Areg00: reg port map(
     63         clr            =>  reset,
     64         D            =>    d_input ,
     65         clock        =>    clk ,        
     66         write        =>    DRWr ,
     67         sel            =>    sel00 ,    
     68         Q            =>  reg00
     69         );
     70 
     71 Areg01: reg port map(
     72         clr            =>  reset,
     73         D            =>    d_input ,
     74         clock        =>    clk ,        
     75         write        =>    DRWr ,
     76         sel            =>    sel01 ,    
     77         Q            =>  reg01    
     78         );
     79 
     80 Areg02: reg port map(
     81         clr            =>  reset,
     82         D            =>  d_input ,
     83         clock        =>    clk ,        
     84         write        =>    DRWr ,
     85         sel            =>    sel02 ,    
     86         Q            =>  reg02
     87         );
     88 
     89 Areg03: reg port map(
     90         clr            =>  reset,
     91         D            =>    d_input ,
     92         clock        =>    clk ,        
     93         write        =>    DRWr ,
     94         sel            =>    sel03 ,    
     95         Q            =>  reg03
     96         );
     97 
     98 -- decoder
     99 des_decoder: decoder_2_to_4 port map
    100         (
    101         sel     => DR,
    102         sel00     => sel00 ,
    103         sel01     => sel01 ,
    104         sel02     => sel02 ,
    105         sel03     => sel03 
    106         );
    107 
    108 mux1: mux_4_to_1 PORT MAP(
    109     Input0 => reg00 ,
    110     Input1 => reg01 ,
    111     Input2 => reg02 ,
    112     Input3 => reg03 ,
    113     sel => DR ,
    114     out_put => DR_data
    115     );
    116     
    117 mux2: mux_4_to_1 PORT MAP(
    118     input0     => reg00 ,
    119     input1     => reg01 ,
    120     input2     => reg02 ,
    121     input3     => reg03 ,
    122     sel     => SR ,
    123     out_put => SR_data
    124     );
    125 
    126 end struct;
    regfile

    如上图所示:

    (1)通用寄存器组是即可以读(两个口可以读),又可以写(只有一个口)

    (2)通用寄存器组是CPU暂存数据的单元;这里还包括程序状态标志位,跳转指令会用到

    2、取指部分 (instru_fetch) 

     1 library ieee, my_lib;
     2 use ieee.std_logic_1164.all;
     3 use ieee.std_logic_arith.all;
     4 use ieee.std_logic_unsigned.all;
     5 use my_lib.exp_cpu_components.all;
     6 
     7 entity instru_fetch  is
     8     port(reset,clk:     in std_logic;
     9         data_read:     in std_logic_vector(15 downto 0); --存储器读出的数
    10         lj_instruct: in std_logic; --长转移指令
    11         DW_intruct:     in std_logic;
    12         c_z_j_flag:  in std_logic; --为1时进行条件转移
    13         sjmp_addr:     in std_logic_vector(15 downto 0); --条件转移指令的转移地址
    14         t1,t2,t3:      buffer std_logic;
    15         pc:             buffer std_logic_vector(15 downto 0);
    16         pc_inc:         buffer std_logic_vector(15 downto 0);
    17         IR:             out std_logic_vector(15 downto 0)
    18         );
    19 end instru_fetch;
    20         
    21 architecture behav of instru_fetch is
    22 signal start:    std_logic;
    23 
    24 begin
    25 IR_poc: process(reset,t2)
    26 begin
    27     if reset = '0' then
    28         IR <= x"7000";  --nop指令
    29     elsif t2'event and t2 = '1' then
    30         IR <= data_read;
    31     end if;
    32 end process;
    33 
    34 process(reset,clk)
    35 begin
    36     if reset = '0' then
    37         start <= '1';
    38     else
    39         if clk'event and clk ='0' then
    40             start <= '0';
    41         end if;
    42     end if;
    43 end process;
    44 
    45 process(reset,clk)
    46 begin    
    47     if reset = '0' then
    48         t1 <= '0';
    49         t2 <= '0';
    50         t3 <= '0';
    51     elsif clk'event and clk = '1' then
    52         t1 <= start or t3;
    53         t2 <= t1;
    54         t3 <= t2;
    55     end if;
    56 end process;
    57 
    58 pc_inc <= pc + '1';        --为取双字指令的第2个字或者计算相对转移地址做准备
    59 PC_proc:    process(reset,t3)
    60 begin
    61    if reset = '0' then
    62         pc <= x"0000";
    63     elsif t3'event and t3 = '0' then
    64         if lj_instruct = '1' then
    65             pc <= data_read;
    66         elsif c_z_j_flag ='1' then
    67             pc <= sjmp_addr;
    68         elsif DW_intruct = '1' then
    69             pc <= pc + "10";
    70         else
    71             pc <= pc_inc;
    72         end if;
    73     end if;
    74 end process;
    75 
    76 end behav;
    77             
    78         
    79     
    instru_fetch

    (1)其实我更愿意把这部分分成两个部分,一个是取指模块,一个是控制器模块(产生CPU时序信号)

    (2)取指部分是在t2的上升沿完成的

    (3)PC的更新是在t3的下降沿完成的

    3、指令译码部分 (decoder_unit)

      1 library ieee, my_lib;
      2 use ieee.std_logic_1164.all;
      3 use ieee.std_logic_arith.all;
      4 use ieee.std_logic_unsigned.all;
      5 use my_lib.exp_cpu_components.all;
      6 
      7 entity decoder_unit is
      8     port   (IR:             in std_logic_vector(15 downto 0);
      9               SR:          out std_logic_vector(1 downto 0);
     10             DR:          out std_logic_vector(1 downto 0);
     11             op_code:     out std_logic_vector(2 downto 0);
     12               zj_instruct: out std_logic;
     13               cj_instruct: out std_logic;
     14               lj_instruct: out std_logic;
     15               DRWr:          buffer std_logic;  --为1时写DR寄存器
     16               Mem_Write:   out std_logic;
     17               DW_intruct:  buffer std_logic;
     18             change_z:    out std_logic;
     19             change_c:    out std_logic;
     20             sel_memdata: out std_logic;  --为1时存储器的读出数据作为写入DR的数据
     21               r_sjmp_addr:  out std_logic_vector(15 downto 0) --相对转移地址
     22             );
     23 end decoder_unit;
     24 
     25 architecture behav of decoder_unit is
     26 
     27 begin
     28 
     29 SR <= IR(9 downto 8);
     30 DR <= IR(11 downto 10);
     31 sel_memdata <= IR(15) and IR(14) and (not IR(13));
     32 change_z <= not IR(15) and IR(1);
     33 change_c <= not IR(15) and IR(2);
     34 
     35 DRWr_proc: process(IR)
     36 begin
     37     if IR(15) = '0' then
     38         if IR(0) ='1' then
     39             DRWr <= '1';
     40         else
     41             DRWr <= '0';
     42         end if;
     43     elsif IR(14) = '1' and IR(13) = '0' then
     44         DRWr <= '1';
     45     else
     46         DRWr <= '0';
     47     end if;
     48 end process;
     49  
     50 sj_addr_proc:    process(IR)  --条件转移指令的相对转移地址从8位扩展到16位
     51 begin
     52     if IR(7) ='1' then
     53         r_sjmp_addr <= "11111111" & IR(7 downto 0);
     54     else
     55         r_sjmp_addr <= "00000000" & IR(7 downto 0);
     56     end if;
     57 end process;
     58 
     59 M_instruct:process(IR)
     60 begin
     61     case IR(15 downto 12) is
     62         when "1000" | "1100" => --jmp addr;mvDR  dr,data
     63             Mem_Write <= '0';
     64             DW_intruct <= '1';
     65         when "1110" =>  -- str dr,sr
     66             Mem_Write <= '1';
     67             DW_intruct <= '0';
     68         when others =>
     69             Mem_Write <= '0';
     70             DW_intruct <= '0';
     71     end case;
     72 end process;
     73 
     74 ALUOP_CODE_PROC:    PROCESS(IR)
     75 begin
     76        if IR(15) = '0' then
     77         op_code <= IR(14 downto 12);
     78     else
     79         op_code <= "111";
     80     end if;
     81 end process;
     82 
     83 
     84 Jinstruct_PROC:    process(IR)
     85 begin
     86        case IR(15 downto 12) is
     87         when "1000" => --jmp adr
     88             zj_instruct <= '0';
     89             cj_instruct <= '0';
     90             lj_instruct <= '1';
     91         when "1001" => --jnc addr
     92             zj_instruct <= '0';
     93             cj_instruct <= '1';
     94             lj_instruct <= '0';
     95         when "1010" => --jnz addr
     96             zj_instruct <= '1';
     97             cj_instruct <= '0';
     98             lj_instruct <= '0';
     99         when others =>
    100             zj_instruct <= '0';
    101             cj_instruct <= '0';
    102             lj_instruct <= '0';
    103     end case;
    104 end process;
    105 
    106 end behav;
    107         
    decoder_unit

     

    (1)指令译码部分非常简单,是纯逻辑电路(速度非常快)。此模块根据指令暂存器IR特定的位,程序状态标志位c、z再结合设计好的指令系统将指令翻译出来。

    (2)译码的时机是在t2的高电平期间

    4、执行部分 (exe_unit)

     1 library ieee, my_lib;
     2 use ieee.std_logic_1164.all;
     3 use ieee.std_logic_arith.all;
     4 use ieee.std_logic_unsigned.all;
     5 use my_lib.exp_cpu_components.all;
     6 
     7 entity exe_unit is
     8     port(
     9           t1: in std_logic; 
    10         op_code:    in std_logic_vector(2 downto 0);
    11         zj_instruct: in std_logic;
    12           cj_instruct: in std_logic;
    13         pc: in std_logic_vector(15 downto 0);
    14         pc_inc:    in std_logic_vector(15 downto 0);
    15         c_in: in std_logic;  --以前指令产生的进位C
    16         z_in: in std_logic;  --以前指令产生的Z
    17         Mem_Write: in std_logic;  --为1时,写存储器
    18         c_tmp:    out std_logic;
    19         z_tmp:    out std_logic;
    20         c_z_j_flag: out std_logic; --为1时进行条件转移
    21         r_sjmp_addr:    in std_logic_vector(15 downto 0); --相对转移地址
    22         DW_intruct: in std_logic;
    23         sjmp_addr:    out std_logic_vector(15 downto 0); --条件转移指令的转移地址
    24         SR_data: in std_logic_vector(15 downto 0);
    25         DR_data: in std_logic_vector(15 downto 0);
    26         Mem_Addr: out std_logic_vector(15 downto 0);
    27         result: out std_logic_vector(15 downto 0)  --运算结果
    28         );
    29 
    30 end exe_unit;
    31 
    32 architecture behav of exe_unit is
    33 signal A,B :std_logic_vector(15 downto 0);
    34 signal result_t:  std_logic_vector(16 downto 0);
    35 
    36 begin
    37 c_z_j_flag <= ( (not c_in) and cj_instruct) or ((not z_in) and zj_instruct);
    38 A <= DR_data;
    39 B <= SR_data;
    40 sjmp_addr <= pc_inc + r_sjmp_addr;    
    41 
    42 Mem_Addr_proc: process(t1,SR_DATA,pc,DW_intruct)
    43 begin
    44     if t1 = '1' then
    45         Mem_Addr <= pc;
    46     else
    47         if DW_intruct = '1' then
    48             Mem_Addr <= pc_inc;
    49         elsif Mem_Write = '1' then
    50             Mem_Addr <= DR_data;
    51         else
    52             Mem_Addr <= SR_data;
    53         end if;
    54     end if;
    55 end process;
    56 
    57 alu_proc:process(op_code,A,B)
    58 begin
    59     case op_code is
    60         when "000" =>
    61             result_t <= ('0' & A) + ('0' & B);
    62         when "001" =>
    63             result_t <= ('0' & A) +  '1';
    64          when "010" =>
    65             result_t <= ('0' & A) - ('0' & B);
    66         when "011" =>
    67             result_t <= ('0' & A) -  '1';
    68         when "100" =>
    69             result_t <= ('0' & A) and ('0' & B);
    70         when "101" =>
    71             result_t <= ('0' & A) or ('0' & B);
    72         when "110" =>
    73             result_t <= not ('0' & A);
    74         when "111" =>
    75             result_t <=  ('0' & B);
    76     end case;
    77 end process;
    78 result <= result_t(15 downto 0);
    79 c_tmp <= result_t(16);
    80 z_tmp <= (not result_t(15)) and (not result_t(14)) and
    81         (not result_t(13)) and (not result_t(12)) and
    82         (not result_t(11)) and (not result_t(10)) and
    83         (not result_t(9)) and (not result_t(8)) and
    84         (not result_t(7)) and (not result_t(6)) and
    85         (not result_t(5)) and (not result_t(4)) and
    86         (not result_t(3)) and (not result_t(2)) and
    87         (not result_t(1)) and (not result_t(0));
    88 
    89 end behav;
    exe_unit

    (1)执行部分的主体也是纯逻辑电路,根据译码模块产生的控制信号,执行不同的运算,并将结果输出。

    (2)执行的时机是在t2的高电平期间

    5、存储器部分 (memory_unit)

     1 library IEEE, my_lib;
     2 use IEEE.std_logic_1164.all;
     3 use my_lib.exp_cpu_components.all;
     4 
     5 entity memory_unit is
     6     port(
     7         reset:    in std_logic;
     8         clk,t3:    in std_logic;
     9         Mem_addr:    in  std_logic_vector(15 downto 0);
    10         Mem_Write:    in std_logic;
    11         sel_memdata: in std_logic;  --为1时存储器的读出数据作为写入DR的数据
    12         SR_data: in std_logic_vector(15 downto 0); --写存储器的数据
    13         result: in std_logic_vector(15 downto 0);  --运算结果
    14         rw: out std_logic;
    15         ob: inout std_logic_vector(15 downto 0);
    16         ar: out std_logic_vector(15 downto 0);
    17         data_read: buffer  std_logic_vector(15 downto 0); --从存储器读出的指令或者数据
    18         DR_data_out:  out std_logic_vector(15 downto 0) --写入DR的数据
    19         );
    20 end memory_unit;
    21         
    22 architecture behav of memory_unit is
    23 begin
    24 
    25 ar <= Mem_addr;
    26 R_W_Memory_proc: process(reset,ob,SR_DATA,clk,t3,Mem_Write) --读写存储器处理
    27 begin
    28     if reset = '0' then
    29         rw <= '1';
    30         ob <= "ZZZZZZZZZZZZZZZZ";  --将存储器数据总线置为高阻,读存储器
    31     else
    32         if Mem_Write = '1' and t3 = '1' then
    33             ob <= SR_DATA;  --写存储器
    34             rw <= clk;
    35         else
    36             ob <= "ZZZZZZZZZZZZZZZZ";  --将存储器数据总线置为高阻,读存储器
    37             rw <= '1';
    38             data_read <= ob;
    39         end if;
    40     end if;
    41 end process;
    42 
    43 sele_DR_proc:  process(sel_memdata,data_read,result)
    44 begin
    45     if sel_memdata = '1' then
    46         DR_data_out <= data_read; --存储器数据作为写DR的数据
    47     else
    48         DR_data_out <= result;  --运算结果作为写DR的数据
    49     end if;
    50 end process;
    51 
    52 end behav;
    53             
    54         
    55     
    memory_unit

    (1)存储器控制部分主要是完成存储器的读写控制,以及通用寄存器的写控制。

    (2)写memory是在clk的下降沿(t3高电平期间),写DR是在t3的下降沿

    6、程序包(exp_cpu_components)

      1 library ieee;
      2 use ieee.std_logic_1164.all;
      3 
      4 package exp_cpu_components is
      5     component    reg port
      6        (reset:        in     std_logic;
      7         d_input:     in    std_logic_vector(15 downto 0);
      8         clk:        in    std_logic;
      9         write:        in    std_logic;
     10         sel:        in    std_logic;
     11         q_output:     out std_logic_vector(15 downto 0)
     12         );
     13     end component;
     14     
     15     component    mux_4_to_1 port
     16         (
     17         input0,
     18         input1,
     19         input2,
     20         input3:      in  std_logic_vector(15 downto 0);
     21         sel:         in  std_logic_vector(1 downto 0);
     22         out_put:     out std_logic_vector(15 downto 0)
     23         );
     24     end component;
     25     
     26     component    decoder_2_to_4    port
     27         (
     28          sel:    in std_logic_vector(1 downto 0);
     29          sel00:  out std_logic;
     30          sel01:  out std_logic;
     31          sel02:  out std_logic;
     32          sel03:  out std_logic
     33          );    
     34     end component;
     35     
     36     component regfile Port
     37         (DR:         in std_logic_vector(1 downto 0); 
     38         SR:         in std_logic_vector(1 downto 0);   
     39         reset:         in std_logic;
     40         write:         in std_logic;                           
     41         clk:         in std_logic;    
     42         d_input:     in  std_logic_vector(15 downto 0);
     43         change_z:     in std_logic;
     44         change_c:     in std_logic;
     45         c_in:       in std_logic;
     46         z_in:       in std_logic;
     47         R0,R1,R2,R3: out std_logic_vector(15 downto 0);
     48         output_DR:   out std_logic_vector(15 downto 0);        
     49         output_SR:   out std_logic_vector(15 downto 0);
     50         c_out:         out std_logic;
     51         z_out:         out std_logic   
     52         );
     53     end component;
     54     
     55     component instru_fetch port
     56         (
     57         reset,clk:     in std_logic;
     58         data_read:     in std_logic_vector(15 downto 0); --存储器读出的数
     59         lj_instruct: in std_logic; --长转移指令
     60         DW_intruct:     in std_logic; --双字指令
     61         c_z_j_flag:  in std_logic; --为1时进行条件转移
     62         sjmp_addr:     in std_logic_vector(15 downto 0); --条件转移指令的转移地址
     63         t1,t2,t3:      buffer std_logic;
     64         pc:             buffer std_logic_vector(15 downto 0);
     65         pc_inc:         buffer std_logic_vector(15 downto 0);
     66         IR:             out std_logic_vector(15 downto 0)
     67         );
     68     end component;
     69     
     70     component decoder_unit port
     71          (IR:              in std_logic_vector(15 downto 0);
     72          SR:           out std_logic_vector(1 downto 0);
     73          DR:           out std_logic_vector(1 downto 0);
     74          op_code:      out std_logic_vector(2 downto 0);
     75          zj_instruct:  out std_logic;
     76          cj_instruct:  out std_logic;
     77          lj_instruct:  out std_logic;
     78          DRWr:            buffer std_logic;  --为1时写DR寄存器
     79          Mem_Write:    out std_logic;
     80          DW_intruct:   buffer std_logic;
     81          change_z:     out std_logic;
     82          change_c:     out std_logic;
     83          sel_memdata:  out std_logic;  --为1时存储器的读出数据作为写入DR的数据
     84          r_sjmp_addr:  out std_logic_vector(15 downto 0) --相对转移地址
     85          );
     86     end component;
     87     
     88     component exe_unit port
     89         (t1:          in std_logic;
     90          op_code:     in std_logic_vector(2 downto 0);
     91          zj_instruct: in std_logic;
     92            cj_instruct: in std_logic;
     93          pc:             in std_logic_vector(15 downto 0);
     94          pc_inc:         in std_logic_vector(15 downto 0);
     95          c_in:          in std_logic;  --以前指令产生的进位C
     96          z_in:          in std_logic;  --以前指令产生的Z
     97          Mem_Write:  in std_logic;  --为1时,写存储器
     98          c_tmp:         out std_logic;
     99          z_tmp:         out std_logic;
    100          c_z_j_flag:  out std_logic; --为1时进行条件转移
    101          r_sjmp_addr: in std_logic_vector(15 downto 0); --相对转移地址
    102          DW_intruct : in std_logic;
    103          sjmp_addr:     out std_logic_vector(15 downto 0); --条件转移指令的转移地址
    104          SR_data:     in std_logic_vector(15 downto 0);
    105          DR_data:     in std_logic_vector(15 downto 0);
    106          Mem_Addr:    out std_logic_vector(15 downto 0);
    107          result:      out std_logic_vector(15 downto 0)  --运算结果
    108          );
    109     end component;
    110     
    111     component memory_unit port
    112         (reset:    in std_logic;
    113          clk,t3:    in std_logic;
    114          Mem_addr:    in  std_logic_vector(15 downto 0);
    115          Mem_Write:    in std_logic;
    116          sel_memdata: in std_logic;  --为1时存储器的读出数据作为写入DR的数据
    117          SR_data: in std_logic_vector(15 downto 0); --写存储器的数据
    118          result: in std_logic_vector(15 downto 0); --运算结果
    119          rw: out std_logic;
    120          ob: inout std_logic_vector(15 downto 0);
    121          ar:out std_logic_vector(15 downto 0);
    122          data_read: buffer  std_logic_vector(15 downto 0); --从存储器读出的指令或者数据
    123          DR_data_out:  out std_logic_vector(15 downto 0) --写入DR的数据
    124          );
    125     end component;
    126 end exp_cpu_components;
    exp_cpu_components

        将各个模块打包成一个元件库,为设计顶层实体提供方便。

    7、顶层设计实体 (exp_cpu)

    --实验6.13——实验CPU:CPU调试
    library ieee, my_lib;
    use ieee.std_logic_1164.all;
    use my_lib.exp_cpu_components.all;
    
    entity exp_cpu is port
        (
        clk:         in std_logic;              --//系统时钟
        reset:         in std_logic;              --//系统复位信号
        reg_sel:     in std_logic_vector(5 downto 0); --选择寄存器
        reg_content: out std_logic_vector(15 downto 0); --寄存器输出
        c_flag:         out std_logic;
        z_flag:         out std_logic;
        WE:            out std_logic;                    --//读写内存控制信号
        AR:  out std_logic_vector(15 downto 0);     --//读写内存地址
        OB:  inout std_logic_vector(15 downto 0)      --//外部总线
        );
    end exp_cpu;
    
    architecture behav of exp_cpu is
        --instru_fetch out
    signal t1,t2,t3: std_logic;
    signal pc,pc_inc,IR: std_logic_vector(15 downto 0);
        --decoder_unit out
    signal SR,DR: std_logic_vector(1 downto 0);
    signal op_code:    std_logic_vector(2 downto 0);
    signal zj_instruct,cj_instruct,lj_instruct: std_logic;
    signal DRWr,Mem_Write,DW_intruct,change_z:  std_logic;
    signal change_c,sel_memdata: std_logic;
    signal r_sjmp_addr: std_logic_vector(15 downto 0);
        --exe_unit out
    signal c_tmp,z_tmp,c_z_j_flag: std_logic;
    signal Mem_Addr,result,sjmp_addr: std_logic_vector(15 downto 0);
        --memory out
    signal data_read,DR_data_out:  std_logic_vector(15 downto 0);
        --regfile out
    signal R0,R1,R2,R3:  std_logic_vector(15 downto 0);
    signal output_DR,output_SR:  std_logic_vector(15 downto 0);
    signal c_out,z_out:     std_logic;  
    begin
    c_flag <= c_out;
    z_flag <= z_out;
    
    TEST_OUT:  process(reg_sel)  --被测信号以寄存器内容输出
    begin
        case reg_sel is
            when "000000" =>
                reg_content <= R0;
            when "000001" =>
                reg_content <= R1;
            when "000010" =>
                reg_content <= R2;
            when "000011" =>
                reg_content <= R3;
            when "000100" =>
                reg_content <= "0000000" & t3 & "000" & t2 & "000" & t1;
            when "111110" => 
                reg_content <= pc;
            when "111111" =>
                reg_content <= IR;
            when others =>
                reg_content <= x"0000";    
        end case;
    end process;
    --reg_content <= R0; --实际测试中是用这句话代替了上边的进程,也就是说默认选择R0作为要输出显示的寄存器
    
    G_INSTRU_FETCH:  instru_fetch port map
           (reset => reset,
            clk => clk,        
            data_read => data_read,  --存储器读出的数
            lj_instruct => lj_instruct, --来自decoder的长转移指令标志
            DW_intruct => DW_intruct, --来自decoder的双字指令标志
            c_z_j_flag => c_z_j_flag, --为1时进行条件转移,来自EXE
            sjmp_addr => sjmp_addr, --条件转移指令的转移地址,来自EXE
            t1 => t1,
            t2 => t2,
            t3 => t3,
            pc => pc,
            pc_inc => pc_inc,
            IR => IR
            );
            
    G_DECODER:    decoder_unit port map
           (IR => IR,    --来自instru_fetch
            SR => SR,   --源寄存器号
            DR => DR,    --目的寄存器号
            op_code => op_code,  --ALU运算的操作码
            zj_instruct => zj_instruct, --为1时是如果Z=0则转移指令
            cj_instruct => cj_instruct, --为1时是如果C=0则转移指令
            lj_instruct => lj_instruct, --为1时是无条件长转移指令
            DRWr => DRWr,  --为1时在t3下降沿写DR寄存器,送往regfile
            Mem_Write => Mem_Write,  --为1时对存储器进行写操作。
            DW_intruct => DW_intruct, --为1时是双字指令
            change_z => change_z,  --为1时在t3下降沿根据指令执行结果置Z标志
            change_c => change_c,  --为1时在t3下降沿根据指令执行结果置Z标志
            sel_memdata => sel_memdata,  --为1时存储器的读出数据作为写入DR的数据
            r_sjmp_addr => r_sjmp_addr --相对转移地址
            );
            
    G_EXE:    exe_unit port map
            (
              t1 => t1,
            op_code => op_code, --ALU运算的操作码,来自decoder
            zj_instruct => zj_instruct, --为1时是如果Z=1则转移指令,来自decoder
              cj_instruct => cj_instruct, --为1时是如果C=1则转移指令,来自decoder
            pc => pc,  --来自instru_fetch
            pc_inc => pc_inc, --来自instru_fetch
            c_in => c_out,--以前指令产生的进位C,来自regfile
            z_in => z_out,  --以前指令产生的Z,来自regfile
            Mem_Write => Mem_Write, --存储器写,来自decoder_unit
            c_tmp => c_tmp, --本条指令产生的Z标志送往regfile
            z_tmp => z_tmp, --本条指令产生的Z标志送往regfile
            c_z_j_flag => c_z_j_flag, --为1时进行条件转移,送往instru_fetch
            r_sjmp_addr => r_sjmp_addr,  --相对转移地址,来自decoder
            DW_intruct => DW_intruct,  --双字指令标志,来自decoder,送往
            sjmp_addr =>  sjmp_addr,--条件转移指令的转移地址instru_fetch
            SR_data => output_SR,  --SR寄存器值,来自regfile
            DR_data => output_DR,  --SR寄存器值,来自regfile
            Mem_Addr => Mem_Addr, --存储器地址,送往memory
            result => result  --运算结果,送往regfile
            );
        
    G_MEMORY:    memory_unit port map
           (reset => reset,
            clk   => clk,
            t3    => t3, 
            Mem_addr  => Mem_addr,  --存储器地址,来自exe_unit
            Mem_Write => Mem_Write, --存储器写,来自decoder_unit
            sel_memdata => sel_memdata,  --为1时存储器的读出数据作为写入DR的数据,来自decoder
            SR_data => output_SR,--写存储器的数据,来自regfile
            result => result, --运算结果,来自exe_unit
            rw => WE,  --存储器读写信号,送往芯片外部
            ob => ob,  --存储器数据总线,和芯片外部存储器数据总线连接
            ar => AR,  --存储器地址,送往芯片外部和存储器地址总线连接
            data_read   => data_read, --从存储器读出的指令,送往instru_fetch
            DR_data_out => DR_data_out --写入DR的数据,送往regfile
            );
            
    G_REGFILE:    regfile port map
            (DR => DR,  --DR寄存器号,来自decoder
            SR => SR,  --SR寄存器号,来自decoder
            reset => reset,
            write => DRWr, --寄存器写控制信号,来自decoder                          
            clk => t3,    --寄存器写入脉冲,来自instru_fetch,下降沿写入
            d_input => DR_data_out, --写入寄存器的数据,来自memory
            change_z => change_z, --为1时在t4下降沿根据Z_tmp置Z标志,来自decoder
            change_c => change_c, --为1时在t4下降沿根据C_tmp置C标志,来自decoder
            c_in => c_tmp, --本条指令得到的c,来自decoder
            z_in => z_tmp, --本条指令得到的c,来自decoder
            R0 => R0,
            R1 => R1,
            R2 => R2,
            R3 => R3,
            output_DR => output_DR,   --DR寄存器内容,送往exe和memory     
            output_SR => output_SR,   --SR寄存器内容,送往exe
            c_out => c_out,  --C标志,送往exe和exp
            z_out => z_out   --Z标志,送往exe和exp
            );
    
    end behav;
    exp_cpu

    (1)此部分代码实际上就是如上图所示那样,用导线将CPU的各个独立模块连接在一起,构成一个完整的CPU

    (2)此外该部分还加入了测试模块,以便将寄存器的内容或者PC的值从内部引出到外部,供我们去观察

    三、实验环节

    1、实验目的

        测试串行CPU的能否按照预期指令功能那样正常工作

    2、实验方法

        给CPU配以程序存储器ROM(内含三条指令),CPU在低速时钟运行条件下,执行指令,并且将执行指令而改变的寄存器内容引出来通过8位led显示出来。

    3、实验内容

    (1)实验电路图

     

    (1)开发板上的时钟是50MHz,经过50M的分频,实际输送给CPU的主频才1Hz。设置如此低的频率,目的是为了有足够的时间观察每一条指令的执行效果。

    (2)PLL分频后的时钟10MHz送给了ROM,因为ROM也需要时钟线。本实验用ROM代替了RAM(HM6116),显然缺失了写的功能。为了让该ROM的操作如同可读静态RAM(HM6116)一样,用10MHz的时钟。可以看到,只要给ROM发送地址,ROM马上就把相应的数据发送出来。

    (1)给ROM加一个16位地址变换为8位地址的目的是,本实验不需要用那么大的存储器,所以讲容量调整的小一点。

    (2)本实验的输出寄存器直接是R0的内容,这一点在之前也有提到。由于实验板上只有8位led,所以执行指令的功能也只是改变R0的低8位。所以,高8位没必要保留,就通过加上一个地址变换器滤除无用的高8位。

    (2)实验CPU程序

                   ROM存储器中的数据

    翻译成指令:

      movrd r0,#2

      movrd r0,#8

      movrd r0,#6

    (3)实验效果

    1、可以看到CPU如预期那样每3s(1条指令3个时钟周期),灯变换一次(执行一条指令)

    2、灯按照预先设定的数据那样点亮。

    (4)调试过程

        本来暑假做实验时,用书上的程序编译后是能运行的。但是,春节后对学习过程进行整理过程中,发现书上的例程在quartus9.1版本编译后不能运行。经检测,问题出在节拍控制上(t1、t2、t3)。需要修改instruction_fetch文件中相应的程序才能成功运行。

    4、实验结论

    (1)CPU就是用数字电路搭建起来的

    (2)CPU的基本结构是很简单的

    参考:《开放式实验CPU设计》

  • 相关阅读:
    C++学习 之 程序的组成部分(部分知识笔记)
    debian下重装mysql
    CGI 环境变量
    boost的libboost_system问题
    debian下使用shell脚本时出现了 declare:not found 解决方法
    编译的时候出现"/usr/bin/ld: cannot find -lz
    glibc升级,解决glib版本过低的问题
    ubuntu彩色图形界面
    (转)http://blog.chinaunix.net/uid-8363656-id-2031644.html CGI 编写
    linux安装JSONCPP
  • 原文地址:https://www.cnblogs.com/amanlikethis/p/3519612.html
Copyright © 2020-2023  润新知