计算机组成原理实验——实现存储器模块Verilog

敬请指正~

主存

指令内存ROM:运行时指令不能改变 只有一个读接口,根据地址返回对应的指令 只读,一般用来存储指令运行前将指令存放到ROM种
数据内存RAM:一个读接口一个写接口,读写不同时进行,故读写接口共用一个地址输入端

ROM:raddr、rdata、CE
数据初始化
reg[31:0]inst_rom[0:1023];
initial //法一:只能仿真,不能综合
begin
$readmemh(“ins.eme”,inst_rom); //h:十六进制,读文件“ins.men"中的数据放到inst_rom
end

/IP核-ROM,IP核:知识产权核,只能用,不能知道怎么实现
深度:多少条指令 宽度:每条指令几位
分号结束,每个数据间逗号分隔

module sim(
	);
	reg[5:0] addr;
	wire[31:0] ins;
	insrom ir(addr,ins);
initial
	addr = 5'b0;
initial
	$monitor($time,,"ins=%h",ins);
endmodule

//3

module rom(
	input [31:0] addr,
	output [31:0] data
	);
	reg[31:0] romdata;
	always @(*)
		case(addr[31:2])	//抛弃后两位地址
			4'h0: romdata = 32'h11111111;
			4'h1: romdata = 32'h22222222;
			4'h2: romdata = 32'h33333333;
			4'h3: romdata = 32'h44444444;
			default: romdata = 32'h00000000;
		endcase

	assign data = romdata;
endmodule

PC

PC程序计数器,指向下一条指令的地址。
由于MIPS指令是32bit的,所以下一条指令的地址是PC+4,而不是PC+1。
另外,为了实现跳转,PC必须包含接受新地址的能力。

next_addr addr rst clk

module PC(		//顺序执行,不考虑跳转
	input rst,
	input clk,
	output reg [31:0] insAddr
	);
	always @(posedge clk)
	begin
		if (rst==1'b0)
			insAddr<=32'h0;
		else
			insAddr<=insAddr+4;
	end
endmodule

RAM
addr rdata wdata clk CE WE
addr:为读、写提供地址,共用地址端口
写:WE=1
在这里插入图片描述

//rom模块:
module rom(
    input [31:0] addr,
    output [31:0] data
    );
    reg[31:0] romdata;
    always @(*)
        case(addr)
        4'h0:romdata=32'h34020002;       //编写rom存储内容
        4'h4:romdata=32'h8c030020;
        4'h8:romdata=32'h34040001;
        4'hc:romdata=32'h34050001;
        8'h10:romdata=32'h00853020;      //16进制10和14需要8位来存储
        8'h14:romdata=32'h00052026;
        default:romdata=32'h00000000;
        endcase
    assign data=romdata;
endmodule

//pc模块:
module pc(
    input clk,
    input rst,
    output reg [31:0] insAddr
    );
    always @(posedge clk)
    begin
        if(rst==1'b0)
            insAddr<=32'h0;    //当rst=0时进行初始化,初始指令的地址为0
        else
            insAddr<=insAddr+4; //由于MIPS指令是32位,所以下一条指令的地址是PC+4
    end
endmodule

//仿真程序
module rom_sim(
    );
    reg clk;
    reg rst=1'b1;
    wire[31:0] addr;
    wire[31:0] data;
    //时钟信号仿真
    initial 
        begin
            clk=1'b0;
            forever
                #2 clk=~clk;
        end
	//pc、rom模块实例化
    pc mypc(clk,rst,addr);
    rom myrom(addr,data);   
    
initial
        begin
            #2 rst=1'b0;
            #4 rst=1'b1;
        end
    //监视结果,输出rom存储内容
initial
    $monitor($time,,"addr=%h;data=%h",addr,data);
    initial
    #30 $stop;
endmodule

在这里插入图片描述

//top模块:
module top2(
    input clk,
    input rst,
    input [4:0] n,
    output [11:0] result
    );
    wire [31:0] out;
    assign result=out[11:0];
    fib1 f(clk,rst,n,out);
        
    initial
    $monitor($time,,"top:result=%d",result);
endmodule

//alu模块:
module alu(
    input [31:0] a,
    input [31:0] b,
    input [3:0] operation,
    output [31:0] f,
    output z
    );
     reg[31:0]result;
       always@(*)
       begin
           case(operation)
               4'b0000:result=32'b0;
               4'b0001:result=a+b;
               4'b0010:result=a-b;
               4'b0011:result=a&b;
               4'b0100:result=a|b;
               4'b0101:result=a^b;
               default:result=32'b0;
           endcase
       end
       assign f=result;
       assign z=~(|result);
       
       initial
           $monitor($time,,"alu:a=%h,b=%h,operation=%b",a,b,operation);
       initial
           $monitor($time,,"alu:f=%h,z=%b",f,z);
endmodule

//registers模块:
module registers(
    input clk,
    input oc,
    input [4:0] raddr1,
    input [4:0] raddr2,
    input [4:0] waddr,
    input [31:0] wdata,
    input we,       //使能端,读写信号
    output [31:0] rdata1,
    output [31:0] rdata2
    );
    reg [31:0] rdata1;
    reg [31:0] rdata2;
    reg [31:0] regts[1:31];
    //读端口1
    always @(*)     
    begin
        if(oc == 1'b1)
        begin
            rdata1 <= 32'b0;
        end
        else if(raddr1 == 5'b00000)     //$0号寄存器只保存0
        begin
            rdata1 <= 32'b0;
        end
        begin
            rdata1 <= regts[raddr1];
        end
    end
    //读端口2
    always @(*)
        begin
            if(oc == 1'b1)
            begin
                rdata2 <= 32'b0;
            end
            else if(raddr2 == 5'b00000)
            begin
                rdata2 <= 32'b0;
            end
            begin
                rdata2 <= regts[raddr2];
            end
        end
        
    always @(posedge clk)   //脉冲信号作用下才能写
        begin
            #1 if((we == 1'b1) &&(waddr != 5'b00000))      //判断使能端是否为1,是否为0号地址,0号寄存器不可写
            begin
                regts[waddr] <= wdata;
            end
        end
endmodule

//ram模块:
module ram(
    input [31:0] addr,
    input [31:0] wdata,
    input clk,
    input ce,
    input we1,
    output [31:0] rdata
    );
    reg [31:0] rdata;
    reg [31:0] ram[0:30];
    always @(*)		//只要有输入就立即输出
      begin
          if(we1 == 1'b0)        //使能端
          begin
              rdata <= ram[addr];
          end
      end

    always @(posedge clk)		//脉冲信号作用下才能写
        begin
            #1 if(we1 == 1'b1)  //判断使能端是否为1
            begin
                ram[addr] <= wdata;
            end
        end
    
endmodule

//fib模块:
module fib1(
    input clk,
    input rst,
    input [4:0] n,
    output [31:0] result
    );
   wire [31:0] a,b,f;
   reg [31:0] wdata,wd,ad;
   wire [31:0]rd;
   wire we = 1'b1;
   wire ce,we1;
   reg w1;
   reg [4:0] ra1,ra2,wa;
   reg [31:0] count;
   parameter op = 4'b0001;        //加法运算
       
    //实例化寄存器
   registers myregs(.clk(clk),.oc(~rst),.raddr1(ra1),.raddr2(ra2),.waddr(wa),.wdata(wdata),.we(we),.rdata1(a),.rdata2(b));
   //实例化ALU
   alu myalu1(a, b, op, f);    //a b与rdata1(a),rdata2(b)连接
   //实例化RAM
   ram myram(.addr(ad), .wdata(wd), .clk(clk), .ce(ce), .we1(w1), .rdata(rd));
   assign result = rd;
        
   reg[1:0]status = 2'b00;    //状态
   always@(posedge clk)
   begin
        if(rst == 1'b0)    //复位信号
        begin
            status <= 2'b00;    //初始化为0
            count <= 3;    //从3开始算
        end else
        case(status)
        2'b00:
            begin
                ra1 <= 5'b1;
                ra2 <= 5'b10;
                wa <= 5'b1;    //1号寄存器
                wdata <= 32'b1;    //1写入1号寄存器
                status <= 2'b01;    //跳转到下一状态
            end
        2'b01:
            begin
                wa <= 5'b10;
                wdata <= 32'b1;
                status <= 2'b10;
            end
       2'b10:
            begin
                wa <= ra2+1;
                wdata <= f;
                status <= 2'b11;
                count <= count + 1;
            end
        2'b11:
            begin
                if(count <= n)      
                begin
                    ra1 <= ra2;        //ra1=ra1+1
                    ra2 <= wa;        //ra2=ra2+1
                    status <= 2'b10;
                end
            end
        endcase
        if(count==n+1)      //将结果写入ram零号单元
            begin
                ad <= 5'b0;
                w1 <= 1'b1;
                wd<=f;
                count <= count + 1;
            end
        if(count==n+2)  //将结果从ram零号单元读出
            begin
                ad<=5'b0;
                w1<=1'b0;
            end
    end
    
    initial
        $monitor($time,,"fib:rst=%d,wdata=%d,count=%d",rst,wdata,count);
    initial
        $monitor($time,,"fib:result=%d",result); 
endmodule

//仿真程序
module fib_sim(
    output [11:0] result
);
//时钟信号仿真
     parameter clk_period=10;
       reg clk;
       initial 
       begin
           clk=1'b0;
           forever
               #(clk_period/2) clk=~clk;
       end
       
       reg rst=1'b1;
       reg[4:0] n=5'b10000;
       top2 t(.clk(clk),.rst(rst),.n(n),.result(result));
       
       initial
       begin
           #2 rst=1'b0;
           #4 rst=1'b1;
       end
endmodule

在这里插入图片描述

  • 8
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值