原创 【博客大赛】RISC CPU设计之状态控制器

2012-5-4 10:09 1532 11 11 分类: FPGA/CPLD

状态控制器由两部分组成:1.状态机(machine)。2.状态控制器(machinectl)。

状态控制器接收复位信号,当rst有效时,通过信号ena使其为0,输入到状态机中停止状态机的工作。verilog程序如下:

module machinectl(
    input fetch,
    input rst,
    output reg ena
    );

 always @(posedge fetch or posedge rst)
  begin
   if(rst)
    ena <= 0;
   else
    ena <= 1;
  end

endmodule

 

状态机是cpu的控制核心,用于产生一系列的控制信号、启动或停止某些部件。cpu何时进行读指令读写io口、ram等,都由状态机来控制。

指令周期由8个时钟组成。

1.第0个时钟,cpu状态控制器的输出rd和load_ir为高电平,其余低电平。指令寄存器寄存rom送来的高8位指令代码。

2.第1个时钟,inc_pc从0变为1,故pc加1,rd和load_ir高电平,rom送来低8位指令。

3.第2个时钟,空操作。

4.第3个时钟,pc加1,指向下一条指令。若操作符为hlt,则输出信号hlt为高。

5.第4个时钟,若操作符为and、add、xor或lda,读相应地址的数据;若为jmp,将目的地址送给程序计数器;若为sto,输出累加器数据。

6.第5个时钟,若操作符为and、add或xor,算术运算器进行相应的运算;若为lda,就把数据通过算术运算器送给累加器;若为skz,先判断累加器的值是否为0,若为0,pc加1,否则不变;若为jmp,锁存目的地址;若为sto,将数据写入地址处。

7.第6个时钟,空操作。

8.第7个时钟,若操作符为skz且累加器值为0,pc加1,跳过一条指令,否则pc不变。

状态机verilog程序如下:

module machine(
    input clk,
    input zero,
    input ena,
    input [2:0] opcode,
    input int_flag,
    output reg inc_pc,
    output reg load_acc,
    output reg load_pc,
    output reg rd,
    output reg wr,
    output reg load_ir,
    output reg halt,
    output reg datactl_ena
    );
 reg[2:0]  state;
 parameter   HLT  = 3'b000,
     SKZ  = 3'b001,
     ADD  = 3'b010,
     ANDD = 3'b011,
     XORR = 3'b100,
     LDA  = 3'b101,
     STO  = 3'b110,
     JMP  = 3'b111;
     
 always @(negedge clk)
  begin
   if(!ena)
    begin
     state <= HLT;
     {inc_pc,load_acc,load_pc,rd} <= 4'b0000;
     {wr,load_ir,datactl_ena,halt} <= 4'b0000;
    end
   else
    ctl_cycle;
  end
  
 task ctl_cycle;
  begin
   casex(state)
   3'b000: begin    //load high 8bits instruction
        {inc_pc,load_acc,load_pc,rd} <= 4'b0001;
        {wr,load_ir,datactl_ena,halt} <= 4'b0100;
         state <= 3'b001;
         end
   3'b001: begin     //pc increased by one then load low 8bits instruction
        {inc_pc,load_acc,load_pc,rd} <= 4'b1001;
        {wr,load_ir,datactl_ena,halt} <= 4'b0100;
        state <= 3'b010;
        end
   3'b010: begin    //idle
        {inc_pc,load_acc,load_pc,rd} <= 4'b0000;
        {wr,load_ir,datactl_ena,halt} <= 4'b0000;   
      state <= 3'b011;
       end   
   3'b011: begin  //next instruction address setup 分析指令
      if(opcode == HLT)
        begin
           {inc_pc,load_acc,load_pc,rd} <= 4'b1000;
           {wr,load_ir,datactl_ena,halt} <= 4'b0001;
        end
      else  begin
           {inc_pc,load_acc,load_pc,rd} <= 4'b1000;
           {wr,load_ir,datactl_ena,halt} <= 4'b0000;
       end
      state <= 3'b100;
       end 
   3'b100: begin   //fetch oprand
           if(opcode == JMP)
       begin
        {inc_pc,load_acc,load_pc,rd} <= 4'b0010;
            {wr,load_ir,datactl_ena,halt} <= 4'b0000;
       end
       else 
       if(opcode==ADD || opcode==ANDD || opcode==XORR || opcode==LDA)
         begin
          {inc_pc,load_acc,load_pc,rd} <= 4'b0001;
              {wr,load_ir,datactl_ena,halt} <= 4'b0000;
         end
       else
       if(opcode == STO)
         begin
          {inc_pc,load_acc,load_pc,rd} <= 4'b0000;
              {wr,load_ir,datactl_ena,halt} <= 4'b0010;
         end
       else 
           begin
          {inc_pc,load_acc,load_pc,rd} <= 4'b0000;
              {wr,load_ir,datactl_ena,halt} <= 4'b0000;
         end
      state <= 3'b101;
     end   
   3'b101: begin    //operation
      if(opcode==ADD || opcode==ANDD || opcode==XORR || opcode==LDA)
       begin
           {inc_pc,load_acc,load_pc,rd} <= 4'b0101;
             {wr,load_ir,datactl_ena,halt} <= 4'b0000;
       end
          else
       if(opcode==SKZ && zero==1)
        begin
          {inc_pc,load_acc,load_pc,rd} <= 4'b1000;
                {wr,load_ir,datactl_ena,halt} <= 4'b0000;
        end
          else
        if(opcode == JMP)
         begin
           {inc_pc,load_acc,load_pc,rd} <= 4'b1010;
                   {wr,load_ir,datactl_ena,halt} <= 4'b0000;
         end
         else
         if(opcode == STO)
          begin
            {inc_pc,load_acc,load_pc,rd} <= 4'b0000;
                      {wr,load_ir,datactl_ena,halt} <= 4'b1010;
          end
          else
           begin
             {inc_pc,load_acc,load_pc,rd} <= 4'b0000;
                         {wr,load_ir,datactl_ena,halt} <= 4'b0000;
           end
      state <= 3'b110; 
      end  
   3'b110: begin    //idle
      if(opcode == STO)
       begin
        {inc_pc,load_acc,load_pc,rd} <= 4'b0000;
              {wr,load_ir,datactl_ena,halt} <= 4'b0010;
       end
      else
       if(opcode==ADD || opcode==ANDD || opcode==XORR || opcode==LDA)
        begin
          {inc_pc,load_acc,load_pc,rd} <= 4'b0001;
                {wr,load_ir,datactl_ena,halt} <= 4'b0000;
        end
       else
        begin
         {inc_pc,load_acc,load_pc,rd} <= 4'b0000;
                 {wr,load_ir,datactl_ena,halt} <= 4'b0000;
        end
      state <= 3'b111;
     end  
   3'b111: begin     //
      if(opcode==SKZ && zero==1)
       begin
          {inc_pc,load_acc,load_pc,rd} <= 4'b1000;
              {wr,load_ir,datactl_ena,halt} <= 4'b0000;
       end
      else
       begin
           {inc_pc,load_acc,load_pc,rd} <= 4'b0000;
              {wr,load_ir,datactl_ena,halt} <= 4'b0000;
       end
      state <= 3'b000;
      end
   default: begin
       {inc_pc,load_acc,load_pc,rd} <= 4'b0000;
         {wr,load_ir,datactl_ena,halt} <= 4'b0000;
       state <= 3'b000;
      end
   endcase
   end
 endtask
 
endmodule
 

整体模块图如下:

ctl.jpg
//参考 夏宇闻·数字系统设计
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
11
关闭 站长推荐上一条 /3 下一条