计算机组成原理cpu数据通路(Verilog HDL虚拟实验)

数据通路的作用

数据在功能部件之间传送的路径称为数据通路,建立数据通路的任务是由“控制部件"来完成的

  • 内部数据通路:CPU内部的数据传送通路,用于在寄存器之间或寄存器ALU之间传送数据。
  • 外部数据通路:一般借助系统总线,将寄存器(MAR和MDR)与存储器和I/O模块连接起来。
  • 内部总线:是指同一部件,如CPU内部连接各寄存器及运算部件之间的总线
  • 系统总线:是指同一台计算机系统的各部件,如CPU、内存、通道和各类I/O接口间互相连接的总线。

一、多周期实现示例

在这里插入图片描述

顶层代码:

`default_nettype none 
module VirtualBoard (
    input  logic  CLOCK,      // 10 MHz Input Clock 
    input  logic [19:0] PB,   // 20 Push Buttons, logical 1 when pressed
    input  logic [35:0] S,    // 36 Switches
    output logic [35:0] L,    // 36 LEDs, drive logical 1 to light up
    output logic  [7:0] SD7,  // 8 common anode Seven-segment Display
    output logic  [7:0] SD6,
    output logic  [7:0] SD5,
    output logic  [7:0] SD4,
    output logic  [7:0] SD3,
    output logic  [7:0] SD2,
    output logic  [7:0] SD1,
    output logic  [7:0] SD0
);

/********* Seven-segment decoder instantiation **********/
logic [3:0] HD[7:0];  // 8 hexadecimal display 
SevenSegDecode ssdecode_inst7(.iData(HD[7]), .oSeg(SD7));
SevenSegDecode ssdecode_inst6(.iData(HD[6]), .oSeg(SD6));
SevenSegDecode ssdecode_inst5(.iData(HD[5]), .oSeg(SD5));
SevenSegDecode ssdecode_inst4(.iData(HD[4]), .oSeg(SD4));
SevenSegDecode ssdecode_inst3(.iData(HD[3]), .oSeg(SD3));
SevenSegDecode ssdecode_inst2(.iData(HD[2]), .oSeg(SD2));
SevenSegDecode ssdecode_inst1(.iData(HD[1]), .oSeg(SD1));
SevenSegDecode ssdecode_inst0(.iData(HD[0]), .oSeg(SD0));

/** The input port is replaced with an internal signal **/
wire reset  = PB[0];
wire clk    = PB[1];
wire [3:0] DATA  = S[3:0];
wire [1:0] INDEX = S[5:4];
wire RFoe   = S[6];
wire GRSoe = S[7];
wire DATAoe= S[8];
wire [3:0] ALUop = S[12:9];
// wire    = S[13];
wire RFce = S[14];
wire PSWce= S[15];
wire GRSce= S[16];
wire RXce = S[17];

/************* The logic of this experiment *************/
//各模块间连线信号
wire [3:0] BUS, RX_Q, F, RF_Q, GRS_Q;
wire [3:0] FLAG, PSW_Q;

//模块实例
ALU #(4) ALU_inst(.iOp(ALUop), .iX(RX_Q), .iY(BUS), .oF(F), .oFlag(FLAG), .Cin(PSW_Q[0]));

GRS #(4) GRS_inst(.iD(BUS), .oQ (GRS_Q), .Load(GRSce), .Clk(clk), .Index(INDEX));

DataReg #(4) RX_inst(.oQ(RX_Q), .iD(BUS), .Clk(clk), .Load(RXce), .Reset(reset));

DataReg #(4) RF_inst(.oQ(RF_Q), .iD(F), .Clk(clk), .Load(RFce), .Reset(reset));

DataReg #(4) PSW_inst(.oQ(PSW_Q), .iD(FLAG), .Clk(clk), .Load(PSWce ), .Reset(reset));

//三态缓冲器逻辑描述
assign BUS = RFoe   ? RF_Q  : 4'bzzzz;
assign BUS = GRSoe  ? GRS_Q : 4'bzzzz;
assign BUS = DATAoe ? DATA  : 4'bzzzz;

/****** Internal signal assignment to output port *******/
assign L[25:22] = PSW_Q;
assign L[21:18] = FLAG;
assign HD[5] = RX_Q;
assign HD[4] = BUS;
assign HD[3] = GRS_Q;
assign HD[1] = RF_Q;
assign HD[0] = F;

endmodule

ALU

module ALU
#(parameter N=4)
(
input wire [N-1:0]iOp,
input wire Cin,
input wire [N-1:0] iX,
input wire [N-1:0] iY ,
output wire [N-1:0] oF,
output wire [N-1:0] oFlag
);
wire [N-1:0]M;
logic [N:0]result;
wire SR;
wire SV;
wire SL;
wire [1:0]SW;


wire [N-1:0] A,B;
wire C0;
always@(iOp[N-1:0])
 begin
  case(iOp[N-1:0])  //F=X;
   4'b0000:begin
	 SW[1:0]=2'b00;  //11
	 M[3:0]=4'b0000;
	 SV=1'b1;
	 
	 SR=1'b0;
	 SL=1'b0;
     end
	4'b0001: begin  //F=X+Y
	 SW[1:0]=2'b00;
	 M[3:0]=4'b0001;
	 SV=1'b1;
	 SR=1'b0;
	 SL=1'b0;
	        end
	4'b0010: begin	//F=X-Y 
	   SW[1:0]=2'b00;
      SV=1'b1;
      M[3:0]=4'b0110;
      SR=1'b0;
	   SL=1'b0;		
				end
	4'b0011:begin     //F=X &Y
	     SV=1'b1;
		  SW[1:0]=2'b01;
		  M[3:0]=4'b0001;
		  SR=1'b0;
		  SL=1'b0;
		  end
	4'b0100:begin   // F=X or Y
	    SV=1'b1;
		 SW[1:0]=2'b10;
		 M[3:0]=4'b0001;
		 SR=1'b0;
		 SL=1'b0;
		 end
	4'b0101:begin       //F=X ^Y
	   SV=1'b1;
		SW[1:0]=2'b11;
		M[3:0]=4'b0001;
		SL=1'b0;
		SR=1'b0;
		end
	4'b0110:begin     //F=X/2
	   SR=1'b1;
		SV=1'b0;
		SL=1'b0;
		SW[1:0]=2'b00;
		M[3:0]=4'b0000;
		end
	4'b0111:begin
	  SL=1'b1;    //F=2X
	  SV=1'b0;
	  SR=1'b0;
	  SW[1:0]=2'b00;
		M[3:0]=4'b0000;
	  end
	 4'b1000:begin  //F=!X
	  SV=1'b1;
	  SW[1:0]=2'b11;
	  M[3:0]=4'b0011;
	  SL=1'b0;
	  SR=1'b0;
	  end
	 4'b1001:begin  //F=X+1
	  SV=1'b1;
	  M[3:0]=4'b0100;
	  SL=1'b0;
	  SR=1'b0;
	  SW[1:0]=2'b00;
	  end
	 4'b1010:begin  //F=X-1
	  SV=1'b1;
	  M[3:0]=4'b0011;
	  SL=1'b0;
	  SR=1'b0;
	  SW[1:0]=2'b00;
	  end
	 4'b1011:begin //F=X+Y+Cin
	  SV=1'b1;
	  M[3:0]=4'b1001;
	  SL=1'b0;
	  SR=1'b0;
	  SW[1:0]=2'b00;
	  end
	  4'b1100:begin  //F=X-Y-Cin
	  SV=1'b1;
	  M[3:0]=4'b1010;
	  SL=1'b0;
	  SR=1'b0;
	  SW[1:0]=2'b00;
	  end
	  default:begin
	  SV=1'b0;
	  M[3:0]=4'b0000;
	  SL=1'b0;
	  SR=1'b0;
	  SW[1:0]=2'bXX;
	  end
	  endcase
	  end
	 
//assign C0 =(Cin & M[3] & M[0]| M[2]);
wire sign, zero, overflow, carryOut;
assign A[3]=SR & iX[3] | iX[3] & SV | SL &iX[2] ;
assign A[2]=SR & iX[3] | iX[2] & SV | SL &iX[1];
assign A[1]=SR & iX[2] | iX[1] & SV | SL &iX[0] ;
assign A[0]=SR & iX[1] | iX[0] & SV | SL &1'b0 ;
assign B[3] =(M[0] & iY[3]) | (M[1] & !iY[3]) ;
assign B[2] =M[0] & iY[2] | M[1] & !iY[2] ;
assign B[1] =M[0] & iY[1] | M[1] & !iY[1] ;
assign B[0] =M[0] & iY[0] | M[1] & !iY[0] ;


always_comb
 begin 
  case({SW[1:0]})
   2'b00: result=A+B+C0;
	2'b01: result=iX & B;
	2'b10: result=iX |B;
	2'b11: result=iX ^ B;
	default:begin
	if(SV==0 & SR==0 & SL==0)
	result={(5){1'bZ}};
	end
	endcase
end

assign carryOut=result[4];
assign oF[3:0] = result[3:0];  
assign sign = oF[3];
always@( SV,SR,SL)
begin
if(SV==0 & SR==0 & SL==0)
 zero=0;
 else
 zero = (oF==0) ? 1 : 0;  // ~|F;
end
assign overflow = (~A[3]) & ~B[3] & oF[3] | (A[3]) & B[3] & ~oF[3] ;


assign oFlag={sign, zero, overflow, carryOut};
endmodule

GRS

module GRS
#(parameter N = 4)
 (
  input wire [N-1:0]iD,
  input wire Load,
  input  wire[1:0]Index,
  input wire Clk,
  output  wire[N-1:0]oQ
  
 );
// 2-4 decode 二四译码器
logic load3, load2, load1, load0;
always_comb begin
    if (Load)
        case (Index)
            2'b00: {load3, load2, load1, load0} = 4'b0001;
            2'b01: {load3, load2, load1, load0} = 4'b0010;
			2'b10: {load3, load2, load1, load0} = 4'b0100;
			2'b11: {load3, load2, load1, load0} = 4'b1000;
            default: {load3, load2, load1, load0} = 4'bx;
        endcase
    else
        {load3, load2, load1, load0} = 4'b0000;
end

// register instantiation 译码器的实例化
logic [N-1:0] R0_Q, R1_Q, R2_Q, R3_Q;
DataReg #(N) R0(.oQ(R0_Q), .iD(iD), .Clk(Clk), .Load(load0), .Reset(1'b0));//由于本实验没有用到复位信号,所以reset恒为0,在待会的三端口寄存器堆里可以将第一个寄存器的信号设置为1使它无法存值
DataReg #(N) R1(.oQ(R1_Q), .iD(iD), .Clk(Clk), .Load(load1), .Reset(1'b0));
DataReg #(N) R2(.oQ(R2_Q), .iD(iD), .Clk(Clk), .Load(load2), .Reset(1'b0));
DataReg #(N) R3(.oQ(R3_Q), .iD(iD), .Clk(Clk), .Load(load3), .Reset(1'b0));

// 4-1 MUX 四选一多路器

always_comb begin
	case (Index)//根据地址信号选择输出哪个寄存器的值
		2'b00: oQ = R0_Q;
		2'b01: oQ = R1_Q;
		2'b10: oQ = R2_Q;
		2'b11: oQ = R3_Q;
	endcase
end
/****** Internal signal assignment to output port *******/

endmodule

二、单周期实现示例

在这里插入图片描述

视频演示

顶层代码:

`default_nettype none 
module VirtualBoard (
    input  logic  CLOCK,      // 10 MHz Input Clock 
    input  logic [19:0] PB,   // 20 Push Buttons, logical 1 when pressed
    input  logic [35:0] S,    // 36 Switches
    output logic [35:0] L,    // 36 LEDs, drive logical 1 to light up
    output logic  [7:0] SD7,  // 8 common anode Seven-segment Display
    output logic  [7:0] SD6,
    output logic  [7:0] SD5,
    output logic  [7:0] SD4,
    output logic  [7:0] SD3,
    output logic  [7:0] SD2,
    output logic  [7:0] SD1,
    output logic  [7:0] SD0
);

/********* Seven-segment decoder instantiation **********/
logic [3:0] HD[7:0];  // 8 hexadecimal display 
SevenSegDecode ssdecode_inst7(.iData(HD[7]), .oSeg(SD7));
SevenSegDecode ssdecode_inst6(.iData(HD[6]), .oSeg(SD6));
SevenSegDecode ssdecode_inst5(.iData(HD[5]), .oSeg(SD5));
SevenSegDecode ssdecode_inst4(.iData(HD[4]), .oSeg(SD4));
SevenSegDecode ssdecode_inst3(.iData(HD[3]), .oSeg(SD3));
SevenSegDecode ssdecode_inst2(.iData(HD[2]), .oSeg(SD2));
SevenSegDecode ssdecode_inst1(.iData(HD[1]), .oSeg(SD1));
SevenSegDecode ssdecode_inst0(.iData(HD[0]), .oSeg(SD0));

/** The input port is replaced with an internal signal **/
wire reset  = PB[0];
wire clk    = PB[1];
wire [1:0] WINDEX = S[5:4];
wire RFoe   = S[6];

wire [1:0]SW =S[13:12];
wire M0 = S[14];

wire [3:0] enter=S[11:8];
 
wire[1:0]RA1=S[1:0];
wire [1:0]RA2=S[3:2];

wire choose =S[7];
/************* The logic of this experiment *************/
//各模块间连线信号
wire [3:0] tempmux,  F, GRS_Q1,GRS_Q2;
wire [3:0] FLAG;

assign tempmux = choose? enter:GRS_Q2 ;
//模块实例
ALU #(4) ALU_inst(.iX(GRS_Q1), .iY(tempmux), .oF(F), .oFlag(FLAG), .M0(M0),.SW(SW));

GRS #(4) GRS_inst(.iD(F),.Load(RFoe),.WIndex(WINDEX),.RIndex1(RA1),.RIndex2(RA2),.Clk(clk),.oQ1 (GRS_Q1), .oQ2(GRS_Q2));

/****** Internal signal assignment to output port *******/


assign L[21:18] = FLAG;
assign HD[1] = GRS_Q1;
assign HD[2] = GRS_Q2;
assign HD[0] = tempmux;
assign HD[3] = F;

endmodule

GRS模块

module GRS
#(parameter N = 4)
 (
  input wire [N-1:0]iD,
  input wire Load,
  input  wire[1:0]WIndex,
  input wire [1:0]RIndex1,
  input wire [1:0]RIndex2,
  input wire Clk,
  output  wire[N-1:0]oQ1,
  output wire [N-1:0]oQ2
  
 );
// 2-4 decode
logic load3, load2, load1, load0;
always_comb begin
    if (Load)
        case (WIndex)
            2'b00: {load3, load2, load1, load0} = 4'b0001;
            2'b01: {load3, load2, load1, load0} = 4'b0010;
			2'b10: {load3, load2, load1, load0} = 4'b0100;
			2'b11: {load3, load2, load1, load0} = 4'b1000;
            default: {load3, load2, load1, load0} = 4'bx;
        endcase
    else
        {load3, load2, load1, load0} = 4'b0000;
end
// register instantiation
logic [N-1:0] R0_Q, R1_Q, R2_Q, R3_Q;
DataReg #(N) R0(.oQ(R0_Q), .iD(iD), .Clk(Clk), .Load(load0), .Reset(1'b1));//这个reset改了
DataReg #(N) R1(.oQ(R1_Q), .iD(iD), .Clk(Clk), .Load(load1), .Reset(1'b0));
DataReg #(N) R2(.oQ(R2_Q), .iD(iD), .Clk(Clk), .Load(load2), .Reset(1'b0));
DataReg #(N) R3(.oQ(R3_Q), .iD(iD), .Clk(Clk), .Load(load3), .Reset(1'b0));

// 4-1 MUX 现在有两个多路器
logic  [N-1:0] GRS_Q1, GRS_Q2;
always_comb begin
	case (RIndex1)
		2'b00: oQ1 = R0_Q;
		2'b01: oQ1 = R1_Q;
		2'b10: oQ1 = R2_Q;
		2'b11: oQ1 = R3_Q;
	endcase
	case (RIndex2)
		2'b00: oQ2 = R0_Q;
		2'b01: oQ2 = R1_Q;
		2'b10: oQ2 = R2_Q;
		2'b11: oQ2 = R3_Q;
	endcase
	end
endmodule

ALU模块

module ALU
#(parameter N=4)
(
input wire [N-1:0] iX,
input wire [N-1:0] iY ,
input wire [1:0]SW,
input wire M0,
output wire [N-1:0] oF,
output wire [N-1:0] oFlag
);
logic [N:0]result;

wire [N-1:0] A,B;
wire C0;
assign C0=M0;
wire sign, zero, overflow, carryOut;
assign A=iX;
assign B=iY ;
always_comb
  begin 
   case({SW[1:0]})
   2'b00: result=A+B^M0+C0;
	2'b01: result=A & B;
	2'b10: result=A|B;
	2'b11: result=A ^ B;
	default:result={(N+1){1'bx}};
  endcase
end

assign carryOut = result[N];
assign oF[N-1:0] = result[N-1:0];  
assign sign = oF[N-1];
assign overflow = (~A[N-1]) & ~B[N-1] & oF[N-1] | (A[N-1]) & B[N-1] & ~oF[N-1] ;

assign oFlag={sign, zero, overflow, carryOut};
endmodule

公用模块

七段数码管显示模块

module SevenSegDecode(
   input logic[3:0]iData,
	output logic[7:0]oSeg
);

always_comb
 begin
   case(iData)
   4'h0:oSeg=8'b11000000;
	4'h1:oSeg=8'b11111001;
	4'h2:oSeg=8'b10100100;
	4'h3:oSeg=8'b10110000;
	4'h4:oSeg=8'b10011001;
	4'h5:oSeg=8'b10010010;
	4'h6:oSeg=8'b10000010;
	4'h7:oSeg=8'b11111000;
	4'h8:oSeg=8'b10000000;
	4'h9:oSeg=8'b10010000;
	4'hA:oSeg=8'b10001000;
	4'hB:oSeg=8'b10000011;
	4'hC:oSeg=8'b11000110;
	4'hD:oSeg=8'b10100001;
	4'hE:oSeg=8'b10000110;
	4'hF:oSeg=8'b10001110;
	default:oSeg=8'bx;
   endcase
 end
endmodule

寄存器

module DataReg
#(parameter N = 4)
(   output reg [N-1:0] oQ,
    input wire [N-1:0] iD,
    input wire Clk,
    input wire Load,
    input wire Reset
);
always @(posedge Clk or posedge Reset)
begin
  if (Reset)
		oQ <= 0;	
  else if (Load)
		oQ <= iD;
end
endmodule

版权声明:本文为weixin_46831482原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。