数字逻辑实验:Vivado设计单周期RISC-V处理器

从子模块开始,按照向上的逻辑依次展示每一个模块代码如下:

immprocess.sv:根据immpro的控制信号处理立即数

module immprocess(input logic[31:0]instr,
                  input logic[2:0]immpro,
                  output logic[31:0]y);
	always_comb
	   case(immpro)
	       3'b001:y={{20{instr[31]}},instr[31:20]};
	       3'b010:y={{20{instr[31]}},instr[31:25],instr[11:7]};
	       3'b011:y={{19{instr[31]}},instr[31],instr[7],instr[30:25],instr[11:8],1'b0};
	       3'b100:y={instr[31:12],12'b0};
	       3'b101:y={{11{instr[31]}},instr[31],instr[19:12],instr[20],instr[30:21],1'b0};
	       default:y=32'b0;
	   endcase
endmodule

adder.sv:一个加法器

module adder(input logic[31:0]a,
             input logic[31:0]b,
             output logic[31:0]y);
	assign y = a+b;
endmodule

mux2.sv:一个2:1的选择器

module mux2#(parameter WIDTH = 8)
            (input logic[WIDTH-1:0]d0,
             input logic[WIDTH-1:0]d1,
             input logic s,
             output logic[WIDTH-1:0]y);
	assign y = s?d1:d0;
endmodule

flopr.sv:处理下一个PC的模块

module flopr#(parameter WIDTH = 8)
             (input logic clk,
              input logic reset,
              input logic[WIDTH-1:0]d,
              output logic[WIDTH-1:0]q);
	
	always_ff@(posedge clk,posedge reset)
		if (reset)
			q <= 0;
		else
			q <= d;
endmodule

regfile.sv:寄存器文件,对寄存器进行操作

module regfile(input logic clk,
               input logic we3,
               input logic[4:0] ra1,
               input logic[4:0] ra2,
               input logic[4:0] wa3,
               input logic[31:0]wd3,
               output logic[31:0]rd1,
               output logic[31:0]rd2,
               output logic[31:0]rf[31:0]
               );

	//three ported register file
	// read two ports combinationally
	// write third port on rising edge of clk
	// register 0 hardwired to0
	// note:for pipelined processor,write third port on falling edge of clk
	always_ff@(posedge clk)
		if (we3)
			rf[wa3] <= wd3;
	assign rd1 = (ra1!= 0)?rf[ra1]:0;
	assign rd2 = (ra2!= 0)?rf[ra2]:0;
endmodule

alu.sv:根据alucontrol的信号决定alu进行何种运算

module alu(input logic [31:0] srca,
           input logic [31:0] srcb,
           input logic [3:0] alucontrol,
           output logic [31:0] aluout,
           output logic zero,
           output logic smaller);
	always_comb
		case (alucontrol)
			4'b0010: aluout  = srca + srcb;
			4'b0110: aluout  = srca - srcb;
			4'b0000: aluout  = srca & srcb;
			4'b0001: aluout  = srca | srcb;
			4'b0111: aluout  = (srca < srcb) ? 32'd1 : 32'd0;
			4'b0011: aluout  = srca >> srcb;
			4'b0100: aluout  = srca << srcb;
			4'b0101: aluout  = srca ^ srcb;
			4'b1000: aluout  = srca >>> srcb;
			default: aluout = 32'b0;
		endcase
	assign zero = (aluout == 32'b0);
	assign smaller = (srca < srcb);

endmodule

datapath.sv:包含对alu与register整体处理的模块

module datapath(input logic clk,                                             
                input logic reset,
                input logic memtoreg,
                input logic branch_beq,
                input logic branch_bne,
                input logic branch_blt,
                input logic alusrc,
                input logic regwrite,
                input logic jump,
                input logic [3:0]alucontrol,
                input logic [2:0]immpro,
                input logic isonlyimm,
                output logic [31:0] pc,
                input logic [31:0] instr,
                output logic [31:0] aluout,
                output logic [31:0] writedata,
                input logic [31:0] readdata,
                output logic[31:0]rf[31:0]
                );
	

	logic[31:0]pcnext,pcnextbr_beq,pcnextbr_bne,pcnextbr_blt,pcplus4,pcbranch;
	logic[31:0]signimm;
	logic[31:0]srca,srcb;
	logic[31:0]result_1,result;
	logic zero,pcsrc_beq,pcsrc_bne,pcsrc_blt,smaller;
	
	assign pcsrc_beq=zero & branch_beq;
	assign pcsrc_bne=(~zero) & branch_bne;
	assign pcsrc_blt=smaller & branch_blt;
	
	immprocess immp(.instr(instr),
                    .immpro(immpro),
                    .y(signimm));
                    
	adder pcadd1(
		.a(pc),
		.b(32'b100),
		.y(pcplus4)
	);
	
	adder pcadd2(
		.a(pc),
		.b(signimm),
		.y(pcbranch)
	);

	mux2#(.WIDTH(32)) pcbrmux_beq(
		.d0(pcplus4),
		.d1(pcbranch),
		.s(pcsrc_beq),
		.y(pcnextbr_beq)
	);
	
	mux2#(.WIDTH(32)) pcbrmux_bne(
		.d0(pcnextbr_beq),
		.d1(pcbranch),
		.s(pcsrc_bne),
		.y(pcnextbr_bne)
	);
	
	mux2#(.WIDTH(32)) pcbrmux_blt(
		.d0(pcnextbr_bne),
		.d1(pcbranch),
		.s(pcsrc_blt),
		.y(pcnextbr_blt)
	);
	
	mux2#(.WIDTH(32)) pcmux(
		.d0(pcnextbr_blt),
		.d1(pcbranch),
		.s(jump),
		.y(pcnext)
	);
	
	//nextPC logic
	flopr#(.WIDTH(32)) pcreg(
		.clk(clk),
		.reset(reset),
		.d(pcnext),
		.q(pc)
	);
	
	regfile rfile(
		.clk(clk),
		.we3(regwrite),
		.ra1(instr[19:15]),
		.ra2(instr[24:20]),
		.wa3(instr[11:7]),
		.wd3(result),
		.rd1(srca),
		.rd2(writedata),
		.rf(rf)
	);
	
	//ALU logic
	mux2#(.WIDTH(32)) srcbmux(
		.d0(writedata),
		.d1(signimm),
		.s(alusrc),
		.y(srcb)
	);

    alu alu(
		.srca(srca),
		.srcb(srcb),
		.alucontrol(alucontrol),
		.aluout(aluout),
		.zero(zero),
		.smaller(smaller)
	);
	
	// register file logic
	
	mux2#(.WIDTH(32)) resmux(
		.d0(aluout),
		.d1(readdata),
		.s(memtoreg),
		.y(result_1)
	);
	
	mux2#(.WIDTH(32)) resimm(
		.d0(result_1),
		.d1(signimm),
		.s(isonlyimm),
		.y(result)
	);
	
endmodule

controller.sv:控制器,根据输入的机器码决定一系列控制信号

module controller(input logic [6:0]opcode,
                  input logic [6:0]funct7,
                  input logic [2:0]funct3,
                  output logic [2:0]immpro,
                  output logic isonlyimm,
                  output logic memtoreg,
                  output logic memwrite,
                  output logic branch_beq,
                  output logic branch_bne,
                  output logic branch_blt,
                  output logic alusrc,
                  output logic regwrite,
                  output logic jump,
                  output logic [3:0]alucontrol
                );
	logic [15:0]controls;
	always_comb
		case(opcode)
			7'b0110011://处理R指令
                case(funct7)
                     7'b0000000:
                         case(funct3)
                             3'b000:controls=16'b1_0_0_0_0_0_0_0_0010_000_0;//add
                             3'b001:controls=16'b1_0_0_0_0_0_0_0_0100_000_0;//sll
                             3'b010:controls=16'b1_0_0_0_0_0_0_0_0111_000_0;//slt
                             3'b100:controls=16'b1_0_0_0_0_0_0_0_0101_000_0;//xor
                             3'b101:controls=16'b1_0_0_0_0_0_0_0_0011_000_0;//srl
                             3'b110:controls=16'b1_0_0_0_0_0_0_0_0001_000_0;//or
                             3'b111:controls=16'b1_0_0_0_0_0_0_0_0000_000_0;//and
                             default:controls=16'bx_x_x_x_x_x_x_x_xxxx_xxx_x;
                         endcase
                     7'b0100000:
                         case(funct3)
                             3'b000:controls=16'b1_0_0_0_0_0_0_0_0110_000_0;//sub
                             3'b101:controls=16'b1_0_0_0_0_0_0_0_1000_000_0;//sra
                             default:controls=16'bx_x_x_x_x_x_x_x_xxxx_xxx_x;
                         endcase
                     default:controls=16'bx_x_x_x_x_x_x_x_xxxx_xxx_x;
                 endcase
             7'b0010011://第一类I指令
                 case(funct3)
                     3'b000:controls=16'b1_1_0_0_0_0_0_0_0010_001_0;//addi
                     3'b110:controls=16'b1_1_0_0_0_0_0_0_0001_001_0;//ori
                     3'b111:controls=16'b1_1_0_0_0_0_0_0_0000_001_0;//andi
                     default:controls=16'bx_x_x_x_x_x_x_x_xxxx_xxx_x;
                 endcase
             7'b0000011://lw指令
                controls=16'b1_1_0_0_0_0_1_0_0010_001_0;//lw
             7'b0100011://sw指令
                controls=16'b0_1_0_0_0_1_0_0_0010_010_0;//sw
             7'b1100111://jalr指令
                controls=16'b1_1_0_0_0_0_0_1_0010_001_0;//jalr
             7'b1100011://B指令
                case(funct3)
                    3'b000:controls=16'b0_0_1_0_0_0_0_0_0110_011_0;//beq
                    3'b001:controls=16'b0_0_0_1_0_0_0_0_0110_011_0;//bne
                    3'b100:controls=16'b0_0_0_0_1_0_0_0_0110_011_0;//blt
                    default:controls=16'bx_x_x_x_x_x_x_x_xxxx_xxx_x;
                endcase
             7'b1101111://J指令
                controls=16'b0_0_0_0_0_0_0_1_0010_101_0;//jal
             7'b0110111:
                controls=16'b1_1_0_0_0_0_0_0_0010_100_1;//lui
             default:controls=16'bx_x_x_x_x_x_x_x_xxxx_xxx_x;
         endcase 
         
    assign {regwrite,alusrc,branch_beq,branch_bne,branch_blt,memwrite,memtoreg,jump,alucontrol,immpro,isonlyimm} = controls; 
      		         
endmodule

risc.sv:单周期RISC-V处理器对机器码处理整体实现

module risc(input logic clk,
            input logic reset,
            output logic[31:0]pc,
            input logic[31:0]instr,
            output logic memwrite,
            output logic[31:0]aluout,
            output logic[31:0]writedata,
            input logic[31:0]readdata,
            output logic[31:0]rf[31:0])
            ;
	
	logic memtoreg,alusrc,regwrite,jump,branch_beq,branch_bne,branch_blt,isonlyimm;
	logic [3:0]alucontrol;
	logic [2:0]immpro;
	
	controller c(
		.opcode(instr[6:0]),
		.funct7(instr[31:25]),
		.funct3(instr[14:12]),
		.immpro(immpro),
		.isonlyimm(isonlyimm),
		.memtoreg(memtoreg),
		.memwrite(memwrite),
        .branch_beq(branch_beq),
        .branch_bne(branch_bne),
		.alusrc(alusrc),
		.regwrite(regwrite),
		.jump(jump),
		.alucontrol(alucontrol),
		.branch_blt(branch_blt)
	);
	
	datapath dp(
		.clk(clk),
		.reset(reset),
		.memtoreg(memtoreg),
	    .branch_beq(branch_beq),
	    .branch_bne(branch_bne),
	    .branch_blt(branch_blt),
		.alusrc(alusrc),
		.regwrite(regwrite),
		.jump(jump),
		.alucontrol(alucontrol),
		.immpro(immpro),
		.isonlyimm(isonlyimm),
		.pc(pc),
		.instr(instr),
		.aluout(aluout),
		.writedata(writedata),
		.readdata(readdata),
		.rf(rf)
	);
endmodule

imem.sv:指令存储器

module imem(input logic[5:0] a,
            output logic[31:0]rd);
/*
logic[31:0]RAM[63:0];
initial
	$readmemh("C:\Users\DELL\Desktop\单周期RISC-V处理器设计\memfile.dat",RAM);
*/
// 不要声明很大的数组,FPGA板子放不下

//基本测试,用于跑simulation出一个较好的波形图

logic[31:0]RAM[0:18] = { // 注意!指令存储器容量最多只有64个字!
32'h00500113,
32'h00c00193,
32'hff718393,
32'h0023e233,
32'h0041f2b3,
32'h004282b3,
32'h02728663,
32'h0041a233,
32'h00020463,
32'h00000293,
32'h0023a233,
32'h005203b3,
32'h402383b3,
32'h0471a223,
32'h05002103,
32'h008000ef,
32'h00100113,
32'h04202a23,
32'hfe000ee3	// beq $0,$0,self,跳转到自己,终止执行后续指令
};

/*
//求1到100和的测试,用于跑BASYS板子
logic[31:0]RAM[0:11] = { // 注意!指令存储器容量最多只有64个字!
32'h000003b7,
32'h00038393,
32'h00000437,
32'h06340413,
32'h000004b7,
32'h00048493,
32'h00944863,
32'h00148493,
32'h009383b3,
32'hff5ff0ef,
32'h04702a23,
32'hfe000ee3    // beq $0,$0,self,跳转到自己,终止执行后续指令
};
*/

assign rd = RAM[a]; // 注意!指令存储器容量最多只有64个字!
endmodule

dmem.sv:数据存储器

module dmem(input logic clk,
            input logic we,
            input logic[31:0]a,
            input logic[31:0]wd,
            output logic[31:0]rd);
	
	// 不要声明很大的数组,FPGA板子放不下
	logic[31:0]RAM[63:0];	// 注意!数据存储器容量最多只有64个字!
	assign rd = RAM[a[7:2]]; // word aligned
	
	always_ff@(posedge clk)
		if (we)
			RAM[a[7:2]] <= wd;
endmodule

以上是所必需的基本模块,下面的模块分别用于跑板子和跑simulation。

(一)跑simulation所需的模块:

top.sv:用于跑simulation的顶层模块

module top(input logic clk,
			input logic reset,
			output logic success_led,
			output logic fail_led,
			output logic[31:0] pc
	);
	logic[31:0]readdata,instr,dataadr,writedata;
	logic memwrite;
	logic[31:0]rf[31:0];

	//instantiate processor and memories
	imem imem(
		.a(pc[7:2]),
		.rd(instr)
	);
	risc risc(
		.clk(clk),
		.reset(reset),
		.pc(pc),
		.instr(instr),
		.memwrite(memwrite),
		.aluout(dataadr),
		.writedata(writedata),
		.readdata(readdata),
		.rf(rf)
	);
	dmem dmem(
		.clk(clk),
		.we(memwrite),
		.a(dataadr),
		.wd(writedata),
		.rd(readdata)
	);
  
	// 加入两个led指示灯。当写入存储器地址84且数据是7时,点亮success_led灯
	// 如果第1次写入的地址不是80,点亮fail_led灯
	always_ff @(posedge clk,posedge reset)
		if (reset)
		begin
			success_led <= 1'b0;
			fail_led <= 1'b0;
		end
		else if (memwrite == 1'b1)
		begin
			if (dataadr == 84 & writedata == 7)
				success_led <= 1'b1;
			else if (dataadr != 80)
				fail_led <= 1'b1;
		end
endmodule

testbench.sv:用于跑simulation的仿真波形图

`timescale 1ns / 1ps

module testbench();
	logic clk;
	logic reset;
	logic success_led;
	logic fail_led;
	logic [31:0]pc;

	// instantiate device to be tested
	top dut(
		.clk(clk),
		.reset(reset),
		.success_led(success_led),
		.fail_led(fail_led),
		.pc(pc)
	);
	
	// initialize test
	initial
	begin
		reset = 1;
		#10;
		reset = 0;
	end
	
	// generate clock to sequence tests
	always
	begin
	clk = 1;
	#1;
	clk = 0;
	#1;
	end
	
	// check results
	always@(posedge clk)
	begin
		if (success_led)
		begin
			$display("Simulation succeeded");
		end
		if (fail_led)
		begin
			$display("Simulation failed");
		end
	end
endmodule

(二)跑板子所需的模块

display_sum.sv:用于让板子显示最后求和得到的结果

`timescale 1ns / 1ps

module display_sum(
        input clk,
        input [31:0]num,
        output logic [10:0] disp_7seg
    ); 
  logic [1:0] sel=0;
  logic [19:0]count=0;
  logic [3:0] num1,num2,num3,num4,disp_number;
  parameter T1MS=50000; 

  always@(posedge clk) 
    begin 
        count<=count+1; 
        if(count==T1MS) 
            begin 
                count<=0; 
                sel<=sel+1; 
                if(sel==4) 
                    sel<=0; 
            end 
    end 
      
  assign num1=num/1000%10;
  assign num2=num/100%10;
  assign num3=num/10%10;
  assign num4=num%10;
  
  always_comb
    case(disp_number)
        4'd0: disp_7seg[6:0] = 7'b0000001;
	    4'd1: disp_7seg[6:0] = 7'b1001111;
		4'd2: disp_7seg[6:0] = 7'b0010010;
		4'd3: disp_7seg[6:0] = 7'b0000110;
		4'd4: disp_7seg[6:0] = 7'b1001100;
		4'd5: disp_7seg[6:0] = 7'b0100100;
		4'd6: disp_7seg[6:0] = 7'b0100000;
		4'd7: disp_7seg[6:0] = 7'b0001111;
		4'd8: disp_7seg[6:0] = 7'b0000000;
		4'd9: disp_7seg[6:0] = 7'b0000100;
		default: disp_7seg[6:0] = 7'b1111111;
	endcase
	
  always_comb 
    case(sel) 
        0: begin disp_7seg[10:7] = 4'b1110; disp_number = num4; end
		1: begin disp_7seg[10:7] = 4'b1101; disp_number = num3; end
		2: begin disp_7seg[10:7] = 4'b1011; disp_number = num2; end
		3: begin disp_7seg[10:7] = 4'b0111; disp_number = num1; end 
		default:begin disp_7seg[10:7] = 4'b1111; disp_number = 4'd0; end 
    endcase 
        
endmodule 
            
        

top_show_sum.sv:跑板子所需的顶层模块

`timescale 1ns / 1ps

module top_show_sum(input logic clk,
			input logic reset,
			output logic [10:0] disp_7seg
	);

	logic[31:0]readdata,instr,pc,dataadr,writedata;
	logic[31:0]rf[31:0];
	logic memwrite;

	//instantiate processor and memories
	imem imem(
		.a(pc[7:2]),
		.rd(instr)
	);
	risc risc(
		.clk(clk),
		.reset(reset),
		.pc(pc),
		.instr(instr),
		.memwrite(memwrite),
		.aluout(dataadr),
		.writedata(writedata),
		.readdata(readdata),
		.rf(rf)
	);
	dmem dmem(
		.clk(clk),
		.we(memwrite),
		.a(dataadr),
		.wd(writedata),
		.rd(readdata)
	);
	display_sum dis(
	    .clk(clk),
	    .num(rf[7]),
	    .disp_7seg(disp_7seg)
	);
	    
endmodule

约束文件(可以根据自己需求自行修改调整):

set_property PACKAGE_PIN W5 [get_ports clk] 
set_property IOSTANDARD LVCMOS33 [get_ports clk] 
set_property PACKAGE_PIN V17 [get_ports reset] 
set_property IOSTANDARD LVCMOS33 [get_ports reset] 

set_property PACKAGE_PIN W4 [get_ports {disp_7seg[10]}] 
set_property PACKAGE_PIN V4 [get_ports {disp_7seg[9]}] 
set_property PACKAGE_PIN U4 [get_ports {disp_7seg[8]}] 
set_property PACKAGE_PIN U2 [get_ports {disp_7seg[7]}] 
set_property PACKAGE_PIN W7 [get_ports {disp_7seg[6]}] 
set_property PACKAGE_PIN W6 [get_ports {disp_7seg[5]}] 
set_property PACKAGE_PIN U8 [get_ports {disp_7seg[4]}] 
set_property PACKAGE_PIN V8 [get_ports {disp_7seg[3]}] 
set_property PACKAGE_PIN U5 [get_ports {disp_7seg[2]}] 
set_property PACKAGE_PIN V5 [get_ports {disp_7seg[1]}] 
set_property PACKAGE_PIN U7 [get_ports {disp_7seg[0]}] 
set_property IOSTANDARD LVCMOS33 [get_ports {disp_7seg[10]}] 
set_property IOSTANDARD LVCMOS33 [get_ports {disp_7seg[9]}] 
set_property IOSTANDARD LVCMOS33 [get_ports {disp_7seg[8]}] 
set_property IOSTANDARD LVCMOS33 [get_ports {disp_7seg[6]}] 
set_property IOSTANDARD LVCMOS33 [get_ports {disp_7seg[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {disp_7seg[5]}] 
set_property IOSTANDARD LVCMOS33 [get_ports {disp_7seg[4]}] 
set_property IOSTANDARD LVCMOS33 [get_ports {disp_7seg[3]}] 
set_property IOSTANDARD LVCMOS33 [get_ports {disp_7seg[1]}] 
set_property IOSTANDARD LVCMOS33 [get_ports {disp_7seg[2]}] 
set_property IOSTANDARD LVCMOS33 [get_ports {disp_7seg[0]}]

PS:(1)注意跑板子与跑仿真图之间切换时,imem.sv中的测试指令集机器码也要切换;

         (2)跑板子时将跑仿真图所需的两个模块(top.sv与testbench.sv)disable掉,跑仿真图时同理;

         (3)板子只会显示最后的计算结果,可以创新让板子显示出每一次迭代后求和的计算结果(在本人下一个“多周期RISC-V处理器实现”中有实现这个效果)

         (4)记得文件路径不要带中文,否则跑不了板子!!!(本人因为这个耗了一晚上时间捏)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值