一、概述

串行CPU工作流程

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

我们究竟想要CPU干什么?

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

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

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

二、各组成模块

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

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

 --实验6.——实验CPU:通用寄存器组
 library IEEE;
 use IEEE.STD_LOGIC_1164.ALL;

 entity regfile is
 Port (  DR:          );
         SR:          );
         reset:      in std_logic;
         DRWr:       in std_logic;
         clk:         in std_logic;
         d_input:      );
         DR_data:     );
         SR_data:       )
       );
 end regfile;

 architecture struct of regfile is
 -- components
 --  bit Register for register file
 component reg
 port    (
         clr:     in    std_logic;
         D:          );
         clock:     in    std_logic;
         write:  in    std_logic;
         sel:     in    std_logic;
         Q:          )
         );
 end component;

 --   Decoder
 component  decoder_2_to_4
     port(
         sel:      );
         sel00:     out std_logic;
         sel01:     out std_logic;
         sel02:     out std_logic;
         sel03:     out std_logic
         );
 end component;

 --   line multiplexer
 component mux_4_to_1
 port (
     input0,
     input1,
     input2,
     input3:   );
     sel:      );
     out_put:  ));
 end component;

 signal reg00, reg01, reg02, reg03
             : );

 signal sel00 ,sel01 ,sel02 ,sel03
             : std_logic;

 begin
 Areg00: reg port map(
         clr            =>  reset,
         D            =>    d_input ,
         clock        =>    clk ,
         write        =>    DRWr ,
         sel            =>    sel00 ,
         Q            =>  reg00
         );

 Areg01: reg port map(
         clr            =>  reset,
         D            =>    d_input ,
         clock        =>    clk ,
         write        =>    DRWr ,
         sel            =>    sel01 ,
         Q            =>  reg01
         );

 Areg02: reg port map(
         clr            =>  reset,
         D            =>  d_input ,
         clock        =>    clk ,
         write        =>    DRWr ,
         sel            =>    sel02 ,
         Q            =>  reg02
         );

 Areg03: reg port map(
         clr            =>  reset,
         D            =>    d_input ,
         clock        =>    clk ,
         write        =>    DRWr ,
         sel            =>    sel03 ,
         Q            =>  reg03
         );

 -- decoder
 des_decoder: decoder_2_to_4 port map
         (
         sel     => DR,
         sel00     => sel00 ,
         sel01     => sel01 ,
         sel02     => sel02 ,
         sel03     => sel03
         );

 mux1: mux_4_to_1 PORT MAP(
     Input0 => reg00 ,
     Input1 => reg01 ,
     Input2 => reg02 ,
     Input3 => reg03 ,
     sel => DR ,
     out_put => DR_data
     );

 mux2: mux_4_to_1 PORT MAP(
     input0     => reg00 ,
     input1     => reg01 ,
     input2     => reg02 ,
     input3     => reg03 ,
     sel     => SR ,
     out_put => SR_data
     );

 end struct;

regfile

如上图所示:

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

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

2、取指部分 (instru_fetch)

 library ieee, my_lib;
 use ieee.std_logic_1164.all;
 use ieee.std_logic_arith.all;
 use ieee.std_logic_unsigned.all;
 use my_lib.exp_cpu_components.all;

 entity instru_fetch  is
     port(reset,clk:     in std_logic;
         data_read:      ); --存储器读出的数
         lj_instruct: in std_logic; --长转移指令
         DW_intruct:     in std_logic;
         c_z_j_flag:  in std_logic; --为1时进行条件转移
         sjmp_addr:      ); --条件转移指令的转移地址
         t1,t2,t3:      buffer std_logic;
         pc:              );
         pc_inc:          );
         IR:              )
         );
 end instru_fetch;

 architecture behav of instru_fetch is
 signal start:    std_logic;

 begin
 IR_poc: process(reset,t2)
 begin
     ' then
         IR <= x";  --nop指令
     elsif t2' then
         IR <= data_read;
     end if;
 end process;

 process(reset,clk)
 begin
     ' then
         start <= ';
     else
         ' then
             start <= ';
         end if;
     end if;
 end process;

 process(reset,clk)
 begin
     ' then
         t1 <= ';
         t2 <= ';
         t3 <= ';
     elsif clk' then
         t1 <= start or t3;
         t2 <= t1;
         t3 <= t2;
     end if;
 end process;

 pc_inc <= pc + ';        --为取双字指令的第2个字或者计算相对转移地址做准备
 PC_proc:    process(reset,t3)
 begin
    ' then
         pc <= x";
     elsif t3' then
         ' then
             pc <= data_read;
         elsif c_z_j_flag =' then
             pc <= sjmp_addr;
         elsif DW_intruct = ' then
             pc <= pc + ";
         else
             pc <= pc_inc;
         end if;
     end if;
 end process;

 end behav;

instru_fetch

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

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

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

3、指令译码部分 (decoder_unit)

 library ieee, my_lib;
 use ieee.std_logic_1164.all;
 use ieee.std_logic_arith.all;
 use ieee.std_logic_unsigned.all;
 use my_lib.exp_cpu_components.all;

 entity decoder_unit is
      );
               SR:           );
             DR:           );
             op_code:      );
               zj_instruct: out std_logic;
               cj_instruct: out std_logic;
               lj_instruct: out std_logic;
               DRWr:          buffer std_logic;  --为1时写DR寄存器
               Mem_Write:   out std_logic;
               DW_intruct:  buffer std_logic;
             change_z:    out std_logic;
             change_c:    out std_logic;
             sel_memdata: out std_logic;  --为1时存储器的读出数据作为写入DR的数据
               r_sjmp_addr:   ) --相对转移地址
             );
 end decoder_unit;

 architecture behav of decoder_unit is

 begin

 SR <= IR( );
 DR <= IR( );
 sel_memdata <= IR() ) ));
 change_z <= ) );
 change_c <= ) );

 DRWr_proc: process(IR)
 begin
     ) = ' then
         ) =' then
             DRWr <= ';
         else
             DRWr <= ';
         end if;
     elsif IR() = ) = ' then
         DRWr <= ';
     else
         DRWr <= ';
     end if;
 end process;

 sj_addr_proc:    process(IR)  --条件转移指令的相对转移地址从8位扩展到16位
 begin
     ) =' then
         r_sjmp_addr <=  );
     else
         r_sjmp_addr <=  );
     end if;
 end process;

 M_instruct:process(IR)
 begin
      ) is
         " => --jmp addr;mvDR  dr,data
             Mem_Write <= ';
             DW_intruct <= ';
         " =>  -- str dr,sr
             Mem_Write <= ';
             DW_intruct <= ';
         when others =>
             Mem_Write <= ';
             DW_intruct <= ';
     end case;
 end process;

 ALUOP_CODE_PROC:    PROCESS(IR)
 begin
        ) = ' then
         op_code <= IR( );
     else
         op_code <= ";
     end if;
 end process;

 Jinstruct_PROC:    process(IR)
 begin
         ) is
         " => --jmp adr
             zj_instruct <= ';
             cj_instruct <= ';
             lj_instruct <= ';
         " => --jnc addr
             zj_instruct <= ';
             cj_instruct <= ';
             lj_instruct <= ';
         " => --jnz addr
             zj_instruct <= ';
             cj_instruct <= ';
             lj_instruct <= ';
         when others =>
             zj_instruct <= ';
             cj_instruct <= ';
             lj_instruct <= ';
     end case;
 end process;

 end behav;
         

decoder_unit

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

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

4、执行部分 (exe_unit)

 library ieee, my_lib;
 use ieee.std_logic_1164.all;
 use ieee.std_logic_arith.all;
 use ieee.std_logic_unsigned.all;
 use my_lib.exp_cpu_components.all;

 entity exe_unit is
     port(
           t1: in std_logic;
         op_code:     );
         zj_instruct: in std_logic;
           cj_instruct: in std_logic;
         pc:  );
         pc_inc:     );
         c_in: in std_logic;  --以前指令产生的进位C
         z_in: in std_logic;  --以前指令产生的Z
         Mem_Write: in std_logic;  --为1时,写存储器
         c_tmp:    out std_logic;
         z_tmp:    out std_logic;
         c_z_j_flag: out std_logic; --为1时进行条件转移
         r_sjmp_addr:     ); --相对转移地址
         DW_intruct: in std_logic;
         sjmp_addr:     ); --条件转移指令的转移地址
         SR_data:  );
         DR_data:  );
         Mem_Addr:  );
         result:  )  --运算结果
         );

 end exe_unit;

 architecture behav of exe_unit is
  );
  );

 begin
 c_z_j_flag <= ( (not c_in) and cj_instruct) or ((not z_in) and zj_instruct);
 A <= DR_data;
 B <= SR_data;
 sjmp_addr <= pc_inc + r_sjmp_addr;    

 Mem_Addr_proc: process(t1,SR_DATA,pc,DW_intruct)
 begin
     ' then
         Mem_Addr <= pc;
     else
         ' then
             Mem_Addr <= pc_inc;
         elsif Mem_Write = ' then
             Mem_Addr <= DR_data;
         else
             Mem_Addr <= SR_data;
         end if;
     end if;
 end process;

 alu_proc:process(op_code,A,B)
 begin
     case op_code is
         " =>
             result_t <= (' & B);
         " =>
             result_t <= (';
          " =>
             result_t <= (' & B);
         " =>
             result_t <= (';
         " =>
             result_t <= (' & B);
         " =>
             result_t <= (' & B);
         " =>
             result_t <= ' & A);
         " =>
             result_t <=  (' & B);
     end case;
 end process;
 result <= result_t( );
 c_tmp <= result_t();
 z_tmp <= ()) )) and
         ()) )) and
         ()) )) and
         ()) )) and
         ()) )) and
         ()) )) and
         ()) )) and
         ()) ));

 end behav;

exe_unit

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

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

5、存储器部分 (memory_unit)

 library IEEE, my_lib;
 use IEEE.std_logic_1164.all;
 use my_lib.exp_cpu_components.all;

 entity memory_unit is
     port(
         reset:    in std_logic;
         clk,t3:    in std_logic;
         Mem_addr:     );
         Mem_Write:    in std_logic;
         sel_memdata: in std_logic;  --为1时存储器的读出数据作为写入DR的数据
         SR_data:  ); --写存储器的数据
         result:  );  --运算结果
         rw: out std_logic;
         ob:  );
         ar:  );
         data_read:  ); --从存储器读出的指令或者数据
         DR_data_out:   ) --写入DR的数据
         );
 end memory_unit;

 architecture behav of memory_unit is
 begin

 ar <= Mem_addr;
 R_W_Memory_proc: process(reset,ob,SR_DATA,clk,t3,Mem_Write) --读写存储器处理
 begin
     ' then
         rw <= ';
         ob <= "ZZZZZZZZZZZZZZZZ";  --将存储器数据总线置为高阻,读存储器
     else
         ' then
             ob <= SR_DATA;  --写存储器
             rw <= clk;
         else
             ob <= "ZZZZZZZZZZZZZZZZ";  --将存储器数据总线置为高阻,读存储器
             rw <= ';
             data_read <= ob;
         end if;
     end if;
 end process;

 sele_DR_proc:  process(sel_memdata,data_read,result)
 begin
     ' then
         DR_data_out <= data_read; --存储器数据作为写DR的数据
     else
         DR_data_out <= result;  --运算结果作为写DR的数据
     end if;
 end process;

 end behav;

memory_unit

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

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

6、程序包(exp_cpu_components)

 library ieee;
 use ieee.std_logic_1164.all;

 package exp_cpu_components is
     component    reg port
        (reset:        in     std_logic;
         d_input:      );
         clk:        in    std_logic;
         write:        in    std_logic;
         sel:        in    std_logic;
         q_output:      )
         );
     end component;

     component    mux_4_to_1 port
         (
         input0,
         input1,
         input2,
         input3:       );
         sel:          );
         out_put:      )
         );
     end component;

     component    decoder_2_to_4    port
         (
          sel:     );
          sel00:  out std_logic;
          sel01:  out std_logic;
          sel02:  out std_logic;
          sel03:  out std_logic
          );
     end component;

     component regfile Port
         (DR:          );
         SR:          );
         reset:         in std_logic;
         write:         in std_logic;
         clk:         in std_logic;
         d_input:      );
         change_z:     in std_logic;
         change_c:     in std_logic;
         c_in:       in std_logic;
         z_in:       in std_logic;
         R0,R1,R2,R3:  );
         output_DR:    );
         output_SR:    );
         c_out:         out std_logic;
         z_out:         out std_logic
         );
     end component;

     component instru_fetch port
         (
         reset,clk:     in std_logic;
         data_read:      ); --存储器读出的数
         lj_instruct: in std_logic; --长转移指令
         DW_intruct:     in std_logic; --双字指令
         c_z_j_flag:  in std_logic; --为1时进行条件转移
         sjmp_addr:      ); --条件转移指令的转移地址
         t1,t2,t3:      buffer std_logic;
         pc:              );
         pc_inc:          );
         IR:              )
         );
     end component;

     component decoder_unit port
          (IR:               );
          SR:            );
          DR:            );
          op_code:       );
          zj_instruct:  out std_logic;
          cj_instruct:  out std_logic;
          lj_instruct:  out std_logic;
          DRWr:            buffer std_logic;  --为1时写DR寄存器
          Mem_Write:    out std_logic;
          DW_intruct:   buffer std_logic;
          change_z:     out std_logic;
          change_c:     out std_logic;
          sel_memdata:  out std_logic;  --为1时存储器的读出数据作为写入DR的数据
          r_sjmp_addr:   ) --相对转移地址
          );
     end component;

     component exe_unit port
         (t1:          in std_logic;
          op_code:      );
          zj_instruct: in std_logic;
            cj_instruct: in std_logic;
          pc:              );
          pc_inc:          );
          c_in:          in std_logic;  --以前指令产生的进位C
          z_in:          in std_logic;  --以前指令产生的Z
          Mem_Write:  in std_logic;  --为1时,写存储器
          c_tmp:         out std_logic;
          z_tmp:         out std_logic;
          c_z_j_flag:  out std_logic; --为1时进行条件转移
          r_sjmp_addr:  ); --相对转移地址
          DW_intruct : in std_logic;
          sjmp_addr:      ); --条件转移指令的转移地址
          SR_data:      );
          DR_data:      );
          Mem_Addr:     );
          result:       )  --运算结果
          );
     end component;

     component memory_unit port
         (reset:    in std_logic;
          clk,t3:    in std_logic;
          Mem_addr:     );
          Mem_Write:    in std_logic;
          sel_memdata: in std_logic;  --为1时存储器的读出数据作为写入DR的数据
          SR_data:  ); --写存储器的数据
          result:  ); --运算结果
          rw: out std_logic;
          ob:  );
          ar: );
          data_read:  ); --从存储器读出的指令或者数据
          DR_data_out:   ) --写入DR的数据
          );
     end component;
 end exp_cpu_components;

exp_cpu_components

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

7、顶层设计实体 (exp_cpu)

--实验6.——实验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:      ); --选择寄存器
    reg_content:  ); --寄存器输出
    c_flag:         out std_logic;
    z_flag:         out std_logic;
    WE:            out std_logic;                    --//读写内存控制信号
    AR:   );     --//读写内存地址
    OB:   )      --//外部总线
    );
end exp_cpu;

architecture behav of exp_cpu is
    --instru_fetch out
signal t1,t2,t3: std_logic;
 );
    --decoder_unit out
 );
 );
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;
 );
    --exe_unit out
signal c_tmp,z_tmp,c_z_j_flag: std_logic;
 );
    --memory out
 );
    --regfile out
 );
 );
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
        " =>
            reg_content <= R0;
        " =>
            reg_content <= R1;
        " =>
            reg_content <= R2;
        " =>
            reg_content <= R3;
        " =>
            reg_content <= " & t1;
        " =>
            reg_content <= pc;
        " =>
            reg_content <= IR;
        when others =>
            reg_content <= x";
    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设计》

串行CPU设计的更多相关文章

  1. Verilog学习笔记简单功能实现(七)...............接口设计(并行输入串行输出)

    利用状态机实现比较复杂的接口设计: 这是一个将并行数据转换为串行输出的变换器,利用双向总线输出.这是由EEPROM读写器的缩减得到的,首先对I2C总线特征介绍: I2C总线(inter integra ...

  2. 大叔也说并行和串行`性能提升N倍(N由操作系统位数和cpu核数决定)

    返回目录 并行是.net4.5主打的技术,同时被封装到了System.Threading.Tasks命名空间下,对外提供了静态类Parallel,我们可以直接使用它的静态方法,它可以并行一个委托数组, ...

  3. 自制单片机之六……串行I2C总线E2PROM AT24CXXX的应用

    这一篇介绍I2C存储器的使用.主要是介绍AT24CXX系列器件,它分为两类,主要是通过被存储容量地址来分的,一类是AT24C02-AT24C16,它的存储容量从256字节到2048字节.另一类是AT2 ...

  4. 原创:应用串行NOR闪存提升内存处理能力

    在嵌入式系统中,NOR闪存一直以来仍然是较受青睐的非易失性内存,NOR器件的低延时特性可以接受代码执行和数据存储在一个单一的产品.虽然NAND记忆体已成为许多高密度应用的首选解决方案,但NOR仍然是低 ...

  5. 【Java EE 学习 72 下】【数据采集系统第四天】【移动/复制页分析】【使用串行化技术实现深度复制】

    一.移动.复制页的逻辑实现 移动.复制页的功能是在设计调查页面的时候需要实现的功能.规则是如果在同一个调查中的话就是移动,如果是在不同调查中的就是复制. 无论是移动还是复制,都需要注意一个问题,那就是 ...

  6. JVM_垃圾回收串行、并行、并发算法(总结)

    一.串行 JDK1.5前的默认算法 缺点是只有一个线程,执行垃圾回收时程序停止的时间比较长 语法 -XX:+UseSerialGC 新生代.老年代使用串行回收 新生代复制算法 老年代标记-压缩 示例图 ...

  7. ios--进程/多线程/同步任务/异步任务/串行队列/并行队列(对比分析)

    现在先说两个基本的概念,啥是进程,啥是线程,啥又是多线程;先把这两个总是给弄清再讲下面的 进程:正在进行的程序,我们就叫它进程. 线程:线程就是进程中的一个独立的执行路径.这句话怎么理解呢! 一个程序 ...

  8. 串行通讯之UARTLoopback

    目录 第1章串行通讯之UARTLoopback    2 1 USB转串口    2 2 USB Accessory    2 3 连入手机    3 4 代码改进    4 5 打开串口    4 ...

  9. 串行通讯之Qt

    目录 第1章 Qt 串行通讯    1 1.1 配置.pro文件    1 1.2 查询串口信息    1 1.3 配置.打开串口    3 1.4 setRequestToSend在Windows上 ...

随机推荐

  1. Windbg Extension NetExt 使用指南 【3】 ---- 挖掘你想要的数据 Managed Heap

    摘要 : NetExt中有两个比较常用的命令可以用来分析heap上面的对象. 一个是!wheap, 另外一个是!windex. !wheap 这个命令可以用于打印出heap structure信息. ...

  2. 在CentOS 6.7中安装 latex2html, 实现 latex 自动转化为 word

    由于latex文档生成的pdf不便于提供审阅和修改,亟需一个软件实现从latex向word文档的自动转换( 如何把Latex自动转为Word 介绍了由latex2html 可实现这个功能,这也是初衷) ...

  3. gcc 使用 stdio.h

    9876543210z@z:~/funnyC++$ cat main.cpp #include <stdio.h> int main() { ; ) { printf("%d&q ...

  4. 关于netstat

    netstat 命令是 linux 下一个非常有用的命令,顾名思义,其作用是查询当前的网络状态. 以最常用的查询 TCP 连接状态为例 netstat -an|awk '/tcp/ {print $6 ...

  5. python 处理中文文件时的编码问题,尤其是utf-8和gbk

    python代码文件的编码 py文件默认是ASCII编码,中文在显示时会做一个ASCII到系统默认编码的转换,这时就会出错:SyntaxError: Non-ASCII character.需要在代码 ...

  6. ural-1099-Work Scheduling(裸带花树)

    题意: 有N个人,有限对的人可以在一起工作,问最多能有多少对. 分析: 任意图的最大匹配 // File MAXName: 1099.cpp // Author: Zlbing // Created ...

  7. C++的常量折叠(一)

    前言 前几天女票问了我一个阿里的面试题,是有关C++语言的const常量的,其实她一提出来我就知道考察的点了:肯定是const常量的内存不是分配在read-only的存储区的,const常量的内存分配 ...

  8. 算法起步之Kruskal算法

    原文:算法起步之Kruskal算法 说完并查集我们接着再来看这个算法,趁热打铁嘛.什么是最小生成树呢,很形象的一个形容就是铺自来水管道,一个村庄有很多的农舍,其实这个村庄我们可以看成一个图,而农舍就是 ...

  9. JS中的事件大全

    一般事件  onClick            鼠标点击事件,多用在某个对象控制的范围内的鼠标点击 onDblClick        鼠标双击事件 onMouseDown        鼠标上的按 ...

  10. [Angular Tutorial] 12 -Event Handlers

    在这一步中,您将会在电话细节页面添加一个可点击的电话图片转换器. ·电话细节页面展示了当前电话的一张大图片和几张相对较小的略图.如果我们能仅仅通过点击略图就能把大图片换成略图就好了.让我们看看用Ang ...