200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 【计算机组织与体系结构】实验二:给定指令系统的处理器设计

【计算机组织与体系结构】实验二:给定指令系统的处理器设计

时间:2020-07-01 22:21:49

相关推荐

【计算机组织与体系结构】实验二:给定指令系统的处理器设计

系列文章目录

【计算机组织与体系结构】实验一:算术逻辑单元的实现

【计算机组织与体系结构】实验二:给定指令系统的处理器设计

【计算机组织与体系结构】实验三:流水线处理器

【计算机组织与体系结构】实验四:指令 CACHE 的设计与实现

文章目录

系列文章目录一、实验目的二、实验环境三、实验内容1、处理器功能2、指令系统定义1)指令说明2)运算指令3)访存指令3)转移类指令四、实验要求五、设计思想(一)CPU接口信号定义(二)处理器的设计方案1、指令格式设计2、处理器结构设计框图及功能描述3、各功能模块结构设计框图及功能描述4、各模块输入输出接口信号定义六、实验设计及测试1、各模块的详细设计2、各模块的功能测试3、系统的详细设计4、系统的功能测试七、测试结果及实验分析1、处理器仿真测试波形(整体)2、FPGA编程下载八、实验总结

一、实验目的

掌握 Vivado 集成开发环境掌握 Verilog 语言掌握 FPGA 编程方法及硬件调试手段深刻理解处理器结构和计算机系统的整体工作原理

二、实验环境

Vivado 集成开发环境和龙芯 Artix-7 实验平台

三、实验内容

根据课程第五章 MIPS 指令集的基本实现,设计并实现一个符合实验指令的非流水处理器,包括 Verilog语言的实现和 FPGA 芯片的编程实现,要求该处理器可以通过所提供的自动测试环境。

1、处理器功能

本实验的任务是设计一个简单的 RISC 处理器,该处理器是在给定的指令集(与 MIPS32 类似)下构建的,支持 11 条指令。假定存储器分为数据缓冲存储器指令缓冲存储器,且都可以在一个时钟周期内完成一次同步存取操作,时钟信号和 CPU 相同。处理器的指令字长为 32 位,包含 32 个 32 位通用寄存器 R0~R31, 1 个32 位的指令寄存器IR和 1 个 32 位的程序计数器PC, 1 个 256×32 位指令缓冲存储器, 1 个 256×32 位的数据缓冲存储器

2、指令系统定义

处理器所支持的指令包括LW, SW, ADD, SUB, AND, OR, XOR, SLT, MOVZ, BEQ, J

其中仅有LWSW是字访存指令,所有的存储器访问都通过这两条指令完成;ADD、 SUB、 AND、 OR、 XOR、SLT、 MOVZ是运算指令,他们都在处理器内部完成;BEQ是分支跳转指令,根据寄存器的内容进行相对跳转;J是无条件转移指令

1)指令说明

关于汇编指令的说明:

• rs 意味着 source register, rd 意味着 destination register;

• rt 有时(如运算指令)意味着第二个 source register,有时(如访存指令)意味着 target (source/destination)

register;

• 我们使用 [rs] 表示寄存器 rs 的内容;

另外,所有算数运算指令都执行有符号运算。

2)运算指令

(1)加法指令 ADD rd, rs, rt

该指令将两个源寄存器内容相加,结果送回目的寄存器的操作。

具体为: [rd] <- [rs] + [rt]

(2)减法指令 SUB rd, rs, rt

该指令将两个源寄存器内容相减,结果送回目的寄存器的操作。

具体为: [rd] <- [rs] - [rt]

(3)与运算指令 AND rd, rs, rt

该指令将两个源寄存器内容相与,结果送回目的寄存器的操作。

具体为: [rd] <- [rs] & [rt]

(4)或运算指令 OR rd, rs, rt

该指令将两个源寄存器内容相或,结果送回目的寄存器的操作。

具体为: [rd] <- [rs] | [rt]

(5)异或指令 XOR rd, rs, rt

该指令将两个源寄存器内容相异或,结果送回目的寄存器的操作。

具体为: [rd] <- [rs] ⊕ [rt]

(6)小于指令 SLT rd, rs, rt

该指令将两个源寄存器内容相比较,结果决定目的寄存器的值。

具体为: [rd] <- [rs] < [rt] ? 1 : 0

(7)条件移动指令 MOVZ rd, rs, rt

该指令根据其中一个源寄存器内容,决定另一个源寄存器的值是否写回目的寄存器。

具体为: if ([rt] == 0) then [rd] <- [rs]

Note: 注意:当 [rt] != 0 时,不对寄存器 rd 进行任何写回操作。

3)访存指令

Warning: 使用访存指令时,计算后的目标地址必须是访问数据单元大小的整数倍。对于 LW 和 SW 指令, ([base] + offset) % 4 == 0

(1)存数指令 SW rt, offset(base)

该指令将寄存器 rt 的内容存于主存单元中,对应的地址由 16 位偏移地址 offset 经符号拓展加上 base的内容生成。

具体操作为: Mem[[base] + offset] <- [rt]

(2)取数指令 LW rt, offset(base)

该指令将主存单元中的内容存于寄存器 rt,对应的地址由 16 位偏移地址 offset 经符号拓展加上 base

内容生成。

具体操作为: [rt] <- Mem[[base] + offset]

3)转移类指令

Warning:

• 和 MIPS32 指令集不同,我们给出的跳转指令没有延迟槽。

• 跳转指令使用 NPC(也就是 PC+4)参与跳转地址运算。

(1)条件转移(相等跳转)指令 BEQ rs, rt, offset

该指令根据寄存器 rs 和 rt 的内容决定下一条指令的地址,若两个寄存器内容相等,则 16 位偏移 offset扩充为 32 位,左移 2 位后与 NPC 相加,作为下一条指令的地址,否则程序按原顺序执行。

具体操作为: PC <- ([rs] == [rt]) ? [sign_extend(offset) << 2 + NPC] : NPC

(2)无条件转移指令 J target

该指令改变下一条指令的地址,地址由指令中的 26 位形式地址 instr_index 左移 2 位作为低 28 位,和NPC 的高 4 位拼接而成。

具体操作为: PC <- (NPC[31:28]) ## (instr_index << 2)

四、实验要求

要求根据以上给定的指令系统设计处理器,包括指令格式设计、操作的定义、 Verilog 语言的实现及 FPGA 编程实现。处理器设计实验要求按指定阶段进行。

五、设计思想

(一)CPU接口信号定义

(二)处理器的设计方案

1、指令格式设计

处理器所支持的指令包括 LW, SW, ADD, SUB, AND, OR, XOR, SLT, MOVZ, BEQ, J。其中仅有 LW 和 SW 是字访存指令,所有的存储器访问都通过这两条指令完成; ADD、 SUB、 AND、 OR、 XOR、SLT、 MOVZ 是运算指令,他们都在处理器内部完成; BEQ 是分支跳转指令,根据寄存器的内容进行相对跳转;J 是无条件转移指令。

2、处理器结构设计框图及功能描述

该处理器可以实现11种指令,具体见上面表格

3、各功能模块结构设计框图及功能描述

(1)模块名称及功能:pc;指令寄存器,用来给出指令在指令存储器中的地址。

(2)模块名称及功能:npc;暂存PC输出的结果。

(3)模块名称及功能:符号位扩展signextension;将26位数据符号扩展为32位或者取出16位扩展为32位

(4)模块名称及功能:指令缓冲存储器imem;根据输入的地址来找到相应的指令

(5)模块名称及功能:算术逻辑单元alu;根据不同指令进行不同运算操作。

(6)模块名称及功能:数据存储器dmem;大小为256*32位,用来存储数据,在时钟上升沿,判断是否复位,若复位,则将数据缓冲存储器初始化,如果不复位,则根据写使能信号进行写操作。读操作不需要时钟信号。

(7)模块名称及功能:控制单元cu;根据输入的opcode、func、equal、radata、resetn, 来输出各种控制信号。

(8)模块名称及功能:32个32位寄存器堆regfile;可以进行两个寄存器的数据读出和一个寄存器的写回。

(9)模块名称及功能:二选一mux;对输入的两个32位数据进行选择,如果选择控制信号为1,则选择data1;如果为0,则选择data0。

(10)模块名称及功能:datatempstore;暂存数据imm、a、b、ir、aluoutput、lmd

(11)模块名称及功能:equal;比较数据是否相等,0表示不相等;1表示相等。

(12)模块名称及功能:writebackaddrmux;进行写回寄存器的选择

4、各模块输入输出接口信号定义

(1)模块名称及功能:pc;指令寄存器,用来给出指令在指令存储器中的地址。

(2)模块名称及功能:npc;暂存PC输出的结果。

(3)模块名称及功能:符号位扩展signextension;将26位数据符号扩展为32位或者取出16位扩展为32位

(4)模块名称及功能:指令缓冲存储器imem;根据输入的地址来找到相应的指令

(5)模块名称及功能:算术逻辑单元alu;根据不同指令进行不同运算操作。

(6)模块名称及功能:数据存储器dmem;大小为256*32位,用来存储数据,在时钟上升沿,判断是否复位,若复位,则将数据缓冲存储器初始化,如果不复位,则根据写使能信号进行写操作。读操作不需要时钟信号。

(7)模块名称及功能:控制单元cu;根据输入的opcode、func、equal、radata、resetn,

来输出各种控制信号。

(8)模块名称及功能:32个32位寄存器堆regfile;可以进行两个寄存器的数据读出和一个寄存器的写回。

(9)模块名称及功能:二选一mux;对输入的两个32位数据进行选择,如果选择控制信号为1,则选择data1;如果为0,则选择data0。

(10)模块名称及功能:datatempstore;暂存数据,包括imm、a、b、ir、aluoutput、lmd

(11)模块名称及功能:equal;比较数据是否相等,0表示不相等;1表示相等。

(12)模块名称及功能:writebackaddrmux;进行写回寄存器的选择

六、实验设计及测试

1、各模块的详细设计

(包括各模块功能详述,设计方法,Verilog语言实现等)

(1)模块名称及功能:pc;指令寄存器,用来给出指令在指令存储器中的地址。

module pc(input clk,input resetn,input[31:0] nextpc,output reg[31:0] currentpc);initial begincurrentpc <= 0;end always@(posedge clk)beginif(!resetn) currentpc <= 0; else currentpc <= nextpc;endendmodule

(2)模块名称及功能:npc;暂存PC输出的结果。

module npc(input[31:0] pc,output[31:0] pcadd4);assign pcadd4 = pc + 4;endmodule

(3)模块名称及功能:符号位扩展signextension;将26位数据符号扩展为32位或者取出16位扩展为32位

module signextension(input is_J,//控制信号,如果为0,表示为sw/lw/beq(16->32),如果为1,表示为J(26->32)input [25:0]data,//待扩展的数据output [31:0]extendresult//扩展结果);assign extendresult = (is_J)?{{6{data[25]}},data}:{{16{data[15]}},data[15:0]};//如果是J指令,则将26位扩展为32位endmodule

(4)模块名称及功能:指令缓冲存储器imem;根据输入的地址来找到相应的指令

module imem(input[31:0] pc,output[31:0] instruction);reg [31:0] instmemory[255:0];initial begin$readmemh("D:/Users/Administrator/VivadoProjects/lab2/lab2.data/inst_data.txt",instmemory);//读取指令文件到inst_dataendassign instruction = instmemory[pc>>2];endmodule

(5)模块名称及功能:算术逻辑单元alu;根据不同指令进行不同运算操作。

module alu(input[31:0] data0,input[31:0] data1,input[5:0] operation,output[31:0] result);//存储不同指令的计算结果wire [31:0] result1;//add lw swwire [31:0] result2;//subwire [31:0] result3;//andwire [31:0] result4;//orwire [31:0] result5;//xorwire [31:0] result6;//sltwire [31:0] result7;//movzwire [31:0] result8;//beqwire [31:0] result9;//jwire [31:0] temp;//计算不同指令的结果assign result1 = data0 + data1;//add sw lwassign result2 = data0 - data1;assign result3 = data0 & data1;assign result4 = data0 | data1;assign result5 = data0 ^ data1;assign result6 = (data0 < data1)?32'b1 : 32'b0;assign result7 = (data1 == 0)? data0 : 32'b0;assign result8 = data0 + (data1 << 2);//beqassign temp = data1 << 2;assign result9 ={data0[31:26], temp[25:0]};//j//根据operation选择resultassign result = ({32{operation == 6'b100000}} & result1) |//add({32{operation == 6'b100010}} & result2) |//sub({32{operation == 6'b100100}} & result3) |//and({32{operation == 6'b100101}} & result4) |//or({32{operation == 6'b100110}} & result5) |//xor({32{operation == 6'b101010}} & result6) |//slt({32{operation == 6'b001010}} & result7) |//movz({32{operation == 6'b111000}} & result1) |//lw sw({32{operation == 6'b101000}} & result8) |//beq({32{operation == 6'b110000}} & result9) ;//jendmodule

(6)模块名称及功能:数据存储器dmem;大小为256*32位,用来存储数据,在时钟上升沿,判断是否复位,若复位,则将数据缓冲存储器初始化,如果不复位,则根据写使能信号进行写操作。读操作不需要时钟信号。

module dmem(input[31:0] data,//待存入的数据input[31:0] address,//要读数据的地址input dmem_write_en,//0表示lw取数;1表示sw存数,即写使能有效input clk,input resetn,output[31:0] outputdata );reg [31:0]datamemory[255:0];reg [31:0]static_memory[255:0];initial begin$readmemh("D:/Users/Administrator/VivadoProjects/lab2/lab2.data/data_data.txt",datamemory);$readmemh("D:/Users/Administrator/VivadoProjects/lab2/lab2.data/data_data.txt",static_memory);endreg[7:0] addr;initial addr = 0;always@(posedge clk)beginif(!resetn)datamemory[addr] <= static_memory[addr];else if(dmem_write_en)datamemory[address>>2]<=data;//swendalways@(posedge clk) beginif(!resetn) addr <=addr +1;endassign outputdata = datamemory[address>>2];//lwendmodule

(7)模块名称及功能:控制单元cu;根据输入的opcode、func、equal、radata、resetn,

来输出各种控制信号。

module cu(input[5:0] opcode,input[10:0] func,input equal,input[31:0] rtdata,input resetn,output pc_select,output lw_select,output reg_wen,output a_mux_select,output b_mux_select,output dmem_write_en,output is_J,output[5:0] operation);//opcodeparameter [5:0] ALU = 6'b000000;parameter [5:0] SW = 6'b101011;parameter [5:0] LW = 6'b100011;parameter [5:0] BEQ = 6'b000100;parameter [5:0] J = 6'b000010;//funcparameter [5:0] MOVZFUNC = 6'b001010;//用来暂存不同指令应该输出的operationwire [5:0] operation1;wire [5:0] operation2;wire [5:0] operation3;wire [5:0] operation4;//列举所有operation情况assign operation1 = func[5:0];//alu指令后6位作为operation标志assign operation2 = 6'b101000;//beqassign operation3 = 6'b110000;//jassign operation4 = 6'b111000;//lw swassign operation = ({6{opcode == ALU}}& operation1) |({6{opcode == BEQ}}& operation2) |({6{opcode == J}}& operation3) |({6{opcode == LW}}& operation4) |({6{opcode == SW}}& operation4);//输出各种信号assign pc_select = (opcode == J || (opcode == BEQ && equal ==1 ))? 1'b1:1'b0;assign lw_select = (opcode == LW)? 1'b1:1'b0;assign reg_wen = (opcode == LW || (opcode == ALU &&!(func[5:0]==MOVZFUNC && rtdata !=0))) ? 1'b1 :1'b0;assign a_mux_select = (opcode ==J || opcode == BEQ) ? 1'b1:1'b0;//1表示需要跳转assign b_mux_select = (opcode == J || opcode == BEQ || opcode == LW || opcode == SW) ? 1'b1:1'b0;//表示需要用到偏移assign dmem_write_en = (opcode == SW)? 1'b1:1'b0;//只有sw往dmem写assign is_J = (opcode == J)? 1'b1:1'b0;endmodule

(8)模块名称及功能:32个32位寄存器堆regfile;可以进行两个寄存器的数据读出和一个寄存器的写回。

module regfile(input clk ,input resetn ,// READ PORT 1input [4 :0] raddr1,output [31:0] rdata1,// READ PORT 2input [4 :0] raddr2,output [31:0] rdata2,// WRITE PORTinput wen , //write enable, active highinput [4 :0] waddr ,input [31:0] wdata);reg [31:0] rf [31:1];//R0恒0 不可操作// initial with $readmemh is synthesizable hereinitial begin$readmemh("D:/Users/Administrator/VivadoProjects/lab2/lab2.data/reg_data.txt", rf);end//WRITEalways @(posedge clk) beginif (wen && |waddr) begin // don't write to $0rf[waddr] <= wdata;endend //READ OUT 1assign rdata1 = (raddr1 == 5'b0) ? 32'b0 : rf[raddr1];//READ OUT 2assign rdata2 = (raddr2 == 5'b0) ? 32'b0 : rf[raddr2];endmodule

(9)模块名称及功能:二选一mux;对输入的两个32位数据进行选择,如果选择控制信号为1,则选择data1;如果为0,则选择data0。

module mux(input[31:0] data0,input[31:0] data1,input selectsignal,output[31:0] result);assign result = (selectsignal)?data1:data0;endmodule

(10)模块名称及功能:datatempstore;暂存数据,包括imm、a、b、ir、aluoutput、lmd

module datatempstore(input[31:0] inputdata,output[31:0] outputdata);assign outputdata = inputdata;endmodule

(11)模块名称及功能:equal;比较数据是否相等,0表示不相等;1表示相等。

module equal(input[31:0] data0,input[31:0] data1,output result);assign result = (data0 == data1)? 1 : 0;endmodule

(12)模块名称及功能:writebackaddrmux;进行写回寄存器的选择

module writebackaddrmux(input [4:0] addr0,input [4:0] addr1,input lw_select,output [4:0] result);assign result = (lw_select)? addr1:addr0;endmodule

2、各模块的功能测试

(每个模块作为一个部分,包括测试方案、测试过程和测试波形等)

(1)alu_tb 对模块alu进行仿真

测试方案:

module alu_tb;//输入reg [31:0] data0;reg [31:0] data1;reg [5:0] operation;//输出wire [31:0] result;initial begindata0 = 31'hfffffff0;data1 = 32'h00000002;#10 operation = 6'b100000;//add#10 operation = 6'b111000;//sw lw#10 operation = 6'b100010;//sub#10 operation = 6'b100100;//and#10 operation = 6'b100101;//or#10 operation = 6'b100110;//xor#10 operation = 6'b101010;//slt#10 operation = 6'b001010;//movz#10 operation = 6'b101000;//beq#10 operation = 6'b110000;//jmpendalu alu_0(.operation(operation),.data0(data0),.data1(data1),.result(result));endmodule

仿真波形:

(2) cu_tb对模块cu进行仿真

测试方案:

module cu_tb;//输入reg [5:0] opcode;reg [10:0] func;reg equal;reg [31:0] rtdata;//输出wire pc_select;wire lw_select;wire reg_wen;wire a_mux_select;wire b_mux_select;wire dmem_write_en;wire is_J;wire [5:0] operation;initial begin//初始化opcode = 6'b000000;func = 11'b00000100000;equal = 1'b0;rtdata = 32'b0;#10 //addopcode = 6'b000000;func = 11'b00000100000;equal = 1'b0;#10 //subopcode = 6'b000000;func = 11'b00000100010;equal = 1'b0;#10 //andopcode = 6'b000000;func = 11'b00000100100;equal = 1'b0;#10 //oropcode = 6'b000000;func = 11'b00000100101;equal = 1'b0;#10 //xoropcode = 6'b000000;func = 11'b00000100110;equal = 1'b0;#10 //sltopcode = 6'b000000;func = 11'b00000101010;equal = 1'b0;#10 //movz rtdata==0opcode = 6'b000000;func = 11'b00000001010;equal = 1'b0;rtdata = 32'b0;#10 //movz rtdata!=0opcode = 6'b000000;func = 11'b00000001010;equal = 1'b0;rtdata = 32'b1;#10 //swopcode = 6'b101011;#10 //lwopcode = 6'b100011;#10 //beq equal == 1opcode = 6'b000100;equal = 1'b1;#10 //beq equal == 0opcode = 6'b000100;equal = 1'b0;#10 //jopcode = 6'b000010;endcu cu_0(.opcode(opcode),.func(func),.equal(equal),.rtdata(rtdata),.resetn(resetn),.pc_select(pc_select),.lw_select(lw_select),.reg_wen(reg_wen),.a_mux_select(a_mux_select),.b_mux_select(b_mux_select),.dmem_write_en(dmem_write_en),.is_J(is_J),.operation(operation) );endmodule

仿真波形:

3、系统的详细设计

(包括系统功能详述,设计方法,Verilog语言实现等)

module cpu(input clk , // clock, 100MHz(*mark_debug = "true"*)input resetn , // active high// debug signals(*mark_debug = "true"*)output [31:0] debug_wb_pc , // 当前正在执行指令的 PC(*mark_debug = "true"*)output debug_wb_rf_wen , // 当前通用寄存器组的写使能信号(*mark_debug = "true"*)output [4 :0] debug_wb_rf_addr, // 当前通用寄存器组写回的寄存器编号(*mark_debug = "true"*)output [31:0] debug_wb_rf_wdata // 当前指令需要写回的数据);//存储指令的各个部分wire [5:0] opcode;//cuwire [4:0] raddr1;wire [4:0] raddr2;wire [4:0] raddr3;wire [10:0] func;//cuwire [25:0] instr_index;wire [31:0] current_instruction;//当前指令,从ir取出assign opcode = current_instruction[31:26];assign raddr1 = current_instruction[25:21];assign raddr2 = current_instruction[20:16];assign raddr3 = current_instruction[15:11];assign func = current_instruction[10:0];assign instr_index = current_instruction[25:0];//定义各种线//cu的输出wire pc_select;wire lw_select;wire reg_wen;wire a_mux_select;wire b_mux_select;wire dmem_write_en;wire [5:0] operation;wire is_J;//控制signextensionwire equal;wire [31:0] nextpc;//pc输入,pc_mux输出wire [31:0] currentpc;//pc输出,imem\npc输入wire [31:0] pcadd4;//pc+4wire [31:0] output_instruction;//imem读出的指令wire [31:0] immin;//imm输入wire [31:0] immout;//imm输出wire [31:0] aout;//A输出wire [31:0] bout;//B输出wire [31:0] rdata1;//register读出的第一个数,A输入wire [31:0] rdata2;//register读出的第二个数,B输入wire [4:0] waddr;//register要写回的寄存器编号,writebackaddr_mux输出wire [31:0] wdata;//register要写回的寄存器内容,data_mux输出wire [31:0] alua;//alu第一个操作数,a_mux输出wire [31:0] alub;//alu第二个操作数,b_mux输出wire [31:0] result;//alu的计算结果wire [31:0] aluresultdata;//aluoutput输出wire [31:0] lmdin;//dmem读出的数据,lmd输入wire [31:0] lmdout;//lmd输出,data_mux输入//cpu输出assign debug_wb_pc = currentpc;assign debug_wb_rf_wen = reg_wen;assign debug_wb_rf_addr = waddr;assign debug_wb_rf_wdata = wdata;//各个模块的连线 pc U_pc(.clk(clk),.resetn(resetn),.nextpc(nextpc),.currentpc(currentpc));npc U_npc(.pc (currentpc),.pcadd4 (pcadd4));imem U_imem(.pc(currentpc),.instruction(output_instruction));datatempstore U_ir(.inputdata (output_instruction),.outputdata (current_instruction));regfile U_regfile(.clk(clk),.resetn(resetn),.raddr1(raddr1),.rdata1(rdata1),.raddr2(raddr2),.rdata2(rdata2),.wen(reg_wen),.waddr(waddr) ,.wdata(wdata));datatempstore U_a(.inputdata (rdata1),.outputdata (aout));datatempstore U_b(.inputdata (rdata2),.outputdata (bout)); signextension U_signextension(.is_J(is_J),.data(instr_index),.extendresult(immin));datatempstore U_imm(.inputdata (immin),.outputdata (immout)); equal U_equal(.data0(aout), .data1(bout),.result(equal)); mux U_a_mux(.data0(aout),.data1(pcadd4),.selectsignal(a_mux_select),.result(alua));mux U_b_mux(.data0(bout),.data1(immout),.selectsignal(b_mux_select),.result(alub));alu U_alu(.data0(alua),.data1(alub),.operation(operation),.result(result));datatempstore U_aluoutput(.inputdata (result),.outputdata (aluresultdata)); dmem U_dmem(.data(bout),.address(aluresultdata),.dmem_write_en(dmem_write_en),.clk(clk),.resetn(resetn),.outputdata(lmdin));datatempstore U_lmd(.inputdata (lmdin),.outputdata (lmdout)); mux U_pc_mux(.data0(pcadd4),.data1(aluresultdata),.selectsignal(pc_select),.result(nextpc));mux U_data_mux(.data0(aluresultdata),.data1(lmdout),.selectsignal(lw_select),.result(wdata));writebackaddrmux U_writebackaddrmux(.addr0(raddr3),.addr1(raddr2),.lw_select(lw_select),.result(waddr));cu U_cu(.opcode(opcode),.resetn(resetn),.func(func),.equal(equal),.rtdata(rdata2),.pc_select(pc_select),.lw_select(lw_select),.reg_wen(reg_wen),.a_mux_select(a_mux_select),.b_mux_select(b_mux_select),.dmem_write_en(dmem_write_en),.operation(operation),.is_J(is_J));endmodule

4、系统的功能测试

(包括系统整体功能的测试方案、测试过程和测试波形等)

测试方案:本实验已经提供了测试代码,观察代码发现,首先resetn信号置为0,表示重置,即需要初始化,等到2000ns时,重置信号resetn变成1,这时我们的指令才开始执行,即调用cpu_top模块来进行测试。

`timescale 1ns / 1psmodule cpu_tb();//-----Clock and reset signal simulation-----//signalsreg clk;reg resetn;//simulationinitial beginclk = 1'b0;resetn = 1'b0;#2000;resetn = 1'b1;endalways #5 clk = ~clk;cpu_top U_cpu_top(.clk(clk),.reset (resetn ));//-----monitor test-----initialbegin$timeformat(-9,0," ns",10);while(!resetn) #5;$display("==============================================================");$display("Test begin!");#10000;endendmodule

测试波形如下:

七、测试结果及实验分析

1、处理器仿真测试波形(整体)

2、FPGA编程下载

(1) 编写处理器功能测试程序,包括助记符和二进制代码。

对于实验二,提供了一个自动测试环境,包含了所设计的11中指令。cpu_tb文件具体设计如下,调用了cpu_top函数。观察发现,时钟信号clk是每5ns进行取反。前2000ns里面resetn信号一直为0,直到第2000ns resetn信号才变为1,指令才开始向下执行。

`timescale 1ns / 1psmodule cpu_tb();//-----Clock and reset signal simulation-----//signalsreg clk;reg resetn;//simulationinitial beginclk = 1'b0;resetn = 1'b0;#2000;resetn = 1'b1;endalways #5 clk = ~clk;cpu_top U_cpu_top(.clk(clk),.reset (resetn ));//-----monitor test-----initialbegin$timeformat(-9,0," ns",10);while(!resetn) #5;$display("==============================================================");$display("Test begin!");#10000;endendmodule

(2) 上板波形记录与解释

上板情况如下,开发板上一排单色灯同时亮起:

对4个信号的抓取情况如下:首先启动逻辑分析仪,然后按下复位键,可以观察到捕捉到了后半阶段的波形,data的输出与之前的仿真结果相同,pc表示指令地址,也是每次加4,写使能信号和addr的输入也都符合之前的分析。

八、实验总结

这次实验通过编写verilog实现了一个非流水线单周期处理器,本次实验细节非常多,需要考虑的事情也很多,也使我体会到了模块化编程的简便之处。通过自己动手设计一个处理器,是我更加深刻地学习到了其中的细节,体会到了乐趣。总之,这次实验使我收获很多。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。