数模电知识 经典电路欣赏 单片机 嵌入式系统 接口电路 仿真与制板EDA DSP MEMS 通信技术 现代电子 电子维修
返回首页
当前位置: QQ电子网 > 电子技术 > EDA >

用Verilog语言写的简单微处理器程序(QuartusII下可编译)

时间:2010-04-18 20:09来源:未知 作者:admin 点击:

//最简单计算机核设计 2010-4-16(可下载到开发板验证)
//可以用QuartusII编译下载 
//仅限学习;
//参考书:advanced Digital Design with the Verilog HDL 作者:Michael D.ciletti

//基本输入时钟CLK

//仅限于学习

//复位控制:rst低电位有效

 

//***************指令集****************

//指令     操作码      源寄存器   目的寄存器      操作

// NOP   0000       xxxxx      xxxxxx       空操作

//ADD    0001      src             dest            dest<=src+dest

//SUB    0010        src             dest          dest<=dest-src

//AND    0011      src             dest           dest<=src&&dest

//NOT   0100      src             dest           dest<=~src

//RD      0101     xxxxx        dest          dest<= memory[Add_R]

//WR     0110     src              xxxxx      memory[Add_R]<=src

//BR     0111       xxxxx         xxxxx     PC<=memory[Add_R]

//BRZ    1000     xxxxx         xxxxx    PC<=memory[Add_R]

//HALT  1111     xxxxx         xxxxx    挂起至RST

//**************************************

 


 

状态转移图

 


 

 RTL级验证 Processing_Unit Control_Unit Memory_Unit组成


Processing_Unit   RTL级验证

 


 

Control_Unit  RTL级验证
 

 



//*******************代码开始**********************************

module RISC_CPU (clk,rst);//dingcengmokuai

parameter word_size =8;
parameter Sel1_size =3;
parameter Sel2_size =2;
wire [Sel1_size-1:0] Sel_bus_1_Mux;
wire [Sel2_size-1:0] Sel_bus_2_Mux;
input clk,rst;

wire zero;
wire [word_size-1:0] instruction,address,Bus_1,mem_word;

wire Load_R0,Load_R1,Load_R2,Load_R3,Load_PC,Inc_PC,Load_IR;
wire Load_Add_R,Load_Reg_Y,Load_Reg_Z;
wire write;

Processing_Unit M0_Processor(instruction,zero,address,Bus_1,mem_word,Load_R0,
      Load_R1,Load_R2,Load_R3,Load_PC,Inc_PC,Sel_bus_1_Mux,Load_IR,
      Load_Add_R,Load_Reg_Y,Load_Reg_Z,Sel_bus_2_Mux,clk,rst);
      
Control_Unit M1_Controller(Load_R0,Load_R1,Load_R2,Load_R3,Load_PC,Inc_PC,Sel_bus_1_Mux,
       Sel_bus_2_Mux,Load_IR,Load_Add_R,Load_Reg_Y,Load_Reg_Z,write,
       instruction,zero,clk,rst);


Memory_Unit M2_Sram(.data_out(mem_word),.data_in(Bus_1),.address(address),.clk(clk),.write(write));

endmodule


module Processing_Unit (instruction,Zflag,address,Bus_1,mem_word,Load_R0,
      Load_R1,Load_R2,Load_R3,Load_PC,Inc_PC,Sel_bus_1_Mux,Load_IR,
      Load_Add_R,Load_Reg_Y,Load_Reg_Z,Sel_bus_2_Mux,clk,rst);


parameter word_size =8;
parameter Sel1_size =3;
parameter Sel2_size =2;
parameter op_size =4;

output[word_size-1:0] instruction,address,Bus_1;
output Zflag;
input[word_size-1:0] mem_word;
input  Load_R0,Load_R1,Load_R2,Load_R3,Load_PC,Inc_PC;

input [Sel1_size-1:0] Sel_bus_1_Mux;
input [Sel2_size-1:0] Sel_bus_2_Mux;

input Load_IR,Load_Add_R,Load_Reg_Y,Load_Reg_Z;
input clk,rst;

wire  Load_R0,Load_R1,Load_R2,Load_R3;
wire [word_size-1:0] Bus_2;
wire [word_size-1:0] R0_out,R1_out,R2_out,R3_out;
wire [word_size-1:0] PC_count,Y_value,alu_out;
wire alu_zero_flag;
wire [op_size-1:0] opcode=instruction[word_size-1:word_size-op_size];


Register_Unit R0(R0_out,Bus2,Load_R0,clk,rst);
Register_Unit R1(R1_out,Bus2,Load_R1,clk,rst);
Register_Unit R2(R2_out,Bus2,Load_R2,clk,rst);
Register_Unit R3(R3_out,Bus2,Load_R3,clk,rst);
Register_Unit Reg_Y(Y_value,Bus2,Load_Reg_Y,clk,rst);
D_flop    Reg_Z(Zflag,alu_zero,Load_Reg_Z,clk,rst);
Adress_Register Add_R(address,Bus_2,Load_Add_R,clk,rst);
Instruction_Register IR(instruction,Bus_2,Load_IR,clk,rst);
Program_Counter  PC(PC_count,Bus_2,Load_PC,Inc_PC,clk,rst);
Multiplexer_5ch Mux_1(Bus_1,R0_out,R1_out,R2_out,R3_out,PC_count,Sel_bus_1_Mux);
Multiplexer_3ch Mux_2(Bus_2,alu_out,Bus_1,mem_word,Sel_bus_2_Mux);

Alu_RISC ALU(alu_zero_flag,alu_out,Y_value,Bus_1,opcode);

endmodule


module Register_Unit(data_out,data_in,load,clk,rst);
parameter word_size =8;
output [word_size-1:0] data_out;
input [word_size-1:0] data_in;
input load;
input clk,rst;
reg [word_size-1:0] data_out;

always @(posedge clk or negedge rst)
begin
 if(rst==0) data_out<=0;
 else if(load) data_out<=data_in;
 
end
endmodule

module D_flop(data_out,data_in,load,clk,rst);

output  data_out;
input  data_in;
input load;
input clk,rst;
reg  data_out;

always @(posedge clk or negedge rst)
begin
 if(rst==0) data_out<=0;
 else if(load==1) data_out<=data_in;
 
end
endmodule

module Adress_Register(data_out,data_in,load,clk,rst);
parameter word_size =8;
output [word_size-1:0] data_out;
input [word_size-1:0] data_in;
input load;
input clk,rst;
reg [word_size-1:0] data_out;

always @(posedge clk or negedge rst)
begin
 if(rst==0) data_out<=0;
 else if(load) data_out<=data_in;
 
end
endmodule

module Instruction_Register (data_out,data_in,load,clk,rst);
parameter word_size =8;
output [word_size-1:0] data_out;
input [word_size-1:0] data_in;
input load;
input clk,rst;
reg [word_size-1:0] data_out;

always @(posedge clk or negedge rst)
begin
 if(rst==0) data_out<=0;
 else if(load) data_out<=data_in;
 
end
endmodule


module Program_Counter (count,data_in,Load_PC,Inc_PC,clk,rst);
parameter word_size =8;
output [word_size-1:0] count;
input [word_size-1:0] data_in;
input Load_PC,Inc_PC;
input clk,rst;
reg [word_size-1:0] count;
always @(posedge clk or negedge rst)
begin
if(rst==0) count<=0;
else if(Load_PC==1)count<=data_in;
 else if (Inc_PC)
  count<=count+1;


end
endmodule


module Multiplexer_5ch (mux_out,data_a,data_b,data_c,data_d,data_e,sel);
parameter word_size =8;
output [word_size-1:0] mux_out;
input [word_size-1:0] data_a,data_b,data_c,data_d,data_e;
input [2:0]sel;

assign mux_out=(sel==0) ? data_a:(sel==1)
      ?data_b:(sel==2)
      ?data_c:(sel==3)
      ?data_d:(sel==4)?
      data_e:3'bx;

endmodule


module Multiplexer_3ch (mux_out,data_a,data_b,data_c,sel);
parameter word_size =8;
output [word_size-1:0] mux_out;
input [word_size-1:0] data_a,data_b,data_c;
input [1:0]sel;

assign mux_out=(sel==0) ? data_a:(sel==1)
      ?data_b:(sel==2)
      ?data_c:3'bx;

endmodule


module Alu_RISC (alu_zero_flag,alu_out,data_1,data_2,sel);
parameter word_size =8;
parameter op_size =4;

parameter NOP =4'b0000;
parameter ADD =4'b0001;
parameter SUB =4'b0010;
parameter AND =4'b0011;
parameter NOT =4'b0100;
parameter RD =4'b0101;
parameter WR =4'b0110;
parameter BR =4'b0111;
parameter BRZ =4'b1000;
output alu_zero_flag;


output [word_size-1:0] alu_out;
input [word_size-1:0] data_1,data_2;
input [op_size-1:0] sel;
reg alu_out;

assign alu_zero_flag=~|alu_out;
always@(sel or data_1 or data_2)
case (sel)

NOP:     alu_out=0;
ADD:     alu_out=data_1+data_2;
SUB:  alu_out=data_2-data_1;
AND:     alu_out=data_1&data_2;
NOT:  alu_out=~data_2;
default : alu_out=0;

endcase
endmodule

module Control_Unit (Load_R0,Load_R1,Load_R2,Load_R3,Load_PC,Inc_PC,Sel_Bus_1_Mux,Sel_Bus_2_Mux,
      Load_IR,Load_Add_R,Load_Reg_Y,Load_Reg_Z,write,instruction,zero,clk,rst);
      
parameter word_size =8,op_size=4,state_size=4;
parameter src_size=2,dest_size=2,Sel1_Size=3,Sel2_Size=2;

parameter S_idle=0,S_fet1=1,S_fet2=2,S_dec=3;
parameter S_ex1=4,S_rd1=5,S_rd2=6;
parameter S_wr1=7,S_wr2=8,S_br1=9,S_br2=10,S_halt=11;

parameter NOP=0,ADD=1,SUB=2,AND=3,NOT=4;
parameter RD=5,WR=6,BR=7,BRZ=8;

parameter R0=0,R1=1,R2=2,R3=3;

output Load_R0,Load_R1,Load_R2,Load_R3;
output Load_PC,Inc_PC;
output [Sel1_Size-1:0] Sel_Bus_1_Mux;
output Load_IR,Load_Add_R;
output Load_Reg_Y,Load_Reg_Z;
output [Sel2_Size-1:0] Sel_Bus_2_Mux;
output write;
input  [word_size-1:0] instruction;
input zero;
input clk,rst;


reg [state_size-1:0] state,next_state;
reg Load_R0,Load_R1,Load_R2,Load_R3,Load_PC,Inc_PC;
reg Load_IR,Load_Add_R,Load_Reg_Y;
reg Sel_ALU,Sel_Bus_1,Sel_Mem;
reg Sel_R0,Sel_R1,Sel_R2,Sel_R3,Sel_PC;
reg Load_Reg_Z,write;
reg err_flag;

wire [op_size-1:0] opcode=instruction [word_size-1:word_size-op_size];
wire [src_size-1:0] src=instruction [src_size+dest_size-1:dest_size];
wire [dest_size-1:0] dest=instruction [dest_size-1:0];

assign Sel_Bus_1_Mux[Sel1_Size-1:0]=Sel_R0 ?0:Sel_R1 ? 1:Sel_R2 ? 2:Sel_R3 ? 3:Sel_PC ? 4:3'bx;
assign Sel_Bus_2_Mux[Sel2_Size-1:0]=Sel_ALU ?0:Sel_Bus_1 ? 1:Sel_Mem ? 2:2'bx;

always@(posedge clk or negedge rst)
begin
 if(rst==0) state<=S_idle;
 else  state <=next_state;
end

always@(state or opcode or src or dest or zero)
begin
Sel_R0=0;Sel_R1=0;Sel_R2=0;Sel_R3=0;Sel_PC=0;
Load_R0=0;Load_R1=0;Load_R2=0;Load_R3=0;Load_PC=0;Inc_PC=0;
Load_IR=0;Load_Add_R=0;Load_Reg_Y=0;Load_Reg_Z=0;
Inc_PC=0;
Sel_ALU=0;
Sel_Bus_1=0;
Sel_Mem=0;
write=0;
err_flag=0;
next_state=state;

case (state) S_idle:  next_state=S_fet1;
    S_fet1: begin
       next_state=S_fet2;
       Sel_PC=1;
       Sel_Bus_1=1;
       Load_Add_R=1;
      end
   S_fet2:  begin
       next_state=S_dec;
       Sel_Mem=1;
       Load_IR=1;
       Inc_PC=1;
      
      end
   S_dec :
     case (opcode)
      NOP: next_state =S_fet1;
      ADD,SUB,AND: begin
          next_state =S_ex1;
          Sel_Bus_1=1;
          Load_Reg_Y=1;
          case (src)
           R0: Sel_R0 =1;
           R1: Sel_R1 =1;
           R2: Sel_R2 =1;
           R3: Sel_R3 =1;
           default  err_flag=1;
          endcase //ADD SUB AND-src case
          end //add sub and
      NOT:begin
          next_state=S_fet1;
          Load_Reg_Z=1;
          Sel_Bus_1=1;
          Sel_ALU=1;
          case (src)
          R0: Sel_R0=1;
          R1: Sel_R1=1;
          R2: Sel_R2=1;
          R3: Sel_R3=1;
          default: err_flag=1;
        endcase //not-src case
          
        case (dest)
          R0: Load_R0=1;
          R1: Load_R1=1;
          R2: Load_R2=1;
          R3: Load_R3=1;
          default:  err_flag=1;
        endcase //not-dest case
       end //not
      RD:
         begin
       next_state =S_rd1;
       Sel_PC=1;
       Sel_Bus_1=1;
       Load_Add_R=1;
         end //RD
      WR:
       begin
       next_state =S_wr1;
       Sel_PC=1;
       Sel_Bus_1=1;
       Load_Add_R=1;
       end//WR
      BR: begin
       next_state=S_br1;
       Sel_PC=1;Sel_Bus_1=1;Load_Add_R=1;
       end //BR
      
      BRZ:
       if(zero==1)begin
       next_state=S_br1;
       Sel_PC=1;Sel_Bus_1=1;Load_Add_R=1;
       end
       else begin
       next_state=S_fet1;
       Inc_PC =1;
       end
       
       default : next_state=S_halt;
       endcase//opcode
       
   S_ex1: begin
     next_state=S_fet1;
     Load_Reg_Z=1;
     Sel_ALU=1;
     case (dest)
      R0:begin Sel_R0=1;Load_R0=1;end
      R1:begin Sel_R1=1;Load_R1=1;end
      R2:begin Sel_R2=1;Load_R2=1;end
      R3:begin Sel_R3=1;Load_R3=1;end
      default : err_flag =1;
     endcase //S_EX1--DEST--CASE
     end
   S_rd1: begin
      next_state=S_rd2;
      Sel_Mem=1;
      Load_Add_R=1;
      Inc_PC=1;
     end
   
   S_wr1: begin
      next_state=S_wr2;
      Sel_Mem=1;
      Load_Add_R=1;
      Inc_PC=1;
     end
   S_rd2: begin
     next_state=S_fet1;
     Sel_Mem=1;
     case (dest)
      R0:begin Load_R0=1;end
      R1:begin Load_R1=1;end
      R2:begin Load_R2=1;end
      R3:begin Load_R3=1;end
      default : err_flag =1;
     endcase //S_rd2--DEST--CASE
     end
   
   S_wr2: begin
     next_state=S_fet1;
     write=1;
     case (src)
      R0:begin Sel_R0=1;end
      R1:begin Sel_R1=1;end
      R2:begin Sel_R2=1;end
      R3:begin Sel_R3=1;end
      default : err_flag =1;
     endcase //S_wr2--DEST--CASE
     end
   S_br1: begin next_state=S_br2;
       Sel_Mem=1;
       Load_Add_R=1;
       end
   
   S_br2: begin next_state=S_fet1;
       Sel_Mem=1;
       Load_PC=1;
       end
      
   S_halt:
         next_state=S_halt;
   default: next_state=S_idle;
   endcase
   end
   endmodule     
      
      
module Memory_Unit (data_out,data_in,address,clk,write);

parameter word_size=8;
parameter memory_size=256;

output[word_size-1:0] data_out;
input [word_size-1:0] data_in;
input [word_size-1:0] address;
input clk,write;
reg [word_size-1:0] memory [memory_size-1:0];

assign data_out=memory[address]<=data_in;

endmodule


分享到:

本站相关资讯链接QQ电子网
找不到想要的,那就在这里Google一下!
(责任编辑:admin)
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名:密码: 验证码:点击我更换图片
推荐内容
站长推荐