硬布线控制
一、何为硬布线?
硬布线控制器是早期计算机设计方法之一。硬布线把控制部件看作产生专门固定时序控制信号的逻辑电路,而此逻辑电路以使用最少元件和取得最高操作速度作为设计目标。
值得注意的是,一旦控制部件构成后,除非重新设计和物理上对它重新布线,否则要想增加新的控制功能是不可能的。这种逻辑电路是一种由门电路和触发器构成的复杂树形逻辑网路,故称之为硬布线控制器。
13—12 | 11—10 | 9—8 | 7—4 | 3—0 |
---|---|---|---|---|
RD | RS1 | RS2 | DATA | OPCODE |
指令类型 | 指令助记符 | OPCODE | 功能 |
---|---|---|---|
R型 | add rd, rs1, rs2 | 0001 | rd⬅(rs1)+(rs2) |
sub rd,rs1,rs2 | 0010 | rd⬅(rs1)-(rs2) | |
and rd, rs1, rs2 | 0011 | rd⬅(rs1)∧(rs2) | |
or rd, rs1, rs2 | 0100 | rd⬅(rs1)∨(rs2) | |
xor rd, rs1, rs2 | 0101 | rd⬅(rs1)⊕(rs2) | |
I型 | addi rd,rs1,#data | 1001 | rd⬅(rs1)+data |
subi rd,rs1,#data | 1010 | rd⬅(rs1)-data | |
andi rd,rs1,#data | 1011 | rd⬅(rs1)∧data | |
ori rd,rs1,#data | 1100 | rd⬅(rs1)∨data | |
xori rd,rs1,#data | 1101 | rd⬅(rs1)⊕data |
二、顶层模块
`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] write_addr = S[13:12];
wire [1:0] read_addr1 = S[11:10];
wire [1:0] read_addr2 = S[9:8];
wire [3:0] imm_data = S[7:4];
wire [3:0] opcode = S[3:0];
//各模块间连线信号
wire [3:0] alu_result, alu_y, read_data1, read_data2;
wire [3:0] flag;
wire write_enable;
wire immToALU;
wire [3:0] ALUctrl;
/************* The logic of this experiment *************/
assign write_enable =1'b1;
assign immToALU = opcode[3];
always@(opcode[2:0])
begin
case(opcode[2:0])
3'b001:ALUctrl = 4'b0001;
3'b010:ALUctrl = 4'b0010;
3'b011:ALUctrl = 4'b0011;
3'b100:ALUctrl = 4'b0100;
3'b101:ALUctrl = 4'b0101;
endcase
end
RegFile #(4)RegFile_ins(.Data(alu_result),.oQ1(read_data1),.oQ2(read_data2),.iWE(write_enable),.clk(clk),.WIndex(write_addr),.RIndex1(read_addr1),.RIndex2(read_addr2));
// 数据通路部分
assign alu_y = immToALU ? imm_data : read_data2;
ALU #(4)ALU_inst(.iOp(ALUctrl),.iX(read_data1),.iY(alu_y),.oF(alu_result),.oFlag(flag));
/****** Internal signal assignment to output port *******/
assign HD[0] = alu_y;
assign HD[1] = read_data1;
assign HD[2] = read_data2;
assign HD[3] = alu_result;
assign L[21:18] = flag;
assign L[5] = write_enable;
assign L[4] = immToALU;
assign L[3:0] = ALUctrl;
endmodule
RegFile模块
module RegFile
#(parameter N = 4)
(
input logic [N-1:0] Data,
output logic [N-1:0] oQ1,
output logic [N-1:0] oQ2,
input logic iWE,
input logic clk,
input logic [1:0] WIndex,
input logic [1:0] RIndex1,
input logic [1:0] RIndex2
);
logic load3, load2, load1, load0;
always @ (posedge clk or posedge iWE)
begin
if (iWE)
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
logic [N-1:0] R0_Q, R1_Q, R2_Q, R3_Q;
DataReg #(N) R0(.oQ(R0_Q), .iD(Data), .Clk(clk), .Load(load0), .Reset(1'b1));
DataReg #(N) R1(.oQ(R1_Q), .iD(Data), .Clk(clk), .Load(load1), .Reset(1'b0));
DataReg #(N) R2(.oQ(R2_Q), .iD(Data), .Clk(clk), .Load(load2), .Reset(1'b0));
DataReg #(N) R3(.oQ(R3_Q), .iD(Data), .Clk(clk), .Load(load3), .Reset(1'b0));
always @ *
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 logic [N-1:0]iOp,
input logic Cin,
input logic [N-1:0] iX,
input logic [N-1:0] iY ,
output logic [N-1:0] oF,
output logic [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
endcase
end
assign C0 =(Cin & M[3] | 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