CPU0-Mini:3 個指令的版本--從檔案讀取指令

Verilog

基本語法

型態

全域變數

基本元件

多樣的寫法

指定

assign

always

initial

運算式

分枝

迴圈

模組

函數

Task

陣列

輸出入

觀察

真值表

測試程式

訊息顯示

注意事項

模擬程序

硬體工程

程式範例

Xor

Xor3

全加器

加法器

加減器

快速加法器

乘法器

ALU

閂鎖器

脈衝偵測

計數器

多工器

暫存器群

記憶體

延遲問題

浮點數

狀態機

程式計數器

CPU0-Mini

CPU0

pipeline

工具

QuartusII

Icarus

Veritek

訊息

相關網站

參考文獻

最新修改

簡體版

English

輸入指令檔:cpu0m3.hex

00 1F 00 18 // 0000       LD   R1, K1
00 2F 00 10 // 0004       LD   R2, K0
00 3F 00 14 // 0008       LD   R3, SUM
13 22 10 00 // 000C LOOP: ADD  R2, R2, R1
13 33 20 00 // 0010       ADD  R3, R3, R2
26 FF FF F4 // 0014       JMP  LOOP
00 00 00 00 // 0018 K0:   WORD 0
00 00 00 01 // 001C K1:   WORD 1
00 00 00 00 // 0020 SUM:  WORD 0

Verilog 程式:cpu0m3io.v

module computer0m(input clock, reset, output [2:0] tick, 
                  output [31:0] ir, pc, mar, mdr, 
                  inout [31:0] dbus, output m_en, m_rw);

cpu0m cpu (.clock(clock), .reset(reset), .pc(pc), .tick(tick), .ir(ir), 
.mar(mar), .mdr(mdr), .dbus(dbus), .m_en(m_en), .m_rw(m_rw));

memory0m mem (.clock(clock), .reset(reset), .en(m_en), .rw(m_rw), 
.abus(mar), .dbus_in(mdr), .dbus_out(dbus));

endmodule         

module cpu0m(input clock, reset, output reg [2:0] tick, 
             output reg [31:0] ir, pc, mar, mdr,
             inout [31:0] dbus, output reg m_en, m_rw);
    reg signed [31:0] R [0:15];
    reg [7:0] op;
    reg [3:0] ra, rb, rc;
    reg signed [11:0] cx12;
    reg signed [15:0] cx16;
    reg signed [23:0] cx24;
    reg signed [31:0] addr32, A, B, C, aluOut, ipc; // ipc:instruction PC

    `define PC  R[15]
    `define LD  8'h00
    `define ST  8'h01
    `define ADD 8'h13
    `define JMP 8'h26    

    always @(posedge clock) begin
        if (reset) begin
            `PC = 0;
            tick = 0;
          end
        else begin
            tick = tick+1;
            m_en = 0;
            case (tick)
            // 指令擷取階段 Tick 1..3 : memory.read(m[PC])
                1:    begin  // Tick 1:將 PC 丟到位址匯流排上
                    mar = `PC; // MAR = PC
                    m_rw = 1; // m_rw=1 is read mode, read(m[MAR]) => read(m[PC])
                    m_en = 1;
                    ipc  = `PC;
                    `PC = `PC+4; // PC = PC + 4
                end
                2:    begin  // Tick 2:ir = m[PC]
                    mdr = dbus;
                    ir = mdr; // IR = dbus = m[PC]
                    {op,ra,rb,rc,cx12} = ir;
                    cx24 = ir[23:0];
                    cx16 = ir[15:0];
                end
                3:    begin  // Tick 3:取出暫存器 R[ra], R[rb], R[rc] 內容
                    m_en = 0;
                    A = R[ra];
                    B = R[rb];
                    C = R[rc];
                end
            // 指令執行階段 Tick 4..6 : execute(IR)
                4:    begin 
                    case (op) // 解讀 OP: Tick 4
                        `LD: begin // 指令:LD ra, rb, cx ; 語意:R[ra] = m[rb+cx]
                            mar = B + cx16; // mar = 讀取位址 = R[rb]+cx
                            m_rw = 1; // 讀取模式:read 
                            m_en = 1;
                        end
                        `ST: begin // 指令:ST ra, rb, cx ; 語意:m[rb+cx]=R[ra]
                            mar = B + cx16;  // 寫入位址 = R[rb]+cx
                            mdr = A; // 寫入資料:R[ra]
                            m_rw = 0; // 寫入模式:write
                            m_en = 1;
                        end
                        `ADD: begin // 指令:ADD ra, rb, rc ; 語意:R[ra]=R[rb]+R[rc]
                            aluOut = B+C; // 執行加法
                        end
                        `JMP: begin // 指令:JMP cx ; 語意:PC = PC+cx
                            addr32 = cx24; // 取出 cx 並轉為 32 位元有號數
                            `PC = `PC+addr32; // 跳躍目標位址=PC+cx
                        end
                        default:    begin
                        end
                    endcase
                end
                5:    begin // 解讀 OP: Tick 5
                    case (op) // LD ra, rb, cx ; R[ra] = R[rb+cx] ; mdr = R[rb+cx]
                        `LD: begin // 指令:LD ra, rb, cx ; 語意:R[ra] = m[rb+cx]
                            mdr = dbus; // 取得記憶體傳回的 dbus = m[rb+cx]
                            R[ra] = mdr; // 存入到目標暫存器 R[ra] 中
                            m_en = 0; // 讀取完畢
                        end
                        `ST: begin // 指令:ST ra, rb, cx ; 語意:m[rb+cx]=R[ra]
                            m_en = 0; // 寫入完畢
                        end
                        `ADD: begin // 指令:ADD ra, rb, rc ; 語意:R[ra]=R[rb]+R[rc]
                            R[ra] = aluOut;
                        end
                        `JMP: begin // 指令:JMP cx ; 語意:PC = PC+cx
                        end
                        default:    begin
                        end
                    endcase
                end                
                6:    begin
                    case (op) // 解讀 OP: Tick 6; 列印
                        `LD: $display("%4dns %8x : LD  %2x,%2x,%4x; R[%x]=%4d", 
                                        $stime, ipc, ra, rb, cx16, ra, R[ra]);
                        `ST: $display("%4dns %8x : ST  %2x,%2x,%4x; R[%x]=%4d", 
                                        $stime, ipc, ra, rb, cx16, ra, R[ra]);
                        `ADD:$display("%4dns %8x : ADD %2x,%2x,%4x; R[%x]=%4d, B=%4d, C=%4d", 
                                        $stime, ipc, ra, rb, rc, ra, R[ra], B, C);
                        `JMP:$display("%4dns %8x : JMP %10d; PC=%8x", 
                                        $stime, ipc, cx24, R[15]);
                    endcase
                    tick = 0;
                end
                default:    begin
                end
            endcase
        end
        pc = `PC;
    end
endmodule

module memory0m(input clock, reset, en, rw, 
            input [31:0] abus, dbus_in, output [31:0] dbus_out);
reg [7:0] m [0:128];
reg [31:0] data;
integer i;

initial begin
end
    always @(reset) 
    begin
        if (reset == 1) begin
            $readmemh("cpu0m3.hex", m);
            for (i=0; i < 128; i=i+4) begin
                if (m[i] !== 8'hx)
                    $display("%8x: %x", i, {m[i], m[i+1], m[i+2], m[i+3]});
            end
        end
    end

    always @(clock or abus or en or rw or dbus_in) 
    begin
        if (abus >=0 && abus < 125) begin
            if (en == 1 && rw == 0) begin // r_w==0:write
                data = dbus_in;
                {m[abus], m[abus+1], m[abus+2], m[abus+3]} = dbus_in;
            end
            else if (en == 1 && rw == 1) // r_w==1:read
                data = {m[abus], m[abus+1], m[abus+2], m[abus+3]};
            else
                data = 32'hZZZZZZZZ;
        end else
            data = 32'hZZZZZZZZ;
    end
    assign dbus_out = data;
endmodule

module main;
reg clock;
reg reset;
wire [2:0] tick;
wire [31:0] pc, ir, mar, mdr, dbus;
wire m_en, m_rw;
wire [7:0] op;
wire signed [31:0] A, B, C, aluOut;
wire [3:0] ra, rb, rc;

computer0m DUT (.clock(clock), .reset(reset), .pc(pc), .tick(tick), 
.ir(ir), .mar(mar), .mdr(mdr), .dbus(dbus), .m_en(m_en), .m_rw(m_rw));

initial
begin
  clock = 0;
  reset = 1;
end

initial #20 reset = 0;

always #10 clock=clock+1;

initial #5000 $finish;

endmodule

執行結果

D:\cpu0m>iverilog cpu0m3io.v -o cpu0m3io

D:\cpu0m>vvp cpu0m3io
WARNING: cpu0m3io.v:137: $readmemh(cpu0m3.hex): Not enough words in the file for
 the requested range [0:128].
00000000: 001f0018
00000004: 002f0010
00000008: 003f0014
0000000c: 13221000
00000010: 13332000
00000014: 26fffff4
00000018: 00000000
0000001c: 00000001
00000020: 00000000
 130ns 00000000 : LD   1, f,0018; R[1]=   1
 250ns 00000004 : LD   2, f,0010; R[2]=   0
 370ns 00000008 : LD   3, f,0014; R[3]=   0
 490ns 0000000c : ADD  2, 2,   1; R[2]=   1, B=   0, C=   1
 610ns 00000010 : ADD  3, 3,   2; R[3]=   1, B=   0, C=   1
 730ns 00000014 : JMP        -12; PC=0000000c
 850ns 0000000c : ADD  2, 2,   1; R[2]=   2, B=   1, C=   1
 970ns 00000010 : ADD  3, 3,   2; R[3]=   3, B=   1, C=   2
1090ns 00000014 : JMP        -12; PC=0000000c
1210ns 0000000c : ADD  2, 2,   1; R[2]=   3, B=   2, C=   1
1330ns 00000010 : ADD  3, 3,   2; R[3]=   6, B=   3, C=   3
1450ns 00000014 : JMP        -12; PC=0000000c
1570ns 0000000c : ADD  2, 2,   1; R[2]=   4, B=   3, C=   1
1690ns 00000010 : ADD  3, 3,   2; R[3]=  10, B=   6, C=   4
1810ns 00000014 : JMP        -12; PC=0000000c
1930ns 0000000c : ADD  2, 2,   1; R[2]=   5, B=   4, C=   1
2050ns 00000010 : ADD  3, 3,   2; R[3]=  15, B=  10, C=   5
2170ns 00000014 : JMP        -12; PC=0000000c
2290ns 0000000c : ADD  2, 2,   1; R[2]=   6, B=   5, C=   1
2410ns 00000010 : ADD  3, 3,   2; R[3]=  21, B=  15, C=   6
2530ns 00000014 : JMP        -12; PC=0000000c
2650ns 0000000c : ADD  2, 2,   1; R[2]=   7, B=   6, C=   1
2770ns 00000010 : ADD  3, 3,   2; R[3]=  28, B=  21, C=   7
2890ns 00000014 : JMP        -12; PC=0000000c
3010ns 0000000c : ADD  2, 2,   1; R[2]=   8, B=   7, C=   1
3130ns 00000010 : ADD  3, 3,   2; R[3]=  36, B=  28, C=   8
3250ns 00000014 : JMP        -12; PC=0000000c
3370ns 0000000c : ADD  2, 2,   1; R[2]=   9, B=   8, C=   1
3490ns 00000010 : ADD  3, 3,   2; R[3]=  45, B=  36, C=   9
3610ns 00000014 : JMP        -12; PC=0000000c
3730ns 0000000c : ADD  2, 2,   1; R[2]=  10, B=   9, C=   1
3850ns 00000010 : ADD  3, 3,   2; R[3]=  55, B=  45, C=  10
3970ns 00000014 : JMP        -12; PC=0000000c
4090ns 0000000c : ADD  2, 2,   1; R[2]=  11, B=  10, C=   1
4210ns 00000010 : ADD  3, 3,   2; R[3]=  66, B=  55, C=  11
4330ns 00000014 : JMP        -12; PC=0000000c
4450ns 0000000c : ADD  2, 2,   1; R[2]=  12, B=  11, C=   1
4570ns 00000010 : ADD  3, 3,   2; R[3]=  78, B=  66, C=  12
4690ns 00000014 : JMP        -12; PC=0000000c
4810ns 0000000c : ADD  2, 2,   1; R[2]=  13, B=  12, C=   1
4930ns 00000010 : ADD  3, 3,   2; R[3]=  91, B=  78, C=  13

Facebook

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License