BONUS PROJECT

Given a CPU Example SAP444v1 as follows, try to improve it for any one of the following purposes.

    1. Low-power

    2. Low-area

    3. High-performance

    4. Better address mode and instruction format.

    5. Debugging the 1-second timer assembly program and completing it.

@

Example: SAP444v1: Simple-As-Possible with 4-bit OP-code, 4-bit destination-index and 4-bit source-index, version 1.

@

module SAP444(Clk, SW, Button, DIGIT, SEG, RING, LED, Cycle, PC, IR, AC);
// Simple-As-Possible CPU Design on Altera EPM1270T144C5 Design Kit
// Tsung-Chu Huang, National Changhua University of Education
// Version: 1.0
// Date: 2008/01/18
// Clk: 16MHz
// SW: 8-bit DIP switch
// Button: 4-bit press-to-0 buttons
// DIGIT: positions of 4 7-seg LEDs
// SEG: 8-bit 7-Seg Code
// RING: 2-row 4-column LEDs above the DIP
wire   [7:0]	AC;
assign	AC	=	R[A];
output [7:0]	PC, AC;
output [11:0]	IR;
output [1:0]	Cycle;
output [15:0]	LED;
//Clock Frequency Divider
input  	Clk;       //Pin-18
reg    	[13:0] FD; 
always@(posedge Clk) FD = FD + 1'b1;
wire   	Clk1kHz;
assign 	Clk1kHz = FD[13];
// DIP Switch and Ring LEDs
input	[7:0] SW;
output	[7:0] RING;
reg		[7:0] RING;
// Input Debouncer
input	[3:0] Button;
reg		[3:0] H, I;
always@(posedge Clk1kHz) begin 	I <= H; H <= Button; end
// Output Display
output [3:0] DIGIT; 
output [7:0] SEG;
reg    [15:0] LED;
OU	U1(Clk1kHz, LED, DIGIT, SEG);
// Register File
reg		[7:0]	R[15:0];
reg				C; // Carry
// Instruction Memory
reg		[7:0]	PC, STK; // Program Counter, Stack
reg		[11:0]	IR; // Instruction Register
wire	[3:0] OP, SI, DI; // OP code, Source Index, Destination Index
wire	[7:0] OPD; // Operand
assign	OPD = IR[7:0];
assign	OP  = IR[11:8];
assign	DI	= IR[7:4]; // Destination Index
assign	SI	= IR[3:0]; // Source Index
wire	Z; // Zero Flag
wire	[11:0]	M;
IM	IMU(PC, M);
reg		  Cycle;
parameter Fetch=1'b0, Execute=1'b1;
always@(posedge Clk) Cycle = ~Cycle;
			
//`include "IS.v"			
// Instruction Set Architecture
// OP-codes without Operands
parameter [3:0]	
// Alias of Registers
	R0 =4'h0,	// Register index
	R1 =4'h1,	// Register index
	R2 =4'h2,	// Register index
	R3 =4'h3,	// Register index
	R4 =4'h4,	// Register index
	R5 =4'h5,	// Register index
	R6 =4'h6,	// Register index
	R7 =4'h7,	// Register index
	R8 =4'h8,	// Register index
	R9 =4'h9,	// Register index
	R10=4'ha,	// Register index
	R11=4'hb,	// Register index
	R12=4'hc,	// Register index
	R13=4'hd,	// Register index
	R14=4'he,	// Register index
	R15=4'hf,	// Register index
	A  =4'hf,	// Accumulator
	L0 =4'h0,	// 7-Seg LED D
	L1 =4'h1,	// 7-Seg LED C
	L2 =4'h2,	// 7-Seg LED B
	L3 =4'h3;	// 7-Seg LED A
parameter [3:0]
	NOP=4'h0,	// No Operation
	CLC=4'h2,	// Clear C
	SEC=4'h3,	// Set C
	DIP=4'h4,	// DIP <- A
	BUT=4'h5,	// A[3:0] <- Buttons
	RNG=4'h6,	// RingLED <- A
	RET=4'he,	// Return: PC <- STK
	HLT=4'hf;	// Halt
// OP-codes with 4-bit Operands
parameter [3:0]
	NOT=4'h1,	// Ri <- ~Ri
	SHL=4'h2,	// C<-Rr[7],Rr[7:1]<-Rr[6:0]
	SHR=4'h3,	// C<-Rr[0],Rr[6:0]<-Rr[7:1]
	INC=4'h4,	// Ri <- Ri + 1
	DEC=4'h5,	// Ri <- Ri - 1
	CLR=4'h6,	// Ri <- 0
	OUT=4'h7;	// Li <- A[3:0]
	
// OP-codes with 8-bit Operand (d,s) or opd
parameter [3:0]
	EXT=4'h0,	// Extention Code
	MOV=4'h1,	// Rd <- Rs; d: destination, s: source
	AND=4'h2,	// Rd <- Rd & Rs; logic AND
	LOR=4'h3,	// Rd <- Rd | Rs; Logic OR
	ADD=4'h4,	// Rd <- Rd + Rs
	SUB=4'h5,	// Rd <- Rd - Rs; Subtract
	ADC=4'h6,	// Rd <- Rd + Rs; Add with C
	SBC=4'h7,	// Rd <- Rd - Rs-C; Subtract with C
	XOR=4'h8,	// Rd <- Rd ^ Rs
	JMP=4'h9,	// PC <- opd
	JPC=4'ha,	// if(C=1) PC <- opd
	JNC=4'hb,	// if(C=0) PC <- opd
	JPZ=4'hc,	// if(Z=1) PC <- opd; A=0
	JNZ=4'hd,	// if(Z=0) PC <- opd; A not Zero
	CAL=4'he,	// STK <- PC, PC <- opd; Call
	LDI=4'hf;	// A <- opd; load immediately
nor	zflag(Z, R[A][0], R[A][1], R[A][2], R[A][3], R[A][4], R[A][5], R[A][6], R[A][7]);
always@(posedge Clk)
	case(Cycle)
//		Init:	begin PC=8'b0; IR=8'b0; R[A]=8'b0; C=1'b0; end
		Fetch:	begin IR <= M; PC <= PC + 1'b1; end
		Execute: 
			case(OP)
				EXT:	case(DI)
						EXT:	case(SI)
								NOP: ;
								CLC: C=1'b0;
								SEC: C=1'b1;
								DIP: R[A]=SW;
								BUT: R[A][3:0]=I[3:0];
								RNG: RING=R[A];
								RET: PC=STK;
								HLT: PC = PC - 1'b1;
							endcase
						NOT:	R[SI]=~R[SI];
						SHL:	begin C<=R[SI][7]; R[SI][7:1]<=R[SI][6:0]; R[SI][0]<=1'b0; end
						SHR:	begin C<=R[SI][0]; R[SI][6:0]<=R[SI][7:1]; R[SI][7]<=1'b0; end
						INC:	{C, R[SI]} = R[SI] + 1'b1;
						DEC:	{C, R[SI]} = R[SI] - 1'b1; 
						CLR:	R[SI]=8'b0;
						OUT:	case(SI)
								0:	LED[3:0]=R[A][3:0];
								1:	LED[7:4]=R[A][3:0];
								2:	LED[11:8]=R[A][3:0];
								3:	LED[15:12]=R[A][3:0];
							endcase
					endcase
				MOV:	R[DI]=R[SI];
				AND:	R[DI]=R[DI] & R[SI];
				LOR:	R[DI]=R[DI] | R[SI];
				ADD:	{C, R[DI]}=R[DI] + R[SI];
				SUB:	{C, R[DI]}=R[DI] - R[SI];
				ADC:	{C, R[DI]}=R[DI] + R[SI] + C;
				SBC:	{C, R[DI]}=R[DI] - R[SI] - C;
				XOR:	R[DI]=R[DI] ^ R[SI];
				JMP:	PC=OPD;
				JPC:	if(C) PC=OPD;
				JNC:	if(~C) PC=OPD;
				JPZ:	if(Z) PC=OPD;
				JNZ:	if(~Z) PC=OPD;
				CAL:	begin STK<=PC; PC<=OPD; end
				LDI:	R[A] = OPD;
			endcase
	endcase
endmodule
module OU(Clk1kHz, LED, DIGIT, SEG); // Simple Output Unit
input			Clk1kHz;//Internal Inputs
input	[15:0]	LED;	// Internal Inputs
output	[3:0]	DIGIT; 	// Hi-Enable 29, 30, 31, 32
output	[7:0]	SEG; 	// Low-Enable h, .., a
reg		[3:0]	DIGIT;
reg		[7:0]	SEG;
reg		[1:0]	SCAN;
reg 	[3:0]	HEX;
always@(posedge Clk1kHz) SCAN = SCAN + 1'b1;
always@(posedge Clk1kHz)
	case(SCAN)
		0: begin DIGIT = 4'b0001; HEX=LED[3:0]; end
		1: begin DIGIT = 4'b0010; HEX=LED[7:4]; end
		2: begin DIGIT = 4'b0100; HEX=LED[11:8]; end
		3: begin DIGIT = 4'b1000; HEX=LED[15:12]; end
	endcase
always@(HEX)
	case(HEX)  //hgfedcba
		0:SEG=8'b11000000;
		1:SEG=8'b11111001;
		2:SEG=8'b10100100;
		3:SEG=8'b10110000;
		4:SEG=8'b10011001;
		5:SEG=8'b10010010;
		6:SEG=8'b10000010;
		7:SEG=8'b11111000;
		8:SEG=8'b10000000;
		9:SEG=8'b10010000;
	       10:SEG=8'b10100000;
	       11:SEG=8'b10000011;
	       12:SEG=8'b10100111;
	       13:SEG=8'b10100001;
	       14:SEG=8'b10000110;
	       15:SEG=8'b10001110;
  	   default:SEG=8'b01111111;
	endcase
endmodule
module IM(AD, Q);
input	[7:0] AD;
output	[11:0] Q;
reg		[11:0] Q;
//`include "IS.v"
// Instruction Set Architecture
parameter [3:0]	
// Alias of Registers
	R0 =4'h0,	// Register index
	R1 =4'h1,	// Register index
	R2 =4'h2,	// Register index
	R3 =4'h3,	// Register index
	R4 =4'h4,	// Register index
	R5 =4'h5,	// Register index
	R6 =4'h6,	// Register index
	R7 =4'h7,	// Register index
	R8 =4'h8,	// Register index
	R9 =4'h9,	// Register index
	R10=4'ha,	// Register index
	R11=4'hb,	// Register index
	R12=4'hc,	// Register index
	R13=4'hd,	// Register index
	R14=4'he,	// Register index
	R15=4'hf,	// Register index
	A  =4'hf,	// Accumulator
	L0 =4'h0,	// 7-Seg LED D
	L1 =4'h1,	// 7-Seg LED C
	L2 =4'h2,	// 7-Seg LED B
	L3 =4'h3;	// 7-Seg LED A
	
// OP-codes without Operands
parameter [3:0]
	NOP=4'h0,	// No Operation
	CLC=4'h2,	// Clear C
	SEC=4'h3,	// Set C
	DIP=4'h4,	// DIP <- A
	BUT=4'h5,	// A[3:0] <- Buttons
	RNG=4'h6,	// RingLED <- A
	RET=4'he,	// Return: PC <- STK
	HLT=4'hf;	// Halt
	
// OP-codes with 4-bit Operands
parameter [3:0]
	NOT=4'h1,	// Ri <- ~Ri
	SHL=4'h2,	// C<-Rr[7],Rr[7:1]<-Rr[6:0]
	SHR=4'h3,	// C<-Rr[0],Rr[6:0]<-Rr[7:1]
	INC=4'h4,	// Ri <- Ri + 1
	DEC=4'h5,	// Ri <- Ri - 1
	CLR=4'h6,	// Ri <- 0
	OUT=4'h7;	// Li <- A[3:0]
	
// OP-codes with 8-bit Operand (d,s) or opd
parameter [3:0]
	EXT=4'h0,	// Extention Code
	MOV=4'h1,	// Rd <- Rs; d: destination, s: source
	AND=4'h2,	// Rd <- Rd & Rs; logic AND
	LOR=4'h3,	// Rd <- Rd | Rs; Logic OR
	ADD=4'h4,	// Rd <- Rd + Rs
	SUB=4'h5,	// Rd <- Rd - Rs; Subtract
	ADC=4'h6,	// Rd <- Rd + Rs; Add with C
	SBC=4'h7,	// Rd <- Rd - Rs-C; Subtract with C
	XOR=4'h8,	// Rd <- Rd ^ Rs
	JMP=4'h9,	// PC <- opd
	JPC=4'ha,	// if(C=1) PC <- opd
	JNC=4'hb,	// if(C=0) PC <- opd
	JPZ=4'hc,	// if(Z=1) PC <- opd; A=0
	JNZ=4'hd,	// if(Z=0) PC <- opd; A not Zero
	CAL=4'he,	// STK <- PC, PC <- opd; Call
	LDI=4'hf;	// A <- opd; load immediately
// Program: Calculate 1+2+3+...+100=? Answer: 5050 = 16'h13BA
parameter [3:0] SUM1=4'h1, SUM0=4'h0;
parameter [7:0] LOOP=3, NEXT=7, SHR4=100, N=100;
always@(AD)
	case(AD)
		0	:	Q={CLR, SUM0};
		1	:	Q={CLR, SUM1};
		2	:	Q={CLR, R2};
	LOOP	:	Q={INC, R2};
		4	:	Q={ADD, SUM0, R2};
		5	:	Q={JNC, NEXT};		
		6	:	Q={INC, SUM1};
	NEXT	:	Q={LDI, N};
		8	:	Q={SUB, A, R2};
		9	:	Q={JNZ, LOOP};
		10	:	Q={MOV, A, SUM0};
		11	:	Q={OUT, L0};
		12	:	Q={CAL, SHR4};
		13	:	Q={OUT, L1};
		14	:	Q={MOV, A, SUM1};
		15	:	Q={OUT, L2};
		16	:	Q={CAL, SHR4};
		17	:	Q={OUT, L3};
		18	:	Q={HLT};
	SHR4	:	Q={SHR, A};
		101	:	Q={SHR, A};
		102	:	Q={SHR, A};
		103	:	Q={SHR, A};
		104	:	Q={RET};
	default	:	Q={NOP};
	endcase
/*
// Program: Delay Loop for a 1-second timer
parameter	[7:0]	INCREASE=3, NO_CARRY=6, SHR4=16, LABEL1=19, EXIT1=26,	DELAY=27, LABEL2=30, LOOP2=32, LOOP3=34, LOOP4=36, EXIT2=51, N2=63, N3=63, N4=63;
always@(AD)
	case(AD)
		0	:	Q={CLR, R0};
		1	:	Q={CLR, R1};
		2	:	Q={CLC};
INCREASE	:	Q={INC, R0};		//125ns
		4	:	Q={JNC, NO_CARRY};	//125ns
		5	:	Q={INC, R1};		//125ns
NO_CARRY	:	Q={MOV, A, R0};		//125ns
		7	:	Q={OUT, L0};		//125ns
		8	:	Q={CAL, SHR4};		//125ns
		9	:	Q={OUT, L1};		//125ns
		10	:	Q={MOV, A, R1};		//125ns
		11	:	Q={OUT, L2};		//125ns
		12	:	Q={CAL, SHR4};		//125ns * 5
		13	:	Q={OUT, L3};		//125ns
		14	:	Q={CAL, DELAY};		//125ns
		15	:	Q={JMP, INCREASE};	//125ns
// A>>4 Subroutine
SHR4		:	Q={CLR, R5};
		17	:	Q={JNC, LABEL1};
		18	:	Q={INC, R5};
LABEL1		:	Q={SHR, A};
		20	:	Q={SHR, A};
		21	:	Q={SHR, A};
		22	:	Q={SHR, A};
		23	:	Q={MOV, A, R5};
		24	:	Q={JPZ, EXIT2};
		25	:	Q={SEC};
EXIT1		:	Q={RET};
// Delay loop Subroutine
DELAY		:	Q={CLR, R5};		//125ns
		28	:	Q={JNC, LABEL2};	//125ns
		29	:	Q={INC, R5};	
LABEL2		:	Q={LDI, N2};		//125ns
		31	:	Q={MOV, R2, A};		//125ns
LOOP2		:	Q={LDI, N3};		//125ns * N2
		33	:	Q={MOV, R3, N3};	//125ns * N2
LOOP3		:	Q={LDI, N4};		//125ns * N2 * N3
		35	:	Q={MOV, R4, N4};	//125ns * N2 * N3	
LOOP4		:	Q={NOP};			//125ns * N2 * N3 * N4
		37	:	Q={DEC, R4};		//125ns * N2 * N3 * N4
		38	:	Q={MOV, A, R4};		//125ns * N2 * N3 * N4
		39	:	Q={JNZ, LOOP4};		//125ns * N2 * N3 * N4 
		40	:	Q={DEC, R3};		//125ns * N2 * N3
		41	:	Q={MOV, A, R3};		//125ns * N2 * N3
		42	:	Q={JNZ, LOOP3};		//125ns * N2 * N3 
		43	:	Q={DEC, R2};		//125ns * N2
		44	:	Q={NOP};			//125ns * N2
		45	:	Q={MOV, A, R2};		//125ns * N2
		46	:	Q={JNZ, LOOP2};		//125ns * N2
		47	:	Q={NOP};			//125ns
		48	:	Q={MOV, A, R5};
		49	:	Q={JPZ, EXIT2};
		50	:	Q={SEC};
EXIT2		:	Q={RET};			//125ns
	default	:	Q={NOP};			//125ns
	endcase
*/
endmodule
@

@