Trung tâm đào tạo thiết kế vi mạch Semicon


  • ĐĂNG KÝ TÀI KHOẢN ĐỂ TRUY CẬP NHIỀU TÀI LIỆU HƠN!
  • Create an account
    *
    *
    *
    *
    *
    Fields marked with an asterisk (*) are required.
semicon_lab.jpg

Tìm hiểu về Thiết Kế Chip thông qua 8085 Chip

E-mail Print PDF

 

Tổng quan kiến trúc vi xử lý 8085

Vi xử lý 8085 là một vi xử lý 8-bit do Intel phát triển, được sử dụng rộng rãi trong giáo dục và các hệ thống nhúng đơn giản. Sơ đồ khối thể hiện cách các thành phần bên trong phối hợp để xử lý dữ liệu, điều khiển luồng chương trình và giao tiếp với thiết bị ngoại vi.

 

 

1. Khối xử lý trung tâm (Data Processing Unit)

A. Accumulator (A)

  • Là thanh ghi 8-bit trung tâm trong ALU.

  • Tất cả các phép toán số học và logic đều sử dụng hoặc trả kết quả về Accumulator.

  • Ví dụ: Lệnh ADD B sẽ cộng nội dung thanh ghi B với A, kết quả lưu lại trong A.

B. Temporary Register

  • Không truy cập trực tiếp từ phần mềm.

  • Dùng để lưu tạm dữ liệu trong quá trình thực hiện phép toán, đặc biệt là khi xử lý hai toán hạng.

C. ALU (Arithmetic and Logic Unit)

  • Thực hiện các phép toán: cộng, trừ, AND, OR, XOR, so sánh.

  • Kết quả được phản ánh qua các cờ trạng thái (Flags).

D. Flag Flip-Flops

  • Gồm 5 cờ:

    • Sign (S): Bit cao nhất của kết quả.

    • Zero (Z): Kết quả bằng 0.

    • Auxiliary Carry (AC): Dùng trong các phép toán BCD.

    • Parity (P): Số bit 1 trong kết quả là chẵn/lẻ.

    • Carry (CY): Có xảy ra tràn bit hay không.

2. Khối điều khiển và thời gian (Control & Timing Unit)

A. Instruction Register

  • Lưu trữ mã lệnh đang được thực thi.

  • Sau khi lệnh được nạp từ bộ nhớ, nó được giữ tại đây để giải mã.

B. Instruction Decoder

  • Giải mã mã lệnh thành các tín hiệu điều khiển nội bộ.

  • Ví dụ: Lệnh MOV A, B sẽ tạo tín hiệu để truyền dữ liệu từ B sang A.

C. Timing & Control Unit

  • Tạo các tín hiệu điều khiển như RD (Read), WR (Write), ALE (Address Latch Enable).

  • Đồng bộ hóa hoạt động giữa các khối và với bộ nhớ ngoài.

3. Các thanh ghi và bộ đếm

A. General Purpose Registers (B, C, D, E, H, L)

  • Có thể kết hợp thành cặp: BC, DE, HL để xử lý dữ liệu 16-bit.

  • HL thường dùng làm thanh ghi trỏ đến địa chỉ bộ nhớ.

B. Program Counter (PC)

  • Tự động tăng sau mỗi chu kỳ lệnh.

  • Luôn trỏ đến địa chỉ của lệnh kế tiếp cần thực thi.

C. Stack Pointer (SP)

  • Quản lý ngăn xếp trong bộ nhớ.

  • Dùng trong các lệnh CALL, RET, PUSH, POP.

4. Khối giao tiếp ngoại vi

A. Interrupt Control

  • Hỗ trợ 5 ngắt: TRAP, RST7.5, RST6.5, RST5.5, INTR.

  • Cho phép vi xử lý tạm dừng chương trình chính để xử lý sự kiện bên ngoài.

B. Serial I/O Control

  • Giao tiếp nối tiếp qua hai chân: SID (Serial Input Data) và SOD (Serial Output Data).

  • Dùng trong các ứng dụng truyền nhận dữ liệu đơn giản.

5. Khối đệm địa chỉ và dữ liệu

A. Address Buffer

  • Tách riêng phần địa chỉ cao (A8–A15) để truy cập bộ nhớ.

B. Address/Data Buffer

  • Chân A0–A7 vừa dùng để truyền địa chỉ, vừa dùng để truyền dữ liệu (multiplexed).

  • Cần mạch ngoài để tách địa chỉ và dữ liệu (thường dùng latch).

6. Nguồn và xung nhịp

A. Clock Generator

  • Tạo xung nhịp từ thạch anh ngoài (thường 6 MHz).

  • Vi xử lý hoạt động với tần số nội bộ là 3 MHz (do chia đôi).

B. Power Supply

  • Hoạt động với nguồn 5V.

  • Có chân RESET để khởi động lại vi xử lý.

7. Tổng kết học thuật

Sơ đồ này không chỉ là bản vẽ kỹ thuật mà còn là “bản đồ tư duy” giúp người học hiểu cách một vi xử lý thực hiện chương trình. Từ việc nạp lệnh, giải mã, xử lý dữ liệu, đến giao tiếp với thiết bị ngoại vi – tất cả đều được thể hiện rõ ràng.

 

Code Verilog tham khào.

Các module chính trong dự án:

Tên moduleChức năng chính
ALU.v   Thực hiện các phép toán số học và logic
RegisterFile.vQuản lý các thanh ghi đa dụng (B, C, D, E, H, L)
IDecoder.vGiải mã lệnh từ Instruction Register
ControlUnit.vFSM điều khiển luồng thực thi lệnh
Memory.vMô phỏng bộ nhớ chương trình và dữ liệu
MP85.vModule top-level kết nối tất cả các khối
tb_MP85.vTestbench kiểm thử toàn bộ vi xử lý
 
 
 ============================================================================== 

 == ALU.v

 ============================================================================== 

`timescale 1ns / 1ps

module ALU (

    input  alu_enable,

    input  [3:0] alu_op,

    input  [7:0] iA, iB, iF,

    output reg [7:0] oR,

    output reg [7:0] oF,

    output reg       Flag_read_wrbar

);

 

    // Flag positions

    parameter CARRY_F  = 0;

    parameter PARITY_F = 2;

    parameter AUXC_F   = 4;

    parameter ZERO_F   = 6;

    parameter SIGN_F   = 7;

 

    reg aux_carry_add, aux_carry_sub;

    reg [8:0] cmp_result;

    wire [8:0] sum, diff;

    wire parity;

 

    assign sum  = iA + iB + ((alu_op == 4'b0001) ? iF[CARRY_F] : 0); // ADC

    assign diff = iA - iB - ((alu_op == 4'b0011) ? iF[CARRY_F] : 0); // SBB

    assign parity = ~^oR; // Even parity

 

    always @(*) begin

        oF = 0;

        oR = 0;

        Flag_read_wrbar = 1; // Default: do not write to flags

       if(alu_enable) begin

        case (alu_op)

            4'b0000: begin // ADD

                {oF[CARRY_F], oR} = sum;

                Flag_read_wrbar = 0;

            end

            4'b0001: begin // ADC

                {oF[CARRY_F], oR} = sum;

                Flag_read_wrbar = 0;

            end

            4'b0010: begin // SUB

                {oF[CARRY_F], oR} = diff;

                Flag_read_wrbar = 0;

            end

            4'b0011: begin // SBB

                {oF[CARRY_F], oR} = diff;

                Flag_read_wrbar = 0;

            end

            4'b0100: begin // AND

                oR = iA & iB;

                Flag_read_wrbar = 0;

            end

            4'b0101: begin // OR

                oR = iA | iB;

                Flag_read_wrbar = 0;

            end

            4'b0110: begin // XOR

                oR = iA ^ iB;

                Flag_read_wrbar = 0;

            end

            4'b0111: begin // CMP

                cmp_result = iA - iB;

                oF[CARRY_F]  = cmp_result[8];

                oF[ZERO_F]   = (cmp_result[7:0] == 8'd0);

                oF[SIGN_F]   = cmp_result[7];

                oF[PARITY_F] = ~^cmp_result[7:0];

                oF[AUXC_F]   = (iA[3:0] < iB[3:0]);

                oR = 8'hZZ;

                Flag_read_wrbar = 0;

            end

            4'b1000: begin // INR

                oR = iA + 1;

                oF[CARRY_F] = iF[CARRY_F];

                Flag_read_wrbar = 0;

            end

            4'b1001: begin // DCR

                oR = iA - 1;

                oF[CARRY_F] = iF[CARRY_F];

                Flag_read_wrbar = 0;

            end

            default: begin

                oR = 8'hzz;

                oF = 8'hzz;

            end

        endcase

        end

        oF[ZERO_F] = (oR == 0);  

 

        if (alu_op != 4'b0111 && alu_op <= 4'b1001) begin

            oF[ZERO_F]   = (oR == 0);

            oF[SIGN_F]   = oR[7];

            oF[PARITY_F] = parity;

 

            aux_carry_add = ((iA[3:0] + iB[3:0] + (alu_op == 4'b0001 ? iF[CARRY_F] : 0)) > 4'hF);

            aux_carry_sub = ((iA[3:0] - iB[3:0] - (alu_op == 4'b0011 ? iF[CARRY_F] : 0)) < 0);

            oF[AUXC_F] = (alu_op <= 4'b0001) ? aux_carry_add :

                         (alu_op <= 4'b0011) ? aux_carry_sub :

                         0;

        end

    end

 

endmodule

 

 ==============================================================================

ControlUnit.v 

 ============================================================================== 

`timescale 1ns / 1ps

 module ControlUnit(

                    input  wire        clk,

                    input  wire        rst,

                    input  wire        decoder_reg_write,

                    input  wire        decoder_mem_read,

                    input  wire        decoder_mem_write,

                    input  wire        decoder_use_alu,

                    input  wire        decoder_use_immediate,

                    input  wire        decoder_is_branch,

                    input wire [3:0]   decoder_branch_type,

                    input  wire        decoder_halt,

                    input  wire [1:0]  decoder_inst_length,

                    input  wire [2:0]  decoder_src_reg,

                    input  wire [2:0]  decoder_dst_reg,

                    input  wire [3:0]  decoder_alu_op,

                    input  wire [7:0]  mem_out,

                    input wire[7:0]    FLAGS,

                    input wire         decoder_is_mov,

                    output reg         pc_enable,

                    output reg         ir_load,

                    output reg         mar_load,

                    output reg         mar_sel_wz,

                    output reg         mem_read,

                    output reg         mem_write,

                    output reg         reg_write,

                    output reg         alu_enable,

                    output reg  [2:0]  latched_src_reg,

                    output reg  [2:0]  latched_dst_reg,

                    output reg  [3:0]  latched_alu_op,

                    output reg  [7:0]  W,

                    output reg  [7:0]  Z,

                    output reg latched_use_imm,

                    output reg latch_is_mov,

                    output reg latched_is_branch

                );

 

                    localparam [2:0] FETCH = 3'b000, DECODE = 3'b001, FETCH_OP1 = 3'b010,

                                     FETCH_OP2 = 3'b011, MEM_RD = 3'b100, EXEC = 3'b101,

                                     WB = 3'b110, HALT = 3'b111;

                    // Flag positions

    parameter CARRY_F  = 0;

    parameter PARITY_F = 2;

    parameter AUXC_F   = 4;

    parameter ZERO_F   = 6;

    parameter SIGN_F   = 7;

 

                    reg [2:0] state;

                    reg [2:0] t_state;

 

                    reg latched_reg_write, latched_mem_read, latched_mem_write, latched_use_alu;

                    reg  latched_halt;

                    reg [1:0] latched_inst_len;

                    reg [3:0]   latched_branch_type;

 

                    always @(posedge clk or posedge rst) begin

                        if (rst) begin

                            state <= FETCH;

                            t_state <= 0;

                            {pc_enable, ir_load, mar_load, mar_sel_wz, mem_read, mem_write, reg_write, alu_enable,latched_inst_len,latched_src_reg,latched_dst_reg,latched_alu_op,latch_is_mov} <= 0;

                            latched_use_imm<=0;

                            latched_branch_type<=0;

                        end 

                        else begin

                            case (state)

                                FETCH: begin

 

                                    case (t_state)

                                        3'd0: begin mar_sel_wz <= 0; mar_load <= 1; end // Load MAR with PC

                                        3'd1: ; // Wait for MAR to latch

                                        3'd2: begin mem_read <= 1; end

                                        3'd3: ; // Wait for memory

                                        3'd4: begin ir_load <= 1; pc_enable <= 1; end

                                        3'd5:pc_enable <= 0;

                                    endcase

                                    if (t_state == 3'd5) begin

                                        state <= DECODE;

                                        t_state <= 0;

                                    end else t_state <= t_state + 1;

                                end

 

                                DECODE: begin

                                    latched_reg_write <= decoder_reg_write;

                                    latched_mem_read  <= decoder_mem_read;

                                    latched_mem_write <= decoder_mem_write;

                                    latched_use_alu   <= decoder_use_alu;

                                    latched_use_imm   <= decoder_use_immediate;

                                    latched_is_branch <= decoder_is_branch;

                                    latched_halt      <= decoder_halt;

                                    latched_inst_len  <= decoder_inst_length;

                                    latched_src_reg   <= decoder_src_reg;

                                    latched_dst_reg   <= decoder_dst_reg;

                                    latched_alu_op    <= decoder_alu_op;

                                    latch_is_mov<=decoder_is_mov;

                                    latched_branch_type<=decoder_branch_type;

                                    if (decoder_halt) state <= HALT;

                                    else if (decoder_inst_length == 2'd2) state <= FETCH_OP1;

                                    else if (decoder_inst_length == 2'd3) state <= FETCH_OP1;

                                    else if (decoder_mem_read) state <= MEM_RD;

                                    else if (decoder_use_alu) state <= EXEC;

                                    else state <= WB;

                                end

 

                                FETCH_OP1: begin

                                    case (t_state)

                                        3'd0: begin mar_sel_wz <= 0; mar_load <= 1; end

                                        3'd1: ; // Wait

                                        3'd2: begin mem_read <= 1; end

                                        3'd3: ; // Wait

                                        3'd4: begin Z <= mem_out; pc_enable <= 1; end

                                        3'd5:pc_enable <= 0;

                                    endcase

                                    if (t_state == 3'd5) begin

                                        if (latched_inst_len == 2'd2)

                                            state <= (latched_use_alu ? EXEC : WB);

                                        else

                                            state <= FETCH_OP2;

                                        t_state <= 0;

                                    end else t_state <= t_state + 1;

                                end

 

                                FETCH_OP2: begin

                                    case (t_state)

                                        3'd0: begin mar_sel_wz <= 0; mar_load <= 1; end

                                        3'd1: ; // Wait

                                        3'd2: begin mem_read <= 1; end

                                        3'd3: ; // Wait

                                        3'd4: begin W <= mem_out; pc_enable <= 1; end

                                        3'd5:pc_enable <= 0;

                                        3'd6:;

                                        3'd7:;

 

                                    endcase

                     if (t_state == 3'd5) begin

    if (latched_is_branch) begin

        case (latched_branch_type)

            4'b0000: mar_sel_wz <= 1; // JMP (unconditional)

            4'b0001: if (FLAGS[ZERO_F])       mar_sel_wz <= 1;

            4'b0010: if (!FLAGS[ZERO_F])      mar_sel_wz <= 1;

            4'b0011: if (FLAGS[CARRY_F])      mar_sel_wz <= 1;

            4'b0100: if (!FLAGS[CARRY_F])     mar_sel_wz <= 1;

            4'b0101: if (!FLAGS[SIGN_F])      mar_sel_wz <= 1;

            4'b0110: if (FLAGS[SIGN_F])       mar_sel_wz <= 1;

            4'b0111: if (FLAGS[PARITY_F])     mar_sel_wz <= 1;

            4'b1000: if (!FLAGS[PARITY_F])    mar_sel_wz <= 1;

            default: ; // Do nothing special

        endcase

 

    end 

    end

    if (t_state == 3'd7)  begin

    if(latched_is_branch)begin    

     state <= FETCH; // Always go to FETCH after branch condition is checked

         {pc_enable, ir_load, mar_load, mar_sel_wz, mem_read, mem_write, reg_write, alu_enable,latched_inst_len,latched_src_reg,latched_dst_reg,latched_alu_op,latch_is_mov} <= 0;

                            latched_use_imm<=0;

                            latched_branch_type<=0;

        t_state <= 0;

    end

    else begin

        state <= (latched_mem_read ? MEM_RD : EXEC);

        t_state <= 0;

        end

    end

 

   else begin

    t_state <= t_state + 1;

end

 

 

                               end 

 

                                MEM_RD: begin

                                    case (t_state)

                                        3'd0: begin mar_sel_wz <= 1; mar_load <= 1; end

                                        3'd1: ; // Wait

                                        3'd2: ; // Wait

                                        3'd3: begin mem_read <= 1; end

                                        3'd4: ; // Wait

                                    endcase

                                    if (t_state == 3'd4) begin

                                        state <= (latched_use_alu ? EXEC : WB);

                                        t_state <= 0;

                                    end else t_state <= t_state + 1;

                                end

 

                                EXEC:  begin

                                    case (t_state)

            //                            3'd0:;

                                        3'd0:begin  alu_enable <= 1;end

 

                                    endcase

                                     if (t_state == 3'd0) begin

                                         state <= WB;

                                    t_state <= 0;

                                    end 

                                    else t_state <= t_state + 1;

 

                                end

 

                            WB: begin

                    reg_write <= latched_reg_write;  // keep high for 3 cycles

                    mem_write <= latched_mem_write;

 

                    case (t_state)

                        3'd0: ;

                        3'd1: ;

                    endcase

                        if(t_state==3'd1)begin

           {pc_enable, ir_load, mar_load, mar_sel_wz, mem_read, mem_write, reg_write, alu_enable,latched_inst_len,latched_src_reg,latched_dst_reg,latched_alu_op,latch_is_mov} <= 0;

                            latched_use_imm<=0;

                            latched_branch_type<=0; 

                            state <= FETCH;

                            t_state <= 0;

                        end 

                        else t_state <= t_state + 1;

 

                end

 

 

                                     HALT: begin

                                    pc_enable <= 0;

                                end

 

                                default: begin 

                                state <= FETCH;

            {pc_enable, ir_load, mar_load, mar_sel_wz, mem_read, mem_write, reg_write, alu_enable,latched_inst_len,latched_src_reg,latched_dst_reg,latched_alu_op,latch_is_mov} <= 0;

                            latched_use_imm<=0;

                            latched_branch_type<=0;                  

                             end

                            endcase

                        end

                    end

endmodule

 

 ==============================================================================

IDecoder.v

 ============================================================================== 

 `timescale 1ns / 1ps

module IDecoder(

    input  wire [7:0] IR,

    output reg        reg_write,

    output reg        mem_read,

    output reg        mem_write,

    output reg        use_alu,

    output reg [3:0]  alu_op,

    output reg        use_immediate,

    output reg [2:0]  src_reg,

    output reg [2:0]  dst_reg,

    output reg        halt,

    output reg        is_branch,

    output reg  [3:0] branch_type,

    output reg [1:0]  inst_length,

    output reg        is_mov

);

 

    // Opcodes

    localparam [3:0]

        OP_ADD = 4'b0000,

        OP_ADC = 4'b0001,

        OP_SUB = 4'b0010,

        OP_SBB = 4'b0011,

        OP_AND = 4'b0100,

        OP_OR  = 4'b0101,

        OP_XOR = 4'b0110,

        OP_CMP = 4'b0111,

        OP_INR = 4'b1000,

        OP_DCR = 4'b1001;

 

    always @(*) begin

        // Defaults

        reg_write      = 0;

        mem_read       = 0;

        mem_write      = 0;

        use_alu        = 0;

        alu_op         = 4'b0000;

        use_immediate  = 0;

        src_reg        = 3'b000;

        dst_reg        = 3'b000;

        halt           = 0;

        is_branch      = 0;

        branch_type = 0;

        inst_length    = 1;

        is_mov         = 0;

 

        casez (IR)

 

        // === MOV R1, R2 ===

        8'b01??????: begin

            reg_write = 1;

            dst_reg   = IR[5:3];

            src_reg   = IR[2:0];

            is_mov    = 1;

        end

 

        // === MVI R, D8 ===

        8'b00???110: begin

            reg_write     = 1;

            use_immediate = 1;

            dst_reg       = IR[5:3];

            inst_length   = 2;

        end

 

        // === ADD R ===

        8'b10000???: begin

            reg_write = 1;

            use_alu   = 1;

            alu_op    = OP_ADD;

            dst_reg   = 3'b111;      // A

            src_reg   = IR[2:0];     // R

        end

 

        // === ADC R ===

        8'b10001???: begin

            reg_write = 1;

            use_alu   = 1;

            alu_op    = OP_ADC;

            dst_reg   = 3'b111;

            src_reg   = IR[2:0];

        end

 

        // === SUB R ===

        8'b10010???: begin

            reg_write = 1;

            use_alu   = 1;

            alu_op    = OP_SUB;

            dst_reg   = 3'b111;

            src_reg   = IR[2:0];

        end

 

        // === SBB R ===

        8'b10011???: begin

            reg_write = 1;

            use_alu   = 1;

            alu_op    = OP_SBB;

            dst_reg   = 3'b111;

            src_reg   = IR[2:0];

        end

 

        // === ANA R ===

        8'b10100???: begin

            reg_write = 1;

            use_alu   = 1;

            alu_op    = OP_AND;

            dst_reg   = 3'b111;

            src_reg   = IR[2:0];

        end

 

        // === XRA R ===

        8'b10101???: begin

            reg_write = 1;

            use_alu   = 1;

            alu_op    = OP_XOR;

            dst_reg   = 3'b111;

            src_reg   = IR[2:0];

        end

 

        // === ORA R ===

        8'b10110???: begin

            reg_write = 1;

            use_alu   = 1;

            alu_op    = OP_OR;

            dst_reg   = 3'b111;

            src_reg   = IR[2:0];

        end

 

        // === CMP R ===

        8'b10111???: begin

            reg_write = 0;

            use_alu   = 1;

            alu_op    = OP_CMP;

            dst_reg   = 3'b111;

            src_reg   = IR[2:0];

        end

 

        // === INR R ===

        8'b00???100: begin

            reg_write = 1;

            use_alu   = 1;

            alu_op    = OP_INR;

            dst_reg   = IR[5:3];

            src_reg   = IR[5:3];

        end

 

        // === DCR R ===

        8'b00???101: begin

            reg_write = 1;

            use_alu   = 1;

            alu_op    = OP_DCR;

            dst_reg   = IR[5:3];

            src_reg   = IR[5:3];

        end

 

        // === LDA addr ===

        8'h3A: begin

            mem_read    = 1;

            reg_write   = 1;

            dst_reg     = 3'b111; // A

            inst_length = 2'b11;

        end

 

        // === STA addr ===

        8'h32: begin

            mem_write   = 1;

            src_reg     = 3'b111; // A

            inst_length = 2'b11;

        end

 

        // === HLT ===

        8'h76: begin

            halt = 1;

        end

 

              // === JUMP instructions ===

        8'hC3: begin // JMP addr

            is_branch   = 1;

            branch_type = 4'b0000;

            inst_length = 2'b11;

        end

        8'hCA: begin // JZ addr

            is_branch   = 1;

            branch_type = 4'b0001;

            inst_length = 2'b11;

        end

        8'hC2: begin // JNZ addr

            is_branch   = 1;

            branch_type = 4'b0010;

            inst_length = 2'b11;

        end

        8'hDA: begin // JC addr

            is_branch   = 1;

            branch_type = 4'b0011;

            inst_length = 2'b11;

        end

        8'hD2: begin // JNC addr

            is_branch   = 1;

            branch_type = 4'b0100;

            inst_length = 2'b11;

        end

        8'hF2: begin // JP addr

            is_branch   = 1;

            branch_type = 4'b0101;

            inst_length = 2'b11;

        end

        8'hFA: begin // JM addr

            is_branch   = 1;

            branch_type = 4'b0110;

            inst_length = 2'b11;

        end

        8'hEA: begin // JPE addr

            is_branch   = 1;

            branch_type = 4'b0111;

            inst_length = 2'b11;

        end

        8'hE2: begin // JPO addr

            is_branch   = 1;

            branch_type = 4'b1000;

            inst_length = 2'b11;

        end

        default: begin

            // Invalid or unimplemented opcode

        end

        endcase

    end

 

endmodule

 ==============================================================================

=== File memory.v  

 ============================================================================== 

 `timescale 1ns / 1ps

// Memory Module with preloaded instruction/data for 8085

module memory #(

    parameter MEM_DEPTH = 512

)(

    input  wire        clk,

    input  wire        rst,

    input  wire        mem_read,

    input  wire        mem_write,

    input  wire [15:0] address,

    input  wire [7:0]  data_in,

    output reg [7:0]  data_out

);

 

    integer i;

    reg [7:0] mem [0:MEM_DEPTH-1];

always @(posedge clk)

begin

   data_out <= (mem_read && address < MEM_DEPTH) ? mem[address] : 8'd0;

end

    always @(posedge clk) begin

if (rst) begin

    for (i = 0; i < MEM_DEPTH; i = i + 1)

        mem[i] <= 8'd0;

 

    // === Load A with 0x0F ===

    mem[16'h0000] <= 8'h3E;  // MVI A, 0F

    mem[16'h0001] <= 8'h0F;

 

    // === Load C with 0x05 ===

    mem[16'h0002] <= 8'h0E;  // MVI C, 05

    mem[16'h0003] <= 8'h05;

 

    // === INR C ===

    mem[16'h0004] <= 8'h0C;  // INR C  ? C = 06

 

    // === DCR C ===

    mem[16'h0005] <= 8'h0D;  // DCR C  ? C = 05

 

    // === CMP C ===

    mem[16'h0006] <= 8'hB9;  // CMP C  ? flags updated (A = 0F, C = 05)

 

    // === ANA C ===

    mem[16'h0007] <= 8'hA1;  // ANA C  ? A = 0F & 05 = 05

 

    // === ORA C ===

    mem[16'h0008] <= 8'hB1;  // ORA C  ? A = 05 | 05 = 05

 

    // === XRA C ===

    mem[16'h0009] <= 8'hA9;  // XRA C  ? A = 05 ^ 05 = 00 ? Zero flag set

 

    // === Load C with 0x01 again ===

    mem[16'h000A] <= 8'h0E;  // MVI C, 01

    mem[16'h000B] <= 8'h01;

 

    // === Load A with 0x05 again ===

    mem[16'h000C] <= 8'h3E;  // MVI A, 05

    mem[16'h000D] <= 8'h05;

 

    // === SUB C ===

    mem[16'h000E] <= 8'h91;  // SUB C  ? A = 05 - 01 = 04

 

    // === HALT ===

    mem[16'h000F] <= 8'h76;  // HLT

end

 

         else if (mem_write && address < MEM_DEPTH) begin

            mem[address] <= data_in;

        end

    end

endmodule

 
 `timescale 1ns / 1ps
    
    module MP85(
        input wire clk,
        input wire rst
    );
    
        // === Program Counter ===
        reg [15:0] PC;
        reg [15:0] MAR;
        reg [7:0] datareg;
        wire is_mov;
        // === WZ Temporary Register Pair ===
        wire [7:0] W_internal, Z_internal;
        wire [15:0] WZ = {W_internal, Z_internal};
    
        // === Instruction Register ===
        reg [7:0] IR;
    
        // === Memory Interface ===
        wire [7:0] mem_data_out;
        reg [7:0] mem_data_in;
        wire mem_read, mem_write;
    
        // === Register File Interface ===
        wire [7:0] reg_data1, reg_data2;
        wire [2:0] src_reg, dst_reg;
        wire reg_write;
    
        // === ALU Interface ===
        wire [7:0] alu_out, alu_flags;
        wire use_alu, use_immediate;
        wire [3:0] alu_op;
        wire flags_write_en;
    
        // === Flags Register ===
        reg [7:0] FLAGS;
    
        // === Instruction Properties ===
        wire inst_is_2B, inst_is_3B;
        wire halt, is_branch;
        wire [3:0] branch_type;
    
        // === Control Unit Signals ===
        wire pc_inc, ir_load, wz_load;
        wire mar_load, reg_write_ctrl, mem_read_ctrl, mem_write_ctrl;
        wire alu_enable;
        wire [2:0] latched_src_reg, latched_dst_reg;wire latched_use_imm;
        wire[3:0] latched_alu_op;
        wire latch_is_mov;
        wire latched_is_barnch;
        // === Decoder ===
        IDecoder decoder (
            .IR(IR),
            .reg_write(reg_write),
            .mem_read(mem_read),
            .mem_write(mem_write),
            .use_alu(use_alu),
            .alu_op(alu_op),
            .use_immediate(use_immediate),
            .src_reg(src_reg),
            .dst_reg(dst_reg),
            .halt(halt),
            .is_branch(is_branch),
            .branch_type(branch_type),
            .inst_length({inst_is_3B, inst_is_2B}),
            .is_mov(is_mov)
        );
    
        reg [7:0] temp;
        always @(posedge clk) begin
            if (alu_enable)
                temp <= alu_out;
            else if (latched_use_imm && reg_write_ctrl)
                temp <= Z_internal;
            else if (mem_read_ctrl)
                temp <= datareg;
            else
                temp <= 8'h00;
        end
    
        // === Register File ===
        registers regfile (
            .clk(clk),
            .rst(rst),
            .write_en(reg_write_ctrl),
            .read_addr1(latched_src_reg),
            .read_addr2(latched_dst_reg),
            .write_addr(latched_dst_reg),
            .write_data(temp),
            .read_data1(reg_data1),
            .read_data2(reg_data2),
            .latch_is_mov(latch_is_mov)
        );
    
        // === Memory ===
        memory mem (
            .clk(clk),
            .rst(rst),
            .mem_read(mem_read_ctrl),
            .mem_write(mem_write_ctrl),
            .address(MAR),
            .data_in(mem_data_in),
            .data_out(mem_data_out)
        );
    
        // === ALU ===
        ALU alu (
            .alu_enable(alu_enable),
            .alu_op(latched_alu_op),
            .iA(reg_data2),
            .iB(latched_use_imm ? Z_internal : reg_data1),
            .iF(FLAGS),
            .oR(alu_out),
            .oF(alu_flags),
            .Flag_read_wrbar(flags_write_en)
        );
    
        // === Control Logic Unit ===
        ControlUnit control_unit (
            .clk(clk),
            .rst(rst),
            .decoder_is_mov(is_mov),
            .decoder_src_reg(src_reg),
            .decoder_dst_reg(dst_reg),
            .decoder_alu_op(alu_op),
            .decoder_use_alu(use_alu),
            .decoder_use_immediate(use_immediate),
            .decoder_reg_write(reg_write),
            .decoder_mem_read(mem_read),
            .decoder_mem_write(mem_write),
            .decoder_is_branch(is_branch),
          
            .decoder_inst_length({inst_is_3B, inst_is_2B}),
            .mem_out(mem_data_out),
            .ir_load(ir_load),
            .pc_enable(pc_inc),
            .mar_load(mar_load),
            .mar_sel_wz(wz_load),
            .mem_read(mem_read_ctrl),
            .mem_write(mem_write_ctrl),
            .reg_write(reg_write_ctrl),
            .alu_enable(alu_enable),
            .latched_src_reg(latched_src_reg),
            .latched_dst_reg(latched_dst_reg),
            .latched_alu_op(latched_alu_op),
            .W(W_internal),
            .Z(Z_internal),
            .latched_use_imm(latched_use_imm),
            .latch_is_mov(latch_is_mov),
              .decoder_branch_type(branch_type),
            .FLAGS(FLAGS),
            .latched_is_branch(latched_is_branch)
        );
    
        // === Sequential Logic (Registers) ===
        always @(posedge clk or posedge rst) begin
            if (rst) begin
                PC     <= 16'h0000;
                IR     <= 8'h00;
                FLAGS  <= 8'h00;
                MAR    <= 16'h0000;
            end else begin
                if (mar_load)
                    MAR <= ((inst_is_3B || inst_is_2B) && wz_load) ? WZ : PC;
    
                if (mem_read_ctrl)
                    datareg <= mem_data_out;
    
                if (ir_load)
                    IR <= mem_data_out;
                    
                   if(latched_is_branch && wz_load)  PC<=WZ;
                   
                if (pc_inc && !(is_branch && wz_load))begin
                   PC <= PC + 16'h0001;
                  end
                if (!flags_write_en && use_alu)
                    FLAGS <= alu_flags;
            end
        end
    
        // === Data Input Selection for Memory Writes ===
        always @(*) begin
            if (mem_write_ctrl)
                mem_data_in = reg_data1;
            else
                mem_data_in = 8'h00;
        end
    
    endmodule
 
 ============================================================================== 
 
 `timescale 1ns / 1ps
module registers(
    input  wire        clk,
    input  wire        rst,
    input  wire        write_en,
    input wire    latch_is_mov,
//    input wire         alu_enable,
    input  wire [2:0]  read_addr1,
    input  wire [2:0]  read_addr2,
    input  wire [2:0]  write_addr,
    input  wire [7:0]  write_data,
    output reg  [7:0]  read_data1,
    output reg  [7:0]  read_data2,

    // ? Flattened debug output for testbench
    output wire [63:0] debug_regs_flat
);

    reg [7:0] regs [0:7]; // B, C, D, E, H, L, M, A

    // Write & reset
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            regs[0] <= 8'h00;
            regs[1] <= 8'h00;
            regs[2] <= 8'h00;
            regs[3] <= 8'h00;
            regs[4] <= 8'h00;
            regs[5] <= 8'h00;
            regs[6] <= 8'h00;
            regs[7] <= 8'h03;
        end 
        else if (write_en && write_addr != 3'b110) begin
        if(latch_is_mov) regs[read_addr2]<=regs[read_addr1];
           else  regs[write_addr] <= write_data;
        end
    end

    // Read logic
    always @(*) begin
        read_data1 = (read_addr1 == 3'b110) ? 8'hZZ : regs[read_addr1];
        read_data2 = (read_addr2 == 3'b110) ? 8'hZZ : regs[read_addr2];
    end

    // ? Flatten array into 64-bit wire
    assign debug_regs_flat = {
        regs[7], // A
        regs[6], // M (dummy)
        regs[5], // L
        regs[4], // H
        regs[3], // E
        regs[2], // D
        regs[1], // C
        regs[0]  // B
    };

endmodule
 
 ============================================================================== 
// Testbench file 
 ============================================================================== 
 `timescale 1ns / 1ps

module tb_Top8085;

    reg clk;
    reg rst;

    // Instantiate the top module
    MP85 uut (
        .clk(clk),
        .rst(rst)
    );

    // Clock generation: 10ns period
    always #5 clk = ~clk;

    integer cycle;

    initial begin
        $display("==== Starting 8085 Simulation ====");
        $dumpfile("dump.vcd");
        $dumpvars(0, tb_Top8085);

        // Initial conditions
        clk = 0;
        rst = 1;
        #20;
        rst = 0;

        // Simulate 200 cycles
        for (cycle = 0; cycle < 200; cycle = cycle + 1) begin
            @(posedge clk);
            $display("Cycle %0d:", cycle);
            $display("A: %h", uut.regfile.debug_regs_flat[63:56]);
            $display("M: %h", uut.regfile.debug_regs_flat[55:48]);
            $display("L: %h", uut.regfile.debug_regs_flat[47:40]);
            $display("H: %h", uut.regfile.debug_regs_flat[39:32]);
            $display("E: %h", uut.regfile.debug_regs_flat[31:24]);
            $display("D: %h", uut.regfile.debug_regs_flat[23:16]);
            $display("C: %h", uut.regfile.debug_regs_flat[15:8]);
            $display("B: %h", uut.regfile.debug_regs_flat[7:0]);
            $display("-------------------------------");
        end

        $display("==== Simulation Completed ====");
        $finish;
    end

endmodule

 

Last Updated ( Saturday, 27 September 2025 16:26 )  

Related Articles

Chat Zalo