0% found this document useful (0 votes)
2 views35 pages

Mini RISC Advanced Materials

The document outlines the curriculum for the Advanced Diploma in AI-Chip Design, specifically focusing on Microcontroller Programming and the implementation of various components such as ALU, register file, and instruction memory using assembly language and SystemVerilog. It includes a laboratory aim to sum numbers using the 8085 microprocessor, along with code templates and a control unit for a CPU. The document serves as a guide for students to understand microprocessor programming and hardware design principles.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views35 pages

Mini RISC Advanced Materials

The document outlines the curriculum for the Advanced Diploma in AI-Chip Design, specifically focusing on Microcontroller Programming and the implementation of various components such as ALU, register file, and instruction memory using assembly language and SystemVerilog. It includes a laboratory aim to sum numbers using the 8085 microprocessor, along with code templates and a control unit for a CPU. The document serves as a guide for students to understand microprocessor programming and hardware design principles.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Advance Diploma in AI-Chip Design

(ADAC)

SEMESTER - 4
Module - 1

Microcontroller Programming
(ADAC LAB CODE: S1M4L01)
Assembly Level Language for Microprocessors
Table of Content

1. Aim of the Laboratory............................................................................3


2. EDA Tool...............................................................................................4
3. Process Flow.........................................................................................5
4. Design................................................................................................... 6
5. Run Simulation......................................................................................7
6. Conclusion.............................................................................................8
[Link] of the Laboratory
To sum of 10 numbers using 8085 microprocessor.
[Link]
Online compiler
[Link]
[Link] Program
; 8085 ALP to generate an Arithmetic Progression (AP) Series
LXI H, 2000H ; Point HL to the parameter initialization address
MOV C, M ; Load the total number of terms (N) into Register C
(Counter)
INX H ; Move HL to 2001H
MOV A, M ; Load the first term (a) into the Accumulator
INX H ; Move HL to 2002H
MOV B, M ; Load the common difference (d) into Register B
LXI H, 3000H ; Initialize HL to the starting output memory address
LOOP: MOV M, A ; Store the current AP term into the memory
location
ADD B ; Calculate next term by adding common difference: A = A + B
INX H ; Increment memory pointer to point to next storage location
DCR C ; Decrement term counter (C = C - 1)
JNZ LOOP ; If Counter C is not zero, repeat loop for next term
HLT ; Halt the execution
[Link] Simulation

This will print all the node voltages in a table format.


[Link]

Mini RISC Processor


Advanced Implementation Guide
Code Templates, SystemVerilog Verification & FPGA Deployment
PART 1: Detailed Module Code
Templates
1.1 Complete ALU Module (Reference Implementation)
module alu_8bit (
input [7:0] operand_a, // First operand
input [7:0] operand_b, // Second operand
input [3:0] opcode, // Operation code
output reg [7:0] result, // ALU result
output reg carry_out, // Carry/overflow flag
output reg zero_out, // Zero flag
output reg sign_out // Sign flag
);

// Opcode definitions
parameter ADD = 4'b0000;
parameter SUB = 4'b0001;
parameter AND = 4'b0010;
parameter OR = 4'b0011;
parameter XOR = 4'b0100;
parameter NOT = 4'b0101;
parameter SHL = 4'b0110;
parameter SHR = 4'b0111;
parameter CMP = 4'b1000;

// Intermediate signals for better readability


wire [8:0] add_result = operand_a + operand_b;
wire [8:0] sub_result = operand_a - operand_b;
wire [7:0] and_result = operand_a & operand_b;
wire [7:0] or_result = operand_a | operand_b;
wire [7:0] xor_result = operand_a ^ operand_b;
wire [7:0] not_result = ~operand_a;
wire [7:0] shl_result = operand_a << operand_b[2:0];
wire [7:0] shr_result = operand_a >> operand_b[2:0];

always @(*) begin


// Default assignments
result = 8'b0;
carry_out = 1'b0;
zero_out = 1'b0;
sign_out = 1'b0;

case (opcode)
ADD: begin
result = add_result[7:0];
carry_out = add_result[8]; // Overflow
end

SUB: begin
result = sub_result[7:0];
carry_out = sub_result[8]; // Borrow
end

AND: result = and_result;

OR: result = or_result;


XOR: result = xor_result;

NOT: result = not_result;

SHL: begin
result = shl_result;
carry_out = operand_a[7]; // MSB carries out
end

SHR: begin
result = shr_result;
carry_out = operand_a[0]; // LSB carries out
end

CMP: begin
result = operand_a - operand_b;
carry_out = (operand_a < operand_b) ? 1'b1 : 1'b0;
end

default: result = 8'b0;


endcase

// Flag generation
zero_out = (result == 8'b0) ? 1'b1 : 1'b0;
sign_out = result[7];
end

endmodule

1.2 Complete Register File (Reference Implementation)


module register_file (
input clk,
input reset,
input write_enable,
input [2:0] read_addr_a, // First read port
input [2:0] read_addr_b, // Second read port
input [2:0] write_addr, // Write port
input [7:0] write_data,
output [7:0] read_data_a,
output [7:0] read_data_b
);

// 8 registers, 8 bits each


reg [7:0] registers [0:7];

integer i;

// Initialize all registers to zero


initial begin
for (i = 0; i < 8; i = i + 1)
registers[i] = 8'b0;
end

// Combinational read operations (dual-port, no latency)


assign read_data_a = registers[read_addr_a];
assign read_data_b = registers[read_addr_b];

// Synchronous write operation


always @(posedge clk) begin
if (reset) begin
for (i = 0; i
< 8; i = i + 1)
registers[i] <= 8'b0;
end else if (write_enable) begin
registers[write_addr] <= write_data;
end
end

endmodule

1.3 Complete Instruction Memory


module instruction_memory (
input [7:0] address,
output [15:0] instruction
);

// 256-entry instruction memory, 16 bits wide


reg [15:0] memory [0:255];

// Load program from hex file


initial begin
$readmemh("[Link]", memory);
end

// Combinational read (asynchronous ROM)


assign instruction = memory[address];

endmodule

1.4 Complete Data Memory


module data_memory (
input clk,
input [7:0] address,
input [7:0] write_data,
input write_enable,
input read_enable,
output [7:0] read_data
);

// 256-entry data memory, 8 bits wide


reg [7:0] memory [0:255];

integer i;

// Initialize memory to zero


initial begin
for (i = 0; i < 256; i = i + 1)
memory[i] = 8'b0;
end

// Asynchronous read
assign read_data = (read_enable) ? memory[address] : 8'bz;

// Synchronous write
always @(posedge clk) begin
if (write_enable)
memory[address] <= write_data;
end

endmodule
PART 2: Control Unit & FSM
Implementation
2.1 6-Stage Pipeline Control Unit (Complete)
module control_unit (
input clk,
input reset,
input [3:0] opcode,
input zero_flag,
input carry_flag,

output reg pc_increment, // Increment PC


output reg pc_jump, // Jump to address
output reg reg_write_enable, // Write to register
output reg mem_read_enable, // Read from memory
output reg mem_write_enable, // Write to memory
output reg alu_enable, // Enable ALU

output reg [2:0] state,


output wire [2:0] next_state
);

// State definitions
parameter RESET = 3'b000;
parameter FETCH = 3'b001;
parameter DECODE = 3'b010;
parameter EXECUTE = 3'b011;
parameter MEMORY = 3'b100;
parameter WRITEBACK = 3'b101;

// State transition logic (combinational)


assign next_state = (state == RESET) ? FETCH :
(state == FETCH) ? DECODE :
(state == DECODE) ? EXECUTE :
(state == EXECUTE) ? MEMORY :
(state == MEMORY) ? WRITEBACK :
(state == WRITEBACK) ? FETCH :
RESET;

// State register update


always @(posedge clk) begin
if (reset)
state <= RESET;
else
state <= next_state;
end

// Output control based on current state


always @(*) begin
// Default: disable all outputs
pc_increment = 1'b0;
pc_jump = 1'b0;
reg_write_enable = 1'b0;
mem_read_enable = 1'b0;
mem_write_enable = 1'b0;
alu_enable = 1'b0;
case (state)
RESET: begin
// Initialization stage
pc_increment = 1'b0;
end

FETCH: begin
// Fetch instruction from memory
mem_read_enable = 1'b1;
pc_increment = 1'b1;
end

DECODE: begin
// Decode instruction (combinational)
// No outputs - just preparing signals
end

EXECUTE: begin
// Execute ALU operation
alu_enable = 1'b1;

// Check for conditional jumps


case (opcode)
4'b1001: pc_jump = zero_flag; // JZ - Jump if Zero
4'b1010: pc_jump = carry_flag; // JC - Jump if Carry
4'b1011: pc_jump = 1'b1; // JMP - Unconditional
default: pc_jump = 1'b0;
endcase
end

MEMORY: begin
// Access memory for LOAD/STORE
case (opcode)
4'b0101: mem_read_enable = 1'b1; // LOAD
4'b0110: mem_write_enable = 1'b1; // STORE
default: mem_read_enable = 1'b0;
endcase
end

WRITEBACK: begin
// Write result back to register
case (opcode)
4'b0000, 4'b0001, 4'b0010, 4'b0011, 4'b0100: // ALU ops
reg_write_enable = 1'b1;
4'b0101: // LOAD
reg_write_enable = 1'b1;
default:
reg_write_enable = 1'b0;
endcase
end

default: begin
pc_increment = 1'b0;
end
endcase
end

endmodule

2.2 Instruction Decoder


module instruction_decoder (
input [15:0] instruction,

output [3:0] opcode,


output [2:0] dest_reg,
output [2:0] src_reg,
output [5:0] immediate
);

// Instruction format: [OPCODE:4][DEST:3][SRC:3][IMM:6]


assign opcode = instruction[15:12];
assign dest_reg = instruction[11:9];
assign src_reg = instruction[8:6];
assign immediate = instruction[5:0];

endmodule
PART 3: Complete CPU Top-Level
Module
3.1 CPU Top-Level (Full Integration)
module cpu_top (
input clk,
input reset,

// Debugging outputs
output [7:0] pc_out,
output [15:0] instruction_out,
output [7:0] alu_result_out,
output [2:0] cpu_state_out
);

// Internal signals
wire [7:0] pc;
wire [7:0] next_pc;
wire [15:0] instruction;

wire [3:0] opcode;


wire [2:0] dest_reg, src_reg;
wire [5:0] immediate;

wire [7:0] reg_read_a, reg_read_b;


wire [7:0] alu_result;
wire [7:0] alu_input_a, alu_input_b;
wire alu_carry, alu_zero, alu_sign;

wire [7:0] mem_read_data, mem_write_data;

wire pc_increment, pc_jump, reg_write_en;


wire mem_read_en, mem_write_en, alu_en;
wire [2:0] ctrl_state;

// ========== MODULE INSTANTIATIONS ==========

// Program Counter
program_counter pc_inst (
.clk(clk),
.reset(reset),
.increment(pc_increment),
.jump_enable(pc_jump),
.jump_target(immediate),
.pc(pc)
);

// Instruction Memory
instruction_memory imem (
.address(pc),
.instruction(instruction)
);

// Instruction Decoder
instruction_decoder decoder (
.instruction(instruction),
.opcode(opcode),
.dest_reg(dest_reg),
.src_reg(src_reg),
.immediate(immediate)
);

// Register File
register_file regfile (
.clk(clk),
.reset(reset),
.read_addr_a(src_reg),
.read_addr_b(dest_reg),
.write_addr(dest_reg),
.write_data(alu_result),
.write_enable(reg_write_en),
.read_data_a(reg_read_a),
.read_data_b(reg_read_b)
);

// ALU Operand Selection


assign alu_input_a = reg_read_a;
assign alu_input_b = (opcode == 4'b0100) ? {2'b00, immediate} :
reg_read_b;

// ALU
alu_8bit alu_inst (
.operand_a(alu_input_a),
.operand_b(alu_input_b),
.opcode(opcode),
.result(alu_result),
.carry_out(alu_carry),
.zero_out(alu_zero),
.sign_out(alu_sign)
);

// Data Memory
data_memory dmem (
.clk(clk),
.address(alu_result),
.write_data(reg_read_b),
.write_enable(mem_write_en),
.read_enable(mem_read_en),
.read_data(mem_read_data)
);

// Control Unit
control_unit ctrl (
.clk(clk),
.reset(reset),
.opcode(opcode),
.zero_flag(alu_zero),
.carry_flag(alu_carry),
.pc_increment(pc_increment),
.pc_jump(pc_jump),
.reg_write_enable(reg_write_en),
.mem_read_enable(mem_read_en),
.mem_write_enable(mem_write_en),
.alu_enable(alu_en),
.state(ctrl_state)
);

// ========== DEBUG OUTPUTS ==========


assign pc_out = pc;
assign instruction_out = instruction;
assign alu_result_out = alu_result;
assign cpu_state_out = ctrl_state;

endmodule
PART 4: Comprehensive Testbench
4.1 Complete CPU Testbench
module cpu_tb;

// Test signals
reg clk, reset;
wire [7:0] pc_out;
wire [15:0] instr_out;
wire [7:0] alu_out;
wire [2:0] state_out;

// CPU instance
cpu_top cpu (
.clk(clk),
.reset(reset),
.pc_out(pc_out),
.instruction_out(instr_out),
.alu_result_out(alu_out),
.cpu_state_out(state_out)
);

// Clock generation: 10ns period (100 MHz)


initial begin
clk = 0;
forever #5 clk = ~clk;
end

// Main test
initial begin
$dumpfile("cpu_simulation.vcd");
$dumpvars(0, cpu_tb);

// Test 1: Reset
reset_cpu();

// Test 2: Load program


load_program("[Link]");

// Test 3: Run simulation


run_simulation(200); // 200 clock cycles

// Test 4: Check results


check_registers();
check_memory();

$finish;
end

// ========== TASKS ==========

task reset_cpu;
begin
reset = 1;
@(posedge clk);
@(posedge clk);
reset = 0;
@(posedge clk);
$display("[%t] CPU Reset Complete", $time);
end
endtask

task load_program(string filename);


begin
$readmemh(filename, [Link]);
$display("[%t] Program Loaded: %s", $time, filename);
end
endtask

task run_simulation(integer cycles);


integer i;
begin
$display("[%t] Starting Simulation (%d cycles)", $time, cycles);
for (i = 0; i < cycles; i = i + 1) begin
@(posedge clk);
if (i % 10 == 0)
$display("[%t] Cycle %d: PC=%h, Instr=%h, ALU=%h, State=%d",
$time, i, pc_out, instr_out, alu_out, state_out);
end
$display("[%t] Simulation Complete", $time);
end
endtask

task check_registers;
integer i;
begin
$display("\n=== Register File Contents ===");
for (i = 0; i < 8; i = i + 1)
$display("R%d = 0x%02h", i, [Link][i]);
end
endtask

task check_memory;
integer i;
begin
$display("\n=== Data Memory (first 32 locations) ===");
for (i = 0; i < 32; i = i + 1)
$display("MEM[0x%02h] = 0x%02h", i, [Link][i]);
end
endtask

endmodule
PART 5: Example Test Programs & Hex
Files
5.1 Assembly Program Examples
Program 1: Simple Addition
// Simple Addition Test Program
// Expected: R1=5, R2=10, R3=15

MOV R1, 5 // R1 <= 5


MOV R2, 10 // R2 <= 10
ADD R3, R1, R2 // R3 <= R1 + R2 = 15
HALT // Stop

// Hex encoding (16-bit instructions):


// MOV R1,5: opcode=0001, dest=001, src=000, imm=000101 = 0001 001 000
000101 = 1045
// MOV R2,10: opcode=0001, dest=010, src=000, imm=001010 = 0001 010 000
001010 = 128A
// ADD R3,R1,R2: opcode=0000, dest=011, src=001, imm=010 = 0000 011 001
000010 = 0312
// HALT: 1111111111111111 = FFFF

// [Link]:
@0000
1045
128A
0312
FFFF

Program 2: Conditional Jump Test


// Test conditional jumps
// Load 5 into R1
// Load 3 into R2
// Subtract R1-R2 (result=2, non-zero)
// Jump if Zero should NOT execute
// Load 20 into R3
// Expected: R1=5, R2=3, R3=20

MOV R1, 5 // @0000


MOV R2, 3 // @0001
SUB R3, R1, R2 // @0002, R3=2
JZ 0x0005 // @0003, Jump if Zero (should NOT jump)
MOV R4, 20 // @0004
HALT // @0005

// [Link]:
@0000
1045
1203
0312
9005
144D
FFFF
Program 3: Memory Load/Store
// Test memory operations
// Store value to memory
// Load value back
// Expected: MEM[20]=15, R4=15

MOV R1, 15 // R1 <= 15


MOV R2, 20 // R2 <= 20 (address)
STORE R1, R2 // MEM[20] <= R1
LOAD R3, R2 // R3 <= MEM[20]
HALT

// [Link]:
@0000
104F
1414
0612
0512
FFFF

Program 4: Loop Counter


// Loop 5 times, sum values
// Expected: Result = 0+1+2+3+4 = 10 in R3

MOV R1, 0 // Counter


MOV R3, 0 // Accumulator
MOV R4, 5 // Loop limit

LOOP:
ADD R3, R3, R1 // Sum += Counter
ADD R1, R1, 1 // Counter++
CMP R1, R4 // Compare Counter to Limit
JNZ LOOP // Jump if not zero

HALT

// [Link]:
@0000
1000
1800
1405
0301
0101
0104
9000
FFFF
PART 6: SystemVerilog Verification
Environment
6.1 SystemVerilog Transaction-Based Testbench
// SystemVerilog CPU Verification Environment

// ========== TRANSACTION CLASS ==========


class cpu_transaction;
rand bit [3:0] opcode;
rand bit [2:0] dest_reg, src_reg;
rand bit [5:0] immediate;
bit [7:0] expected_result;

constraint valid_opcode {
opcode inside {[4'b0000:4'b1000]};
}

constraint valid_regs {
dest_reg inside {[3'b000:3'b111]};
src_reg inside {[3'b000:3'b111]};
}
endclass

// ========== INSTRUCTION GENERATOR ==========


class instruction_generator;
cpu_transaction trans_queue[$];

function void generate_instructions(int count);


cpu_transaction trans;
repeat(count) begin
trans = new();
if (![Link]())
$fatal("Randomization failed");
trans_queue.push_back(trans);
end
endfunction

function cpu_transaction get_instruction();


if (trans_queue.size() > 0)
return trans_queue.pop_front();
else
return null;
endfunction
endclass

// ========== MONITOR ==========


class cpu_monitor;
virtual cpu_if vif;
cpu_transaction observed_trans;

function void collect_transaction();


@(posedge [Link]);
observed_trans = new();
observed_trans.opcode = [Link];
observed_trans.dest_reg = vif.dest_reg;
observed_trans.expected_result = vif.alu_result;
endfunction
endclass

// ========== SCOREBOARD ==========


class cpu_scoreboard;
cpu_transaction expected_q[$];
cpu_transaction observed_q[$];

function void add_expected(cpu_transaction trans);


expected_q.push_back(trans);
endfunction

function void add_observed(cpu_transaction trans);


observed_q.push_back(trans);
endfunction

function void compare();


cpu_transaction exp, obs;
if (expected_q.size() != observed_q.size())
$warning("Queue size mismatch: %d vs %d",
expected_q.size(), observed_q.size());

while (expected_q.size() > 0) begin


exp = expected_q.pop_front();
obs = observed_q.pop_front();

if ([Link] !== [Link])


$error("Opcode mismatch: exp=%h, obs=%h",
[Link], [Link]);
end
endfunction
endclass

// ========== ENVIRONMENT ==========


class cpu_env;
instruction_generator gen;
cpu_monitor monitor;
cpu_scoreboard scoreboard;

function void build();


gen = new();
monitor = new();
scoreboard = new();
endfunction

function void run();


gen.generate_instructions(100);

repeat(100) begin
cpu_transaction trans = gen.get_instruction();
if (trans != null) begin
scoreboard.add_expected(trans);
monitor.collect_transaction();
scoreboard.add_observed(monitor.observed_trans);
end
end

[Link]();
endfunction
endclass

// ========== TEST DRIVER ==========


module cpu_verification_tb;
cpu_env env;
initial begin
env = new();
[Link]();
[Link]();
end
endmodule
PART 7: Advanced Debugging & Analysis
Techniques
7.1 Signal Tracing with $monitor and $display
// Advanced debugging output
module cpu_tb;
// ... (cpu instance)

initial begin
$dumpfile("cpu_debug.vcd");
$dumpvars(0, cpu_tb);

// Detailed logging
$display("\n===== CPU SIMULATION START =====");
$display("Time | PC | Opcode | State | ALU_Result");
$display("-----|----| -------|-------|----------");

reset_cpu();
end

// Monitor changes in key signals


always @(posedge clk) begin
if (state == FETCH)
$display("%t | %02h | %04h | FETCH | %02h",
$time, pc, instruction, alu_result);

if (state == EXECUTE)
$display("%t | %02h | %04h | EXEC | %02h",
$time, pc, instruction, alu_result);
end

// Track register changes


always @(posedge clk) begin
if (reg_write_enable)
$display("[%t] Register Write: R%d <= 0x%02h",
$time, dest_reg, alu_result);
end

// Track memory changes


always @(posedge clk) begin
if (mem_write_enable)
$display("[%t] Memory Write: MEM[0x%02h] <= 0x%02h",
$time, address, write_data);
end
endmodule

7.2 Assertion-Based Verification


// Add assertions to verify design properties
module cpu_verification;

// Assert: PC must never exceed valid range


property pc_valid;
@(posedge clk) pc <= 8'hFF;
endproperty
assert property (pc_valid) else $error("PC out of range");

// Assert: Register index valid


property reg_index_valid;
@(posedge clk) (write_enable) |-> (dest_reg <= 3'b111);
endproperty
assert property (reg_index_valid) else
$error("Invalid register index");

// Assert: Memory
address valid
property mem_addr_valid;
@(posedge clk) (mem_write_enable) |->
(mem_addr <= 8'hFF);
endproperty
assert property (mem_addr_valid) else
$error("Memory address out of range");

// Assert: ALU result matches expected


property alu_correctness;
@(posedge clk) (opcode == ADD) |->
(alu_result == (operand_a + operand_b));
endproperty
assert property (alu_correctness) else
$error("ALU result mismatch");

// Functional coverage: Track executed opcodes


covergroup cg_instructions;
cp_opcode: coverpoint opcode {
bins add = {4'b0000};
bins sub = {4'b0001};
bins and_op = {4'b0010};
bins or_op = {4'b0011};
bins mov = {4'b0100};
}

cp_reg_cross: cross dest_reg, src_reg;


endgroup

endmodule
PART 8: Synthesis and FPGA Deployment
8.1 Synthesis-Ready Checklist
Before Synthesis:
• ✓ Remove all testbench files ($display, $readmemh, etc.)
• ✓ Verify all $readmemh calls use synthesis-safe patterns
• ✓ Ensure all arrays are properly sized (powers of 2)
• ✓ Check for combinational loops (can cause glitches)
• ✓ Verify all outputs have drivers
• ✓ Check for multiple drivers on same wire

8.2 Vivado/Quartus Project Setup


Xilinx Vivado Flow:
• 1. Create new project (Select FPGA board)
• 2. Add all .v files (exclude testbench)
• 3. Set top module to 'cpu_top'
• 4. Add IP (if using Xilinx primitives)
• 5. Run Synthesis → Analyze results
• 6. Run Place & Route → Check timing
• 7. Generate Bitstream
• 8. Program FPGA

Intel Quartus Flow:


• 1. New Project Wizard (Select Device)
• 2. Add Design Files (Verilog sources)
• 3. Set top entity
• 4. Compile → Analyze
• 5. Timing Analysis
• 6. Program Device
8.3 Resource Optimization
Reduce Area:
// Instead of parallel ALU operations:
wire add_result = a + b;
wire sub_result = a - b;

// Use multiplexed ALU:


wire [7:0] alu_result = (opcode == ADD) ? (a + b) :
(opcode == SUB) ? (a - b) : 0;

// Share registers where possible


wire [7:0] shared_temp = (use_for_addr) ? address :
(use_for_data) ? data_in : 0;

Increase Speed:
• • Add pipeline stages for deep combinational paths
• • Use registered outputs
• • Keep logic between registers simple
• • Example: pipeline[15:0] <= raw_instruction
PART 9: Performance Analysis &
Optimization
9.1 Critical Path Analysis
After synthesis, identify the critical path:
• Open timing report in Vivado/Quartus
• Look for longest combinational path
• Example critical paths in CPU:
• • PC increment to register write
• • ALU input selection to output
• • Memory address decode to data valid

9.2 Timing Constraints


// Example: Vivado XDC constraints file ([Link])

# Clock constraint (100 MHz = 10ns period)


create_clock -period 10.0 -name clk [get_ports clk]

# Input delay (external setup time)


set_input_delay -clock clk 2.0 [get_ports reset]
set_input_delay -clock clk 1.5 [get_ports {data_in[*]}]

# Output delay (external hold time)


set_output_delay -clock clk 3.0 [get_ports {data_out[*]}]
set_output_delay -clock clk 3.0 [get_ports {address[*]}]

# Clock-to-output (internal path delay)


set_max_delay -from [get_clocks clk] -to [get_ports {data_out[*]}] 8.0

# Multi-cycle path (if instruction takes 6 cycles)


set_multicycle_path 6 -from [get_cells instruction_reg]

9.3 Area vs Speed Trade-offs


For Maximum Speed:
• Reduce combinational depth between registers
• Add more pipeline stages
• Accept larger area

For Minimum Area:


• Multiplex hardware (shared ALU, shared ports)
• Reduce register width where possible
• Accept longer clock period

Balanced Approach (recommended):


• 6-stage pipeline (natural instruction phases)
• Pipelined ALU if path is critical
• Single write port (typical for processors)
PART 10: Complete Integration &
Deployment Checklist
Phase Completion Checklist
✓ Phase 1: Verilog Basics (Week 1)
• ☐ Clock divider module working
• ☐ LED blinker generates correct frequency
• ☐ ALU passes all operation tests
• ☐ Testbenches show correct waveforms

✓ Phase 2: Storage (Week 2)


• ☐ Register file read/write functional
• ☐ ROM loads program correctly
• ☐ RAM read/write working
• ☐ PC increments and jumps correctly
• ☐ Instruction decoder extracts fields

✓ Phase 3: CPU Assembly (Week 3)


• ☐ Control FSM transitions correctly
• ☐ All modules instantiate in cpu_top
• ☐ Signals route correctly
• ☐ CPU executes simple instruction sequences

✓ Phase 4: Testbenches (Week 4)


• ☐ Testbench loads programs
• ☐ Tasks print register/memory contents
• ☐ Waveforms show signal transitions
• ☐ Random tests generated successfully

✓ Phase 5: Programs (Week 4)


• ☐ 5+ test programs written in assembly
• ☐ Hex files created correctly
• ☐ Each program produces expected results
• ☐ Edge cases tested

✓ Phase 6: Verification (Week 5)


• ☐ Assertions added to design
• ☐ Functional coverage > 80%
• ☐ Random tests pass
• ☐ All corner cases handled

File Organization Checklist


Mini_RISC_CPU/

├── rtl/ (RTL source files)

│ ├── alu.v (ALU module)

│ ├── register_file.v (Register file)

│ ├── pc.v (Program counter)

│ ├── instruction_memory.v (ROM)

│ ├── data_memory.v (RAM)

│ ├── decoder.v (Instruction decoder)

│ ├── control_unit.v (FSM controller)

│ └── cpu_top.v (Top-level module)

├── tb/ (Testbench files)

│ ├── cpu_tb.v (Main testbench)

│ ├── cpu_verification.sv (SystemVerilog verify)

│ └── Makefile (Simulation commands)

├── programs/ (Test programs)

│ ├── [Link] (Addition test)

│ ├── [Link] (Jump test)

│ ├── [Link] (Memory test)

│ └── [Link] (Loop test)

├── waves/ (Waveform files)

│ └── *.vcd (Simulation dumps)

├── docs/ (Documentation)


│ ├── [Link] (Project overview)

│ ├── [Link] (Instruction set)

│ ├── block_diagram.pdf (Architecture)

│ └── [Link] (Test strategy)

└── constraints/ (FPGA constraints)

└── [Link] (Timing constraints)

Final Verification Steps


1. Compile all RTL modules
2. Run all testbenches
3. Verify waveforms match expected behavior
4. Check code coverage (>95%)
5. Run random test suite (100+ patterns)
6. Verify FPGA synthesis succeeds
7. Check timing requirements met
8. Program FPGA and test hardware
9. Document test results
10. Archive all files

Success Criteria - Final Milestone


• ✓ All 16 instructions execute correctly
• ✓ Register file operates error-free
• ✓ Memory reads/writes verified
• ✓ FSM transitions as designed
• ✓ Test programs produce expected results
• ✓ Functional coverage ≥90%
• ✓ No timing violations
• ✓ FPGA deployment successful
• ✓ Hardware behavior matches simulation
• ✓ Professional documentation complete

You might also like