计算机组成原理——单周期CPU

项目代码

vivado版本为2022.2
链接:
CSDN资源:https://download.csdn.net/download/m0_46314779/85292989
github代码: https://github.com/hd-cmyk/Vivado

实验原理

一共实现了15条指令,9条R型指令,5条I型指令,1条J型指令,指令格式与编码参照《LS-CPU-EXB-003cpu设计与体系结构实验指导手册》中的附录A1。
各个模块核心思路:
PC模块:PC是程序计数器,用于存放下一条要执行指令的地址。有四种情况考虑
① PC=PC+4,执行下一条指令
② PC=PC+4+立即数*4,执行的指令为分支跳转指令,跳转至当前指令后的立即数+1条指令。(考虑了延迟槽技术)
③ PC={(PC+4)[31:28],立即数<<2};,执行的指令为 J型指令,跳转目标为PC 的最高 4 位与立即数左移2 位后的值拼接得到。
④ PC=PC
指令存储器模块:建立异步读的单口ROM 类型的IP核,将指令存入coe文件中供IP核调用。
寄存器堆模块:用二维数组建立两个读端口一个写端口的寄存器堆,并初始化为0。
数据存储器模块:建立二维数据模拟真双口RAM,一个端口用于读写,另一个端口用于将存储器中数据显示在led显示屏上。
控制器模块:针对不同指令中opcode和Func的值设置各个控制变量的值。

MIPS指令

编写冒泡排序程序:
用ADDIU指令将立即数存到寄存器中再用SW指令将寄存器中的数存到存储器中。将8,7,6,5,4,3,2,1八个数存到存储器地址1-8中。写一个循环实现冒泡排序,排序完成后存储器内地址1-8显示1,2,6,7,8,13,14,15。
用汇编指令编写一个冒泡排序,再将汇编指令转化为MIPS指令(下文中G表示通用寄存器)

G[31]1
G[30]0
G[1] ax
G[2] bx
G[3] cx
G[4] dx
G[5] si
G[6] cf
00100111110000110000000000001000//mov cx,8 //addiu 3 30 8
00000000011111100000100000100001//mov ax,xc //addu 1 3 30
loop2:
00100111110001010000000000000001//mov si,1// addiu 5 30 1
loop1:
10001100101000100000000000000000//mov bx,[SI] //lw 2 0 5
10001100101001000000000000000001//mov dx,[SI+1]// lw 4 1 5
00000000010001000011000000101010// cmp bx,dx //slt 6 2 4小于置位
00010000110111110000000000000010//je cf=1 next
10101100101001000000000000000000//mov [SI],dx //sw 4 0 5
10101100101000100000000000000001//mov [SI+1],bx//sw 2 1 5
next:
00100100101001010000000000000001//add si,1//addiu 5 5 1
00010100001001011111111111111000//cmp ax,si jnz loop1//bne 1 5 -7
00000000001111110000100000100011//sub ax,1//subu 1 1 31
00010100001111111111111111110101//cmp ax,1 jnz loop2//bne 1 31 -1

rom.coe文件

memory_initialization_radix = 2;
memory_initialization_vector =
00100111110111110000000000000001
00100111110000010000000000001000
10101111110000010000000000000001
00100111110000010000000000000111
10101111110000010000000000000010
00100111110000010000000000000110
10101111110000010000000000000011
00100111110000010000000000000101
10101111110000010000000000000100
00100111110000010000000000000100
10101111110000010000000000000101
00100111110000010000000000000011
10101111110000010000000000000110
00100111110000010000000000000010
10101111110000010000000000000111
00100111110000010000000000000001
10101111110000010000000000001000
00100111110000110000000000001000
00000000011111100000100000100001
00100111110001010000000000000001
10001100101000100000000000000000
10001100101001000000000000000001
00000000010001000011000000101010
00010000110111110000000000000010       
10101100101001000000000000000000
10101100101000100000000000000001
00100100101001010000000000000001
00010100001001011111111111111000
00000000001111110000100000100011
00010100001111111111111111110101
11111111111111111111111111111111

代码

在这里插入图片描述

顶层模块SingleCycleCPU

module SingleCycleCPU(
        input clk,Reset,
        input [31:0]test_addr,//取存储器
        input [4:0]test_addr1,//取寄存器
        output [31:0] test_data,
        output [31:0]test_data1
       
        
    );
     wire [31:0] instruction;
     wire [31:0]sort;
     wire [31:0] addr;
     wire [1:0]PCSrc;
     wire zero;
     wire [31:0]Out1;
     wire [31:0]Out2;
     wire [4:0]rs;
     wire [4:0]rt;
        
    wire [5:0] opCode;
    wire [31:0] Result;
    wire [4:0] rd;
    wire Extsel, Alu_SrcA, Alu_SrcB;
    wire RD,WR;
    wire [5:0]Func;
    wire PCWre;

    wire [31:0]extendImm;
    
    wire[3:0] Alu_Op;
    wire[31:0] DataOut,DB;
    wire[15:0] Imm;
    wire[4:0] sa;
    wire DBDataSrc, RegWre,RegDst;

    
    assign sort=(opCode==6'b111111)?32'd1:32'd0;
    PC ins(
       .clk(clk),
       .Reset(Reset),
       .PCWre(PCWre),
       .PCSrc(PCSrc),
       .Imm(extendImm),
       .addr(addr),
       .instruction(instruction)
    );
   instructionMemory ins1(
       .addr({2'b0,addr[31:2]}),   
       .opCode(opCode),   
       .rs(rs), 
       .rt(rt),
       .rd(rd),
       .immediate(Imm),
       .sa(sa),
       .Func(Func),
       .instruction(instruction)
    );
    regfile ins2(
       .clk(clk),
       .RegWre(RegWre),//写使能
       .raddr1(rs),//读操作
       .raddr2(rt),
       .rdata1(Out1),
       .rdata2(Out2),
       .waddr(RegDst ? rd : rt),//写操作
       .wdata(DB),//DB从ALU或者寄存器堆拿出数据
       .test_addr(test_addr1),
       .test_data(test_data1)
    );
    Alu ins3(
       .Alu_SrcA(Alu_SrcA),
       .Alu_SrcB(Alu_SrcB),
       .ReadData1(Out1),//操作数1
       .ReadData2(Out2),//操作数2
       .sa(sa),
       .extend(extendImm),
       .Alu_Op(Alu_Op),//操作
       .zero(zero),
       .Alu_Result(Result)//结果
    );
    SignZeroExtend ins4(
    .Imm(Imm),//l型指令低16位是立即数,扩展有1.零扩展 高16为0,2.符号扩展
    .Extsel(Extsel),//状态'0',0扩展,否则符号位扩展
    .extendImm(extendImm)
    );
    DataMemory ins5(
        .clk(clk),
        .wenr(RD),//读使能
        .wenw(WR),//写使能
        .DBDataSrc(DBDataSrc),//MemtoReg数据保存的选择端,为0来自ALU运算结果的输出,为1来自数据寄存器(Data MEM)的输出 
        .DAddr(Result),//若为LW指令则DAddr=aluResult
        .DataIn(Out2),
        .DataOut(DataOut),
        .DB(DB),
        .test_addr(test_addr),
        .test_data(test_data)
    );
    ControlUnit ins6(
        .opCode(opCode),
        .zero(zero),
        .Func(Func),
        .PCWre(PCWre),//=1,PC可变
        .AluSrcA(Alu_SrcA),
        .AluSrcB(Alu_SrcB),    
        .DBDataSrc(DBDataSrc),//数据保存的选择端,为0来自ALU运算结果的输出,为1来自数据寄存器(Data MEM)的输出  
        .RegWre(RegWre), 
        .mRD(RD),//数据存储器的读使能
        .mWR(WR),//数据存储器的写使能
        .ExtSel(Extsel),//立即数扩展
        .RegDst(RegDst),//写寄存器组寄存器的地址,为0的时候地址来自rt,为1的时候地址来自rd
        .PCSrc(PCSrc),//控制PC的
        .Alu_Op(Alu_Op)
    );
    
    
    
endmodule

display外围模块

module single_display(
    //时钟与复位信号
    input clk,
    input resetn,    //后缀"n"代表低电平有效
    //触摸屏相关接口,不需要更改
    output lcd_rst,
    output lcd_cs,
    output lcd_rs,
    output lcd_wr,
    output lcd_rd,
    inout[15:0] lcd_data_io,
    output lcd_bl_ctr,
    inout ct_int,
    inout ct_sda,
    output ct_scl,
    output ct_rstn
);
//-----{LED显示}begin

//-----{LED显示}end

//-----{调用寄存器堆模块}begin
    //寄存器堆多增加一个读端口,用于在触摸屏上显示32个寄存器值
    wire [31:0] test_addr;//存储器
    wire [31:0] test_data;  
    wire [4:0]test_addr1;//寄存器
    wire [31:0]test_data1;

   
    SingleCycleCPU CPU(
        .clk   (clk   ),
        .Reset(resetn),
        .test_addr(test_addr),
        .test_addr1(test_addr1),
        .test_data (test_data),
        .test_data1(test_data1)
    );
//-----{调用寄存器堆模块}end

//---------------------{调用触摸屏模块}begin--------------------//
//-----{实例化触摸屏}begin
//此小节不需要更改
    reg         display_valid;
    reg  [39:0] display_name;
    reg  [31:0] display_value;
    wire [5 :0] display_number;
    wire        input_valid;
    wire [31:0] input_value;

    lcd_module lcd_module(
        .clk            (clk           ),   //10Mhz
        .resetn         (resetn        ),

        //调用触摸屏的接口
        .display_valid  (display_valid ),
        .display_name   (display_name  ),
        .display_value  (display_value ),
        .display_number (display_number),
        .input_valid    (input_valid   ),
        .input_value    (input_value   ),

        //lcd触摸屏相关接口,不需要更改
        .lcd_rst        (lcd_rst       ),
        .lcd_cs         (lcd_cs        ),
        .lcd_rs         (lcd_rs        ),
        .lcd_wr         (lcd_wr        ),
        .lcd_rd         (lcd_rd        ),
        .lcd_data_io    (lcd_data_io   ),
        .lcd_bl_ctr     (lcd_bl_ctr    ),
        .ct_int         (ct_int        ),
        .ct_sda         (ct_sda        ),
        .ct_scl         (ct_scl        ),
        .ct_rstn        (ct_rstn       )
    ); 
//-----{实例化触摸屏}end

//-----{从触摸屏获取输入}begin
//根据实际需要输入的数修改此小节,
//建议对每一个数的输入,编写单独一个always块
    //32个寄存器显示在7~38号的显示块,故读地址为(display_number-1)
    assign test_addr = display_number-6'd1; 
    
//-----{从触摸屏获取输入}end

//-----{输出到触摸屏显示}begin
//根据需要显示的数修改此小节,
//触摸屏上共有44块显示区域,可显示44组32位数据
//44块显示区域从1开始编号,编号为1~44,
    always @(posedge clk)
    begin
        if ( display_number <6'd33 )
        begin //块号7~38显示32个通用寄存器的值
            display_valid <= 1'b1;
            display_name[39:16] <= "MEM";
            display_name[15: 8] <= {4'b0011,test_addr[7:4]};
            display_name[7 : 0] <= {4'b0011,test_addr[3:0]}; 
            display_value       <= test_data;
          end
        else
        begin
           display_valid<=1'b0;
           display_name<=40'd0;
           display_value<=32'd0;
        end
    end
//-----{输出到触摸屏显示}end
//----------------------{调用触摸屏模块}end---------------------//
endmodule

PC

module PC(
    input clk,Reset,//Reset从头开始执行
    input PCWre,//PCWre=1可更改,=0不可更改
    input [1:0]PCSrc,//=1为分支指令
    input [31:0] Imm,//立即数
    inout [31:0] instruction,
    output reg[31:0] addr
    );
   initial
   begin
   addr=0;
   end
   reg [31:0]addr1;
    always@(posedge clk)
    begin
            
            if(PCWre)
            begin
            addr1=addr+4;
            if(PCSrc==2'b00) addr=addr+4;//跳转到下一条指令
            else if(PCSrc==2'b01) addr=addr+4+Imm*4;//跳转指令
            else if(PCSrc==2'b10) addr={addr1[31:28],instruction[25:0]<<2};
            else if(PCSrc==2'b11) addr=addr;
            end
        
    end 
endmodule

instructionMemory

module instructionMemory(
    // 根据数据通路图定义输入和输出
    input  [31:0] addr,   
    output [5:0] opCode,   
    output [4:0] rs, rt, rd,  
    output [15:0] immediate,
    output [4:0] sa,
    output [5:0] Func,
    output [31:0] instruction
    );
    inst_rom inst_rom_module(
        .a  (addr[7:0]),
        .spo  (instruction)
    );

    // output  
    assign opCode = instruction[31:26];  
    assign rs = instruction[25:21];  
    assign rt = instruction[20:16];  
    assign rd = instruction[15:11];  
    assign immediate = instruction[15:0];
    assign sa = instruction[10:6];
    assign Func=instruction[5:0];

endmodule

Alu模块

module Alu(
input Alu_SrcA,
    input Alu_SrcB,
    input [31 :0] ReadData1,//操作数1
    input [31 :0] ReadData2,//操作数2
    input [4:0] sa,
    input [31:0] extend,
    input [3:0] Alu_Op,//操作
    output  reg zero,
    output  reg[31 :0] Alu_Result//结果
    );
    reg [31:0] Alu_Src1;
    reg [31:0] Alu_Src2;
    always@(*)
    begin
        Alu_Src1 = (Alu_SrcA == 0) ? ReadData1 : sa;
        Alu_Src2 = (Alu_SrcB == 0) ? ReadData2 : extend;
        //位运算中负数以补码形式参加
        if(Alu_Op==4'b0001)//无符号加法 
            Alu_Result<=Alu_Src1+Alu_Src2;
        else if(Alu_Op==4'b0010)//无符号减法
            Alu_Result<=Alu_Src1-Alu_Src2;
        else if(Alu_Op==4'b0011)//有符号比较,小于置位1
            Alu_Result<=(((ReadData1 < ReadData2) && (ReadData1[31] == ReadData2[31] )) ||( ( ReadData1[31] ==1 && ReadData2[31] == 0))) ? 1:0;
        else if(Alu_Op==4'b0100)//按位与
            Alu_Result<=Alu_Src1&Alu_Src2;
        else if(Alu_Op==4'b0101)//按位或非
            Alu_Result<=~(Alu_Src1|Alu_Src2);
        else if(Alu_Op==4'b0110)//按位或
            Alu_Result<=(Alu_Src1|Alu_Src2);
        else if(Alu_Op==4'b0111)//按位异或
            Alu_Result<=(Alu_Src1^Alu_Src2);
        else if(Alu_Op==4'b1000)//逻辑左移
            Alu_Result<=Alu_Src2<<Alu_Src1;
        else if(Alu_Op==4'b1001)//逻辑右移
            Alu_Result<=Alu_Src2>>Alu_Src1;
        else Alu_Result<=31'b0;    
           zero=(Alu_Result==0)?1:0;
    end
     
endmodule

DataMemory

module DataMemory(
    input clk,
    input wenr,//读使能
    input wenw,//写使能
    input DBDataSrc,//MemtoReg数据保存的选择端,为0来自ALU运算结果的输出,为1来自数据寄存器(Data MEM)的输出 
    input [31:0] DAddr,//若为LW指令则DAddr=aluResult
    input [31:0] DataIn,
    output reg[31:0]DataOut,
    output reg[31:0] DB,
    input [31:0] test_addr,
    output reg[31:0] test_data
    );
    initial begin
    DB<=16'b0;
    end
    reg[31:0]ram[255:0];
    integer i;
    initial begin
    for(i=0;i<=31;i=i+1)
        begin
        ram[i]=0;
        end
    end
    //写使能,地址不为0,
    always@(wenr or DAddr or DBDataSrc)
    begin
        //读
        DataOut[31:0] = wenr ? ram[DAddr] : 32'bz; // z 为高阻态     

        DB = (DBDataSrc == 0) ? DAddr : DataOut;
    end
    always@(*)
    begin
        //测试
        test_data[31:0] = ram[test_addr];
    end
    always@(posedge clk)
    begin   
        //写
        if(wenw)
            begin
                ram[DAddr] = DataIn[31:0];    
            end
        //$display("mwr: %d $12 %d %d %d %d", mWR, ram[12], ram[13], ram[14], ram[15]);
    end
endmodule

ControlUnit

module ControlUnit(
    input [5:0] opCode,
    input zero,
    input [5:0] Func,
    output reg PCWre,//=1,PC可变
    output reg AluSrcA,
    output reg AluSrcB,    
    output reg DBDataSrc,//数据保存的选择端,为0来自ALU运算结果的输出,为1来自数据寄存器(Data MEM)的输出  
    output reg RegWre,
    
    output reg mRD,//数据存储器的读使能
    output reg mWR,//数据存储器的写使能
    output reg ExtSel,//立即数扩展
    output reg RegDst,//写寄存器组寄存器的地址,为0的时候地址来自rt,为1的时候地址来自rd
    output reg [1:0]PCSrc,//控制PC的
    output reg [3:0]Alu_Op
    );
   initial begin
        PCWre=1;
         mRD=0;
         mWR=0;
         DBDataSrc=0;
   end
   always@(*)
   begin
       PCWre = (opCode == 6'b111111) ? 0 : 1;   //halt
        mWR = (opCode == 6'b101011) ? 1 : 0;     //写存储器使能,sw,寄存器->存储器
        mRD = (opCode == 6'b100011) ? 1 : 0;     //读使能,lw存储器->寄存器
        DBDataSrc = (opCode == 6'b100011) ? 1 : 0;
        if(opCode==6'b000000&&Func==6'b100001)//ADDU 1
        begin
             ExtSel = 0;
             RegDst = 1;
             RegWre = 1;
             AluSrcA = 0;
             AluSrcB = 0;
             PCSrc = 2'b00;
             Alu_Op = 4'b0001;
        end
        else if(opCode==6'b000000&&Func==6'b100011)//SUBU 2
        begin
            ExtSel = 0;
             RegDst = 1;
             RegWre = 1;
             AluSrcA = 0;
             AluSrcB = 0;
             PCSrc = 2'b00;
             Alu_Op = 4'b0010;
        end
        else if(opCode==6'b000000&&Func==6'b101010)//SLT 3
        begin
             ExtSel = 0;
             RegDst = 1;
             RegWre = 1;
             AluSrcA = 0;
             AluSrcB = 0;
             PCSrc = 2'b00;
             Alu_Op = 4'b0011;
        end
        else if(opCode==6'b000000&&Func==6'b100100)//AND 4
        begin
             ExtSel = 0;
             RegDst = 1;
             RegWre = 1;
             AluSrcA = 0;
             AluSrcB = 0;
             PCSrc = 2'b00;
             Alu_Op = 4'b0100;
        end
        else if(opCode==6'b000000&&Func==6'b100111)//NOR 5
        begin
             ExtSel = 0;
             RegDst = 1;
             RegWre = 1;
             AluSrcA = 0;
             AluSrcB = 0;
             PCSrc = 2'b00;
             Alu_Op = 4'b0101;
        end
        else if(opCode==6'b000000&&Func==6'b100101)//OR 6
        begin
            ExtSel = 0;
             RegDst = 1;
             RegWre = 1;
             AluSrcA = 0;
             AluSrcB = 0;
             PCSrc = 2'b00;
             Alu_Op = 4'b0110;
        end
        else if(opCode==6'b000000&&Func==6'b100110)//XOR 7
        begin
             ExtSel = 0;
             RegDst = 1;
             RegWre = 1;
             AluSrcA = 0;
             AluSrcB = 0;
             PCSrc = 2'b00;
             Alu_Op = 4'b0111;
        end
        else if(opCode==6'b000000&&Func==6'b000000)//SLL 8
        begin
             ExtSel = 0;
             RegDst = 1;
             RegWre = 1;
             AluSrcA = 1;
             AluSrcB = 0;
             PCSrc = 2'b00;
             Alu_Op = 4'b1000;
        end
        else if(opCode==6'b000000&&Func==6'b000010)//SRL 9
        begin
             ExtSel = 0;
             RegDst = 1;
             RegWre = 1;
             AluSrcA = 1;
             AluSrcB = 0;
             PCSrc = 2'b00;
             Alu_Op = 4'b1001;
        end
        else if(opCode==6'b001001)//ADDIU 10
        begin
             ExtSel = 1;
             RegDst = 0;
             RegWre = 1;
             AluSrcA = 0;
             AluSrcB = 1;
             PCSrc = 2'b00;
             Alu_Op = 4'b0001;

        end
        else if(opCode==6'b000100)//BEQ 11
        begin
             ExtSel = 1;
             RegDst = 0;
             RegWre = 0;
             AluSrcA = 0;
             AluSrcB = 0;
             PCSrc = zero ? 2'b01 : 2'b00;
             Alu_Op = 4'b0010;//减法判断是否相
        end
        else if(opCode==6'b000101)//BNE 12
        begin
             ExtSel = 1;
             RegDst = 0;
             RegWre = 0;
             AluSrcA = 0;
             AluSrcB = 0;
             PCSrc = zero ? 2'b00 : 2'b01;
             Alu_Op = 4'b0010;//减法判断是否相
        end
        else if(opCode==6'b100011)//LW读存储器 13
        begin
             ExtSel = 1;
             RegDst = 0;
             RegWre = 1;
             AluSrcA = 0;
             AluSrcB = 1;
             PCSrc = 2'b00;
             Alu_Op = 4'b0001;
        end
        else if(opCode==6'b101011)//SW写存储器 14
        begin
             ExtSel = 1;
             RegDst = 0;
             RegWre = 0;
             AluSrcA = 0;
             AluSrcB = 1;
             PCSrc = 2'b00;
             Alu_Op = 4'b0001;
        end
        else if(opCode==6'b000010)//J型直接跳转 15
        begin
            ExtSel=0;
            RegDst=0;
            RegWre=0;
            AluSrcA=0;
            AluSrcB=0;
            PCSrc=2'b10;
            Alu_Op=0;
        end
        else
        begin
            ExtSel=0;
            RegDst=0;
            RegWre=0;
            AluSrcA=0;
            AluSrcB=0;
            PCSrc=2'b11;
            Alu_Op=0;
        end
        

   end
endmodule

旧的xdc

#鏃堕挓淇″彿杩炴帴
set_property PACKAGE_PIN AC19 [get_ports clk]

#鑴夊啿寮?鍏筹紝鐢ㄤ簬杈撳叆浣滀负澶嶄綅淇″彿锛屼綆鐢靛钩鏈夋晥
set_property PACKAGE_PIN Y3 [get_ports resetn]
#led鐏繛鎺ワ紝鐢ㄤ簬杈撳嚭




set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports resetn]


#瑙︽懜灞忓紩鑴氳繛鎺?
set_property PACKAGE_PIN J25 [get_ports lcd_rst]
set_property PACKAGE_PIN H18 [get_ports lcd_cs]
set_property PACKAGE_PIN K16 [get_ports lcd_rs]
set_property PACKAGE_PIN L8 [get_ports lcd_wr]
set_property PACKAGE_PIN K8 [get_ports lcd_rd]
set_property PACKAGE_PIN J15 [get_ports lcd_bl_ctr]
set_property PACKAGE_PIN H9 [get_ports {lcd_data_io[0]}]
set_property PACKAGE_PIN K17 [get_ports {lcd_data_io[1]}]
set_property PACKAGE_PIN J20 [get_ports {lcd_data_io[2]}]
set_property PACKAGE_PIN M17 [get_ports {lcd_data_io[3]}]
set_property PACKAGE_PIN L17 [get_ports {lcd_data_io[4]}]
set_property PACKAGE_PIN L18 [get_ports {lcd_data_io[5]}]
set_property PACKAGE_PIN L15 [get_ports {lcd_data_io[6]}]
set_property PACKAGE_PIN M15 [get_ports {lcd_data_io[7]}]
set_property PACKAGE_PIN M16 [get_ports {lcd_data_io[8]}]
set_property PACKAGE_PIN L14 [get_ports {lcd_data_io[9]}]
set_property PACKAGE_PIN M14 [get_ports {lcd_data_io[10]}]
set_property PACKAGE_PIN F22 [get_ports {lcd_data_io[11]}]
set_property PACKAGE_PIN G22 [get_ports {lcd_data_io[12]}]
set_property PACKAGE_PIN G21 [get_ports {lcd_data_io[13]}]
set_property PACKAGE_PIN H24 [get_ports {lcd_data_io[14]}]
set_property PACKAGE_PIN J16 [get_ports {lcd_data_io[15]}]
set_property PACKAGE_PIN L19 [get_ports ct_int]
set_property PACKAGE_PIN J24 [get_ports ct_sda]
set_property PACKAGE_PIN H21 [get_ports ct_scl]
set_property PACKAGE_PIN G24 [get_ports ct_rstn]

set_property IOSTANDARD LVCMOS33 [get_ports lcd_rst]
set_property IOSTANDARD LVCMOS33 [get_ports lcd_cs]
set_property IOSTANDARD LVCMOS33 [get_ports lcd_rs]
set_property IOSTANDARD LVCMOS33 [get_ports lcd_wr]
set_property IOSTANDARD LVCMOS33 [get_ports lcd_rd]
set_property IOSTANDARD LVCMOS33 [get_ports lcd_bl_ctr]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[11]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[12]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[13]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[14]}]
set_property IOSTANDARD LVCMOS33 [get_ports {lcd_data_io[15]}]
set_property IOSTANDARD LVCMOS33 [get_ports ct_int]
set_property IOSTANDARD LVCMOS33 [get_ports ct_sda]
set_property IOSTANDARD LVCMOS33 [get_ports ct_scl]
set_property IOSTANDARD LVCMOS33 [get_ports ct_rstn]

功能仿真

tb

`timescale 1ns / 1ps
module tb;
    //inputs
    reg clk;
    reg Reset;
    reg [31:0]test_addr;
    wire [31:0]test_data;
    reg [4:0]test_addr1;
    wire [31:0]test_data1;

    SingleCycleCPU ins(
        .clk(clk),
        .Reset(Reset),
      
       
        .test_addr(test_addr),
        .test_data(test_data),
        
        .test_addr1(test_addr1),
        .test_data1(test_data1)
    );
    initial begin
    clk=1;
    Reset=0;
    test_addr=1;
    test_addr1=31;
    #10
    Reset=1;
    #180
    test_addr=1;
    #2
    test_addr=2;
    #2
    test_addr=3;
    #2
    test_addr=4;
    #2
    test_addr=5;
    #2
    test_addr=6;
    #2
    test_addr=7;
    #2
    test_addr=8;
    #576
    test_addr=1;
    #2
    test_addr=2;
    #2
    test_addr=3;
    #2
    test_addr=4;
    #2
    test_addr=5;
    #2
    test_addr=6;
    #2
    test_addr=7;
    #2
    test_addr=8;
    #496
    test_addr=1;
    #2
    test_addr=2;
    #2
    test_addr=3;
    #2
    test_addr=4;
    #2
    test_addr=5;
    #2
    test_addr=6;
    #2
    test_addr=7;
    #2
    test_addr=8;
    #416
    test_addr=1;
    #2
    test_addr=2;
    #2
    test_addr=3;
    #2
    test_addr=4;
    #2
    test_addr=5;
    #2
    test_addr=6;
    #2
    test_addr=7;
    #2
    test_addr=8;
    #336
    test_addr=1;
    #2
    test_addr=2;
    #2
    test_addr=3;
    #2
    test_addr=4;
    #2
    test_addr=5;
    #2
    test_addr=6;
    #2
    test_addr=7;
    #2
    test_addr=8;
    #256
    test_addr=1;
    #2
    test_addr=2;
    #2
    test_addr=3;
    #2
    test_addr=4;
    #2
    test_addr=5;
    #2
    test_addr=6;
    #2
    test_addr=7;
    #2
    test_addr=8;
    #176
    test_addr=1;
    #2
    test_addr=2;
    #2
    test_addr=3;
    #2
    test_addr=4;
    #2
    test_addr=5;
    #2
    test_addr=6;
    #2
    test_addr=7;
    #2
    test_addr=8;
    
    #96
    test_addr=1;
    #2
    test_addr=2;
    #2
    test_addr=3;
    #2
    test_addr=4;
    #2
    test_addr=5;
    #2
    test_addr=6;
    #2
    test_addr=7;
    #2
    test_addr=8;
    test_addr1=31;
    #8000
    test_addr=1;
    #2
    test_addr=2;
    #2
    test_addr=3;
    #2
    test_addr=4;
    #2
    test_addr=5;
    #2
    test_addr=6;
    #2
    test_addr=7;
    #2
    test_addr=8;
    end
   always #5 clk = ~clk;
endmodule

上板验证

在这里插入图片描述

思考

这个代码不是一次就跑成了的,在旧板子和新板子上,第一次都没跑成功,去请教了上一届的一位学长,学长说是数组可能超限,把一个大小为5的数组改成6就过了。按照学长说的把5改6果然过了,但是我还是不明白为什么超限,我觉得我的逻辑结构是没有问题的,后来又把6改成5(和一开始的代码一样了),结果也过了。我觉得我的代码是没问题的,这个板子就很迷惑,不稳定感觉,毕竟不是学电子的,还是不知道到底是哪里的问题。

  • 9
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 单周期 CPU 设计与实现是一种基于单指令的 CPU 架构,它的特点是每个指令的执行时间相同,即一个时钟周期。这种设计简单易懂,但效率较低,因为每个指令都需要占用一个时钟周期,无法实现指令流水线和乱序执行等高级优化技术。 ### 回答2: 单周期 CPU 是计算机的一种设计方式,主要是为了实现简单而高效的执行过程。单周期 CPU 的核心思想是每一条指令只需要完成一个时钟周期,可靠性高且可维护性好,每条指令都有一个预分配的时钟周期,这种方法会带来额外的负担和延迟,同时还有占用额外资源的风险。而单指令 CPU 设计是在单周期 CPU 基础上的一种改进,它通过限制计算机的功能,使得每一条指令都具有高度相似的指令格式和执行过程。这种设计方式,有很多的优点,使得它能够更加灵活适应各种不同的需求。 单指令 CPU 设计最重要的优点是它比较容易实现,因为所有指令都具有相似的执行过程,硬件设计也就比较简单,可以节省大量的成本和时间。同时,由于指令格式的统一,程序员将更容易编写出清晰和可读性较高的代码,也有助于减少不同指令间的对齐限制等问题。此外,由于单指令 CPU 可以根据需求动态配置,因此可以适应不同的应用环境,比如平面图形、音效处理等。因此,单指令 CPU 执行效率比较低,但它的灵活性却是非常好的。 对于单指令 CPU 的实现,主要需要考虑硬件的设计.硬件中要求处理器尽快完成运算,以达到更高的执行速度,同时要保证所耗费的位数不会影响运算结果。为了实现这些目标,有很多种方法可以用于设计和实现。计算机工程师可以借助数字逻辑、逆向工程、调试技术等一系列工具,较为轻松地完成实现。但是,由于单指令 CPU 的原理和设计都比较简单,可能无法满足更复杂的计算需求,在这种情况下,工程师会尝试更高级别的计算机设计技术,比如微处理器或高级计算系统,以实现更高性能的计算机系统。 总的来说,单指令 CPU 是一种比较特殊的设计方式,具有一定的优点和缺点,不同场景的计算需求也会影响该方法的实现方式。计算机设计师可以根据实际情况选择不同的设计策略,以满足不同的性能和实现需求。 ### 回答3: 随着计算机科技的不断进步,单周期CPU被认为是计算机结构设计的最基础单元之一。在单周期CPU中,每个指令在一个时钟周期内执行完成,因此称之为单指令CPU。接下来,我们将深入探讨单周期CPU设计和实现,并对其优缺点进行比较。 单指令CPU设计针对的是简单指令集架构。在这个架构中,每个指令都是通过单个指令来完成的。对于指令集中所包含的每个指令,单指令CPU均为其分配一个固定的时钟周期。但是这种方案的缺点在于,不同指令所需要的时钟周期数是不同的,因此,在执行某些指令时,CPU会在执行完其本身所需要的时钟周期之后等待更多的时钟周期,直到总时钟周期数等于该指令的时钟周期数,这会浪费很多时间。 此外,在单指令CPU中,所有指令均以相同的速率运行,即使某些指令可能需要更多的时间来完成。尽管如此,在多数情况下,单指令CPU的优点在于其设计简单、易于理解和实现。 当谈到单周期CPU的实现时,一般情况下它被分为五个主要的阶段,即指令获取、指令解码、执行操作、访问存储和写回。指令获取阶段的目的是从内存中获取将要执行的指令。在指令解码阶段,CPU会解码指令,理解其意义以及所需要的具体操作。在执行操作阶段,CPU需要根据指令类型执行各种不同的操作,如算术、逻辑和分支操作等。在访问存储阶段,CPU会根据指令类型读取或写入存储器。最后,在写回阶段,结果将会被写入通用寄存器,供后续的指令使用。 在单指令CPU的优缺点方面,由于其简单性,单指令CPU通常比多指令CPU更低成本。此外,由于其设计简单、易于理解和实现,单指令CPU在启动时通常需要很少的时间。然而,由于单指令CPU的每个指令都需要相同的时钟周期,因此在执行某些指令时效率可能会较低。 综上所述,单周期CPU设计和实现是计算机结构设计中最为基础的部分,但它并不是最优解。单指令CPU的优缺点主要取决于具体情况下所需求解的问题。如果要求计算机系统运行速度更快,关键在于将每个指令的执行时间限制在最短时间内。如果要求计算机系统设计更加简单和稳定,单指令CPU则是更适合的选择。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值