zoukankan      html  css  js  c++  java
  • 单周期cpu设计代码解读

    写在前面

    欢迎转载,转载请说明出处。

    单周期cpu设计代码讲解

    概念回顾

    一、电子计算机的部件

    分为:中央处理器(cpu)、内部存储器(Memory)、输入/输出(I/O)设备,以及连接它们的总线(Bus)。下图为图示,注意色块的区分。

    二、cpu

    又包括控制器(Controller)和数据通路(Data Path)。下图为图示,注意色块区分。

    三、控制器

    分为主控(Main Control)和局控(Local Control或ALU Control)。将二进制指令输入控制器,生成控制信号,该过程称为译码。控制信号控制数据通路工作。且不同的指定对应不同的控制信号。

    下图为在控制器中译码的逻辑示意图:

    下图为在控制器中译码的物理示意图:

    讲解一下从逻辑图到物理图的转换:

    1. 首先由主控解析op指令,如果发现该指令为“000000”则表示该指令是R指令,输出中间信号R-Type为1,否则为0;如果发现该指令是其他值,则按照逻辑图,为RegDst等信号赋相应的值;
    2. 中间信号R-Type起到二路选择的作用,如图。
    3. 中间信号ALUop,在R-Type为0(选择0路)时,直接通过局控,输出成为ALUctr信号,对应上面逻辑图的最后一行后5列;在R-Type为1时,局控起作用。
    4. 局控解析R指令的func部分,输出对应指令的ALUctr信号。

    四、数据通路:

    是包括运算器、寄存器组、存储器(高速缓存)、多路选择器等等在内的元件的有结构的组合。如下图所示:

    【数据通路各部分的讲解将结合代码完成】

    Verilog代码讲解

    在代码讲解之前有必要放几张图:

    shift.v

    /*移位*/
    /*输入一个数,返回移位之后的结果*/
    /*输入d(待移的数)、sa(移动的位数)、right(移动方向)、arith(空位补全方式)*/
    /*输出sh(移位后的结果)*/
    module shift (d,sa,right,arith,sh);
    input  [31:0]  d;
    input  [4:0]     sa;
    input  right,arith;
    output [31:0] sh;
    reg  [31:0] sh;
        
    // 组合逻辑
    always  @*  begin
    	if   (!right)  begin // right为逻辑0时,左移
    		sh = d << sa;
    	end else  if   (!arith)  begin // right为逻辑1,且arith为逻辑0时,右移、0补空
    		sh =  d  >>  sa;
    	end else begin // 右移、1补空                     
    		sh =  $signed(d)  >>>  sa;
    	end
    end
    endmodule
    

    scinstmem.v

    /*从ROM(只读存储器)读数据*/
    /*输入目标数据在ROM中的地址a*/
    /*输出地址对应的数据inst*/
    module scinstmem (a,inst); 
    	input [31:0] a; 
    	output [31:0] inst; 
        wire [31:0] rom [0:31]; // 定义32个32位的存储器ROM
    
    	// 想ROM中写入一组指令,指令对应的汇编含义见行注释
     	assign  rom[5'h00] = 32'h3c010000; // (00) main: lui r1,0
    	assign  rom[5'h01] = 32'h34240050; // (04)      ori r4,r1,80
    	assign  rom[5'h02] = 32'h20050004; // (08)      addi r5,r0, 4
    	assign  rom[5'h03] = 32'h0c000018; // (0c)call: jal sum
    	assign  rom[5'h04] = 32'hac820000; // (10)      sw r2,0(r4)
    	assign	rom[5'h05] = 32'h8c890000;	//	(14)		lw	r9,	0(r4)
    	assign	rom[5'h06] = 32'h01244022;	//	(18)		sub	r8,	r9.	r4
    	assign	rom[5'h07] = 32'h20050003;	//	(lc)		addi	r5,	r0.	3
    	assign	rom[5'h08] = 32'h20a5ffff;	//	(20)	loop2:	addi	r5,	r5,	-1
    	assign	rom[5'h09] = 32'h34a8ffff;	//	(24)		ori	r8,	r5,	0xffff
    	assign	rom[5'h0A] = 32'h39085555;	//	(28)		xori	r8.	r8,	0x5555
    	assign	rom[5'h0B] = 32'h2009ffff;	//	(2c)		addi	r9,	rO,	-1
    	assign	rom[5'h0C] = 32'h312affff;	//	(30)		andi	rlO,	r9,	0xffff
    	assign	rom[5'h0D] = 32'h01493025;	//	(34)		or	r6.	rlO,	r9
    	assign	rom[5'h0E] = 32'h01494026;	//	(38)		xor	r8,	rlO,	r9
    	assign	rom[5'h0F] = 32'h01463824;	//	(3c)		and	r7,	rlO,	r6
    	assign	rom[5'h10] = 32'h10a00001;	//	(40)		beq	r5,	r0,	shift
    	assign	rom[5'h11] = 32'h08000008;	//	(44)		j	loop2	
    	assign	rom[5'h12] = 32'h2005ffff;	//	(48)	shift:	addi	r5.	r0,	-1
    	assign	rom[5'h13] = 32'h000543c0;	//	(4c)		sll	r8.	r5.	15
    	assign	rom[5'h14] = 32'h00084400;	//	(50)		sll	r8,	r8,	16
    	assign	rom[5'h15] = 32'h00084403;	//	(54)		sra	r8,	r8,	16
    	assign	rom[5'h16] = 32'h000843c2;	//	(58)		srl	r8.	r8.	15
    	assign	rom[5'h17] = 32'h08000017;	//	(5c)	finish:	j	finish	
    	assign	rom[5'h18] = 32'h00004020;	//	(60)	sum:	add	r8,	r0,	r0
    	assign	rom[5'h19] = 32'h8c890000;	//	(64)	loop:	lw	r9,	(r4)
    	assign	rom[5'h1A] = 32'h20840004;	//	(68)		addi	r4,	r4,	4
    	assign	rom[5'h1B] = 32'h01094020;	//	(6c)		add	r8,	r8,	r9
    	assign	rom[5'h1C] = 32'h20a5ffff;	//	(70)		addi	r5,	r5,	-1
    	assign	rom[5'h1D] = 32'h14a0fffb;	//	(74)		bne	rS,	r0,	loop
    	assign	rom[5'h1E] = 32'h00081000;	//	(78)		sll	r2f	r8f	0
    	assign	rom[5'h1F] = 32'h03e00008;	//	(7c)		jr	r31		
    
    	// 将地址对应的数据放入inst
    	assign inst = rom[a[6:2]];
    
    endmodule
    

    scdatamem.v

    /*将数据写入RAM中(随机存取存储器)的指定位置*/
    /*输入待写数据datain、目标地址addr;写使能信号we;时钟信号clk、inclk、outclk*/
    /*输出将被覆盖的数据dataout*/
    module scdatamem (clk,dataout,datain,addr,we,inclk,outclk);
    input	[31:0]	datain;
    input	[31:0]	addr ;
    input		clk, we, inclk, outclk;
    output	[31:0]	dataout;
    reg [31:0] ram	[0:31]; // 定义32个32位RAM
    // 把将被覆盖的数据放入dataout
    assign	dataout	=ram[addr[6:2]];
    // 时序逻辑,clk的上升沿触发
    always @ (posedge clk) begin
    	if (we) ram[addr[6:2]] = datain; // 如果写使能信号we为1,将数据写入目标地址
    end
    // 为RAM赋值,这一步不是必要的,只是欲运行的自定义程序的需要。
    integer i;
    initial begin
    	for (i = 0;i < 32;i = i + 1)
    		ram[i] = 0;
    	ram[5'h14] = 32'h000000a3;
    	ram[5'h15] = 32'h00000027;
    	ram[5'h16] = 32'h00000079;
    	ram[5'h17] = 32'h00000115;
    end
    endmodule
    

    sccu_dataflow.v

    /*基于MIPS指令集的控制器*/
    /*输入指令的op字段、func字段、z信号*/
    /*输出wreg,regrt,aluc,pcsource等等控制信号*/
    module sccu_dataflow (op,func,z,wmem,wreg,regrt,m2reg,aluc,shift,aluimm,pcsource,jal,sext);
    	input [5:0] op,func;
    	input z;
    	output wreg,regrt,jal,m2reg,shift,aluimm,sext,wmem;
    	output [3:0] aluc;
    	output [1:0] pcsource;
    	
    	// 确定内部信号r_type的值
    	wire r_type = ~|op;
    	
    	// 如果r_type为真,根据func,确定是哪一种R型指令
    	wire i_add = r_type&func[5]&~func[4]&~func[3]&~func[2]&~func[1]&~func[0];
    	wire i_sub = r_type&func[5]&~func[4]&~func[3]&~func[2]&func[1]&~func[0];
    	wire i_and = r_type&func[5]&~func[4]&~func[3]&func[2]&~func[1]&~func[0];
    	wire i_or = r_type&func[5]&~func[4]&~func[3]&func[2]&~func[1]&func[0];
    	wire i_xor = r_type&func[5]&~func[4]&~func[3]&func[2]&func[1]&~func[0];
    	wire i_sll = r_type&~func[5]&~func[4]&~func[3]&~func[2]&~func[1]&~func[0];
    	wire i_srl = r_type&~func[5]&~func[4]&~func[3]&~func[2]&func[1]&~func[0];
    	wire i_sra = r_type&~func[5]&~func[4]&~func[3]&~func[2]&func[1]&func[0];
    	wire i_jr = r_type&~func[5]&~func[4]&func[3]&~func[2]&~func[1]&~func[0];
    	// 如果r_type为假,根据op,确定是哪一种指令
    	wire i_addi = ~op[5]&~op[4]&op[3]&~op[2]&~op[1]&~op[0];
    	wire i_andi = ~op[5]&~op[4]&op[3]&op[2]&~op[1]&~op[0];
    	wire i_ori = ~op[5]&~op[4]&op[3]&op[2]&~op[1]&op[0];
    	wire i_xori = ~op[5]&~op[4]&op[3]&op[2]&op[1]&~op[0];
    	wire i_lw = op[5]&~op[4]&~op[3]&~op[2]&op[1]&op[0];
    	wire i_sw = op[5]&~op[4]&op[3]&~op[2]&op[1]&op[0];
    	wire i_beq = ~op[5]&~op[4]&~op[3]&op[2]&~op[1]&~op[0];
    	wire i_bne = ~op[5]&~op[4]&~op[3]&op[2]&~op[1]&op[0];
    	wire i_lui = ~op[5]&~op[4]&op[3]&op[2]&op[1]&op[0];
    	wire i_j = ~op[5]&~op[4]&~op[3]&~op[2]&op[1]&~op[0];
    	wire i_jal = ~op[5]&~op[4]&~op[3]&~op[2]&op[1]&op[0];
    	
    	// 在确定了指令的情况下,确定控制信号的取值
    	assign wreg = i_add|i_sub|i_and|i_or|i_xor|i_sll|i_srl|i_sra|i_addi|i_andi|i_ori|i_xori|i_lw|i_lui|i_jal;
    	assign regrt= i_addi|i_andi|i_ori|i_xori|i_lw|i_lui;
    	assign jal= i_jal;
    	assign m2reg= i_lw;
    	assign shift=i_sll|i_srl|i_sra;
    	assign aluimm=i_addi|i_andi|i_ori|i_xori|i_lw|i_lui|i_sw;
    	assign sext =i_addi|i_lw|i_sw|i_beq|i_bne;
    	assign aluc[3]=i_sra;
    	assign aluc[2]=i_sub|i_or|i_srl|i_sra|i_ori|i_lui;
    	assign aluc[1]=i_xor|i_sll|i_sra|i_xori|i_beq|i_bne|i_lui;
    	assign aluc[0]=i_and|i_or|i_sll|i_srl|i_sra|i_andi|i_ori;
    	assign wmem = i_sw;
    	assign pcsource[1]=i_jr|i_j|i_jal;
    	assign pcsource[0]=i_beq&z|i_bne&~z|i_j|i_jal;
    endmodule
    

    mux2x32.v

    /*32位二路选择器*/
    /*输入决定选择哪一路的控制信号s,输入待选择的信号a0、a1*/
    /*输出被选择的信号y*/
    module mux2x32 (a0,a1,s,y);
    	input [31:0] a0,a1;
    	input s;
    	output [31:0] y;
    	assign y = s?a1:a0; // 如果s为1,选择a1,否则选择a0
    endmodule
    

    mux2x5.v

    /*5位二路选择器*/
    /*逻辑同上*/
    module mux2x5 (a0,a1,s,y);
    	input [4:0] a0,a1;
    	input s;
    	output [4:0] y;
    	assign y = s?a1:a0;
    endmodule
    

    mux4x32.v

    /*32位四路选择器*/
    /*待选择的数是a0~a3,控制信号为s,选择结果为y*/
    /*s如何控制,由case语句决定*/
    module mux4x32 (a0,a1,a2,a3,s,y);
    	input [31:0] a0,a1,a2,a3;
    	input [1:0] s;
    	output [31:0] y;
    	function [31:0] select;
    		input [31:0] a0,a1,a2,a3;
    		input [1:0] s;
    
    		case (s)
    			2'b00: select = a0; //s为00时,选择a0
    			2'b01: select = a1;
    			2'b10: select = a2;
    			2'b11: select = a3;
    		endcase
    	endfunction
    	assign  y = select(a0,a1,a2,a3,s); // y为选择的结果
    endmodule
    

    dff32.v

    /*将数据送入指定寄存器*/
    /*输入待存数据d,待存寄存器q;时钟clk和clrn*/
    /*没有输出*/
    module dff32(d,clk,clrn,q);
    	input [31:0] d;
    	input 	clk,clrn;
    	output [31:0] q;
    	reg  [31:0] q; 
    	/*时序逻辑,clk的上升沿降沿触发、clrn的下降沿触发*/
    	always @ (negedge clrn or posedge clk)
    		// clrn是清零时钟
    		if (clrn == 0) begin // 当清零时钟到来时
    			q <= 0; // 为q赋值0
    		end else begin
    			q <= d; // 否则赋值d
    		end
    endmodule
    

    cla32.v

    /*下面所有程序都是为了实现一个东东:32位并行加法器*/
    /*从最基本的加法进位模型add实现全加器cla_2,
      逐步集成为4位全加器cla_4、8位的全加器cla_8、
      16位全加器cla_16、32位全加器cla_32,
      最终实现32位并行加法器cla32
    */
    
    /*加数是a、b,和是s*/
    /*借位是ci,进位是co*/
    module cla32 (a,b,ci,s,co);
    	input   [31:0]  a,b;
    	input  ci;
    	output   [31:0]   s;
    	output co;
    	wire  g_out, p_out;
    	cla_32  cla   (a,b, ci,g_out,p_out, s); // 向下调用
    	assign  co  =  g_out| p_out &  ci;
    endmodule
    
    
    
    
    module add(a,b,c,g,p,s);
    	input a,b,c;
    	output g,p,s;
    	assign s = a^b^c;
    	assign g = a & b;
    	assign p = a | b;
    endmodule
    
    
    
    module g_p  (g,p,c_in,g_out,p_out,c_out);
    input  [1:0]  g,p;
    input  c_in;
    output g_out, p_out, c_out;
    assign g_out = g[1]|p[1] & g[0];
    assign p_out = p[1]  & p[0];
    assign c_out = g[0]   |  p[0]  &  c_in;
    endmodule
    
    
    
    module cla_2 (a,b,c_in,g_out,p_out,s) ;
    input  [1:0]  a,b;
    input c_in;
    output g_out, p_out;
    output  [1:0]  s;
    wire  [1:0]  g,p;
    wire c_out;
    add add0 (a[0],b[0],c_in, g[0],p[0],s[0]);
    add add1 (a[1],b[1],c_out, g[1],p[1],s[1]);
    g_p g_p0 (g,p,c_in,  g_out,p_out,c_out);
    endmodule
    
    module cla_4 (a,b, c_in,g_out,p_out,s);
    input  [3:0]  a,b;
    input  c_in;
    output g_out, p_out;
    output  [3:0]  s;
    wire  [1:0]  g,p;
    wire c_out;
    cla_2 cla0 (a[1:0],b[1:0],c_in, g[0],p[0],s[1:0]);
    cla_2 clal (a[3:2],b[3:2],c_out,g[1],p[1],s[3:2]);
    g_p    g_p0  (g,p,c_in, g_out,p_out,c_out);
    endmodule
    
    module  cla_8   (a,b, c_in,g_out,p_out, s);
    input   [7:0]  a,b;
    input  c_in;
    output  g_out, p_out;
    output   [7:0]   s;
    wire   [1:0]   g,p;
    wire  c_out;
    cla_4  cla0  (a[3:0],b[3:0],c_in, g[0],p[0],s[3:0]);
    cla_4  c1a1  (a[7:4],b[7:4],c_out,g[1],p[1],s[7:4]);
    g_p   g_p0  (g,p,c_in,  g_out,p_out,c_out);
    endmodule
    
    
    module cla_16 (a,b, c_in,g_out,p_out, s);
    input   [15:0]  a,b;
    input  c_in;
    output  g_out, p_out;
    output   [15:0]  s;
    wire  [1:0]  g,p;
    wire  c_out;
    cla_8  cla0   (a[7:0],b[7:0],c_in,g[0],p[0],s[7:0]);
    cla_8  cla1   (a[15:8],b[15:8],c_out,g[1],p[1],s[15:8]);
    g_p    g_p0  (g,p,c_in,  g_out,p_out,c_out);
    endmodule
    
    
    module cla_32  (a,b,c_in,g_out,p_out, s);
    input  [31:0]  a,b;
    input c_in;
    output  g_out, p_out;
    output  [31:0]  s;
    wire  [1:0]  g,p;
    wire c_out;
    cla_16 c1a0 (a[15:0],b[15:0],c_in,g[0],p[0],s[15:0]);
    cla_16 c1a1 (a[31:16],b[31:16],c_out,g[1],p[1],s[31:16]);
    g_p    g_p0  (g,p,c_in, g_out,p_out,c_out);
    endmodule
    

    addsub32.v

    /*32位加减运算模块*/
    /*调用32位加法模块*/
    /*是加是减,取决于sub的取值*/
    module addsub32(a,b,sub,s);
    	input [31:0] a,b;
    	input  		sub;
    	output [31:0] s;
    	cla32 as32 (a,b^{32{sub}},sub,s);
    endmodule
    

    alu.v

    /*alu算数逻辑单元*/
    /*输入操作数a、b,操作类型信号aluc*/
    /*输出运算结果r;z是?*/
    module alu (a,b,aluc,r,z);
    input [31:0] a,b; 
    // aluc是3位的,每一位都有作用,见下
    input [3:0] aluc; 
    output  [31:0]  r;  
    output z;            
    wire  [31:0]  d_and = a & b; // 求和
    wire  [31:0] d_or = a | b; // 求或
    wire  [31:0] d_xor = a ^ b; // 求异或
    wire  [31:0]  d_lui = {b[15:0],16'h0}; // 拼接,低16位补0
    
    wire  [31:0]  d_and_or = aluc[2]? d_or : d_and; // aluc[2]决定 与/或
    wire  [31:0]  d_xor_1ui= aluc[2]? d_lui : d_xor;  // aluc[2]决定 异或/拼接
    
    wire  [31:0]  d_as,d_sh; // 加减法结果保存到d_as中;移位结果存入d_sh中
    // aluc[2]控制加减法
    addsub32 as32  (a,b,aluc[2],d_as); 
    // b为待移的数,a[4:0]为移动位数,aluc[2]决定左右移,aluc[3]决定补全方式,结果保存在d_sh中
    shift shifter  (b,a[4:0],aluc[2],aluc[3],d_sh) ; 
    
    // 四路选择,aluc[1:0]控制选择哪一路,r为选择结果
    mux4x32 se1ect  (d_as,d_and_or, d_xor_1ui, d_sh, aluc[1:0],r);
    assign z = ~|r;
    endmodule    
    

    regfile.v

    /*读寄存器堆、写寄存器堆*/
    /*输入将要读取哪一个寄存器rna、rnb;输出读出的内容qa、qb*/
    /*输入写使能we、待写入的寄存器wn,待写入的数据d*/
    /*输入时钟clk、clrn*/
    module regfile  (rna, rnb, d, wn,we, clk, clrn, qa, qb);
    input       [4:0]  rna,rnb,wn;
    input     [31:0]  d;
    input     we, clk, clrn;
    output  [31:0]  qa,qb;
    reg     [31:0]  register  [1:31];  // 定义32个32位寄存器
    
    // 读寄存器
    // 如果指定的是rna,即rna不为0,将rna寄存器中的内容放入qa
    assign qa  =   (rna ==  0) ? 0 : register[rna]; 
    // 如果指定的是rnb,即rnb不为0,将rnb寄存器中的内容放入qb
    assign qb  =   (rnb ==  0) ? 0 : register[rnb];
     
    
    // 写寄存器
    // 时序逻辑,clk的上升沿或clrn的下降沿触发
    always @(posedge clk or negedge clrn)
    begin 
    if  (clrn==0) // 当为清空时钟信号时
    begin
    	integer i;
    	for(i=1;i<32;i=i+1)
    		register[i] <= 0; // 清空所有寄存器
    end 
    else  if((wn!=0)&&we) // 当写使能为逻辑1,且wn不是0时
    register[wn]  <= d; // 将d写入wn寄存器
    end
    endmodule
    

    sccpu_dataflow.v

    /*cpu*/
    /*输入时钟信号clock、是否进行清零的信号resetn*/
    /*输入32位指令inst、以及其他值*/
    module  sccpu_dataflow(clock, resetn, inst, mem, pc, wmem, alu, data);
    input     [31:0]   inst,mem;
    input         clock, resetn;
    output   [31:0]  pc,alu,data;
     
    output wmem;
    wire  [31:0] p4 , bpc, npc, adr, ra, alua, alub, res, alu_mem;
    wire  [3:0] aluc;
    wire  [4:0] reg_dest, wn;
    wire  [1:0] pcsource;
    wire  zero, wmem, wreg, regrt, m2reg, shift, aluimm, jal, sext;
    wire  [31:0]  sa  =  {27'b0,inst[10:6]};
    wire  [31:0]  offset  =  {imm[13:0],inst[15:0],2'b00};
    
    /*控制器*/
    // 输入inst[31:26]即op字段、inst[5:0]即func字段、0标志位zero
    // 输出wmem、wreg等控制信号
    sccu_dataflow cu  (inst[31:26] , inst[5:0] , zero, wmem,wreg,regrt,m2reg, aluc, shift, aluimm,pcsource, jal, sext);
    
    /*0拓展或符号拓展*/
    wire   e  =  sext  &  inst[15]; // 取出0或者符号 
    wire   [15:0]       imm =  {16{e}}; 
    wire  [31:0]       immediate  =  {imm,inst[15:0]}; // 拼接、拓展
    
    /*修改PC,使PC指向下一条地址*、
    dff32  ip  (npc,clock,resetn,pc); // 将npc(即下一条指令的地址)写入寄存器pc
    
    /*计算下地址*/
    // 四路选择器的0路
    cla32  pcplus4   (pc,32'h4,1'b0,p4); // pc和32位十六进制4相加,再加上进位0,结果放入p4
    // 四路选择器的1路
    cla32  br_adr     (p4,offset,1'b0, adr); // p4和拓展后的imm相加,再加上进位0,结果放入adr
    // 四路选择器的3路
    wire  [31:0]        jpc =  {p4[31:28],inst[25:0],2'b00}; // 如图
    
    /*二路选择器*/
    // ③号。在ra即q1、sa之间选择,控制信号是shift,选择结果为alua
    mux2x32  alu_a  (ra,sa,shift,alua);
    // ④号。在data即q2、immediate之间选择,控制信号是aluimm,选择结果为alub
    mux2x32  alu_b  (data, immediate,aluimm, alub);
    // ⑤号。在alu即r、mem即do之间选择,控制信号是m2reg,选择结果为alu_mem
    mux2x32  result   (alu,mem,m2reg,alu_mem);
    // ②号。在alu_mem、p4之间选择,控制信号是jal即call,选择结构是res
    mux2x32  link (alu_mem,p4,jal,res);
    // ①号。在inst[15:11]即rd,inst[20: 16]即rt之间选择,控制信号是regrt,选择结果是reg_dest
    mux2x5  reg_wn   (inst[15:11], inst[20: 16] , regrt, reg_dest);
    // 对应图中的①号后面的f器件(不知道做什么的...)
    assign wn = reg_dest   |   {5{jal}}; 
    
    /*四路选择器,计算下地址*/
    // 在p4、adr即addr、ra即q1、jpc即p4+immidiate<<2,之间选择,控制信号是pcsource,选择结果是npc
    mux4x32  nextpc  (p4,adr,ra, jpc,pcsource,npc);
    
    /*寄存器组*/
    // 定义一个寄存器,输入端口是inst[25:21]即rs(n1)、inst[20:16]即rt(n2)
    // 输出端口是data即ra即q1、data即q2
    // 输入写使能wreg、待写寄存器wn即n
    // 输入时钟clock即clk、清零时钟resetn
    regfile  rf   (inst[25:21] ,inst[20:16] ,res,wn,wreg,clock,resetn,ra,data);
    
    /*alu*/
    // 操作数是alua、alub,操作结果是aluu空r、标志位zero即z
    // 控制信号是aluc
    alu  al_unit   (alua,alub,aluc,alu, zero); 
    endmodule
    

    sccmop_dataflow.v

    /*最顶层的控制模块*/
    /*输入时钟clock和resetn*/
    /*输出 指令inst、PC的值pc、ALU的运算结果aluout、存储器的输出memout、时钟信号mem_clk*/
    module  sccomp_dataflow(clock, resetn, inst, pc, aluout, memout,mem_clk);
    input  clock, resetn,mem_clk;
    output   [31:0]  inst,pc, aluout,memout;
    wire [31:0]   data;
    wire   wmem;
    // 实例化一个cpu
    sccpu_dataflow s (clock, resetn, inst,memout,pc, wmem, aluout, data);
    // 实例化一个ROM
    scinstmem imem (pc,inst);
    // 实例化一个RAM
    scdatamem dmem (clock, memout, data, aluout, wmem, mem_clk, mem_clk);
    endmodule
    
  • 相关阅读:
    [转]Lua中的元表与元方法
    [转]Lua语言基础汇总(7) -- 协同程序
    [转]Lua语言基础汇总(6)-- 迭代器与泛型for
    [转]Lua语言基础汇总(5) -- 闭包
    [转]Lua语言基础汇总(4) -- 函数
    [转]Lua语言基础汇总(3) -- 语句
    [转]Lua语言基础汇总(2) -- 表达式
    [转]Lua语言基础汇总(1) -- 类型与值
    [Cocos2d-x + lua]Label特点总结
    Xenu检测网站死链
  • 原文地址:https://www.cnblogs.com/hesse-summer/p/10940775.html
Copyright © 2011-2022 走看看