Cpu0p (撰寫中,未完成)

Verilog

基本語法

型態

全域變數

基本元件

多樣的寫法

指定

assign

always

initial

運算式

分枝

迴圈

模組

函數

Task

陣列

輸出入

觀察

真值表

測試程式

訊息顯示

注意事項

模擬程序

硬體工程

程式範例

Xor

Xor3

全加器

加法器

加減器

快速加法器

乘法器

ALU

閂鎖器

脈衝偵測

計數器

多工器

暫存器群

記憶體

延遲問題

浮點數

狀態機

程式計數器

CPU0-Mini

CPU0

pipeline

工具

QuartusII

Icarus

Veritek

訊息

相關網站

參考文獻

最新修改

簡體版

English

cpu0p0.3.zip

輸入程式:cpu0p.hex

00 1F 00 24 // 0000       LD   R1, K1
00 2F 00 1C // 0004       LD   R2, K0
00 3F 00 20 // 0008       LD   R3, SUM
08 40 00 0A // 000C        LDI  R4, 10
13 22 10 00 // 0010 LOOP: ADD  R2, R2, R1
13 33 20 00 // 0014       ADD  R3, R3, R2
10 24 00 00 // 0018       CMP  R2, R4
21 FF FF F0 // 001C       JNE  LOOP
2C 00 00 00 // 0020       RET
00 00 00 00 // 0024 K0:   WORD 0
00 00 00 01 // 0028 K1:   WORD 1
00 00 00 00 // 002C SUM:  WORD 0

Verilog 程式

// 定義:寬度形態常數
`define INT32 2'b11     // 寬度 32 位元
`define INT24 2'b10     // 寬度 24 位元
`define INT16 2'b01     // 寬度 16 位元
`define BYTE  2'b00     // 寬度  8 位元
// 記憶體狀態
`define WAITING 2'b00 // 閒置中
`define READING 2'b01 // 讀取中
`define WRITING 2'b10 // 寫入中
// 記憶體讀寫
`define READ 1'b1     // 讀取
`define WRITE 1'b0     // 寫入

module ifetch(input clock, reset);
    always @(posedge clock) begin
//        $display("m_state=%d pc1=%x", m_state, pc1);
        if (cpu0.m_state == `WAITING && cpu0.m_en == 0) begin
            cpu0.m_rw = `READ; // 讀取模式:read 
            cpu0.m_en = 1;     // 啟動讀取
            cpu0.m_w1 = `INT32;
            cpu0.pc = cpu0.pc + 4;
            cpu0.mar = cpu0.pc;
            $display("%-4d:ifetch(abus=pc=%x)", $stime, cpu0.pc);
        end
    end
endmodule

module idecode(input clock, reset);
    reg signed [11:0] cx12;
    reg signed [15:0] cx16;
    reg signed [23:0] cx24;
    always @(posedge clock) begin
//        if (cpu0.m_state == `WAITING && cpu0.m_en == 1) begin
        cpu0.ir = cpu0.mdr; // 取得指令
        cpu0.m_en = 0; // 讀取完畢
        {cpu0.op,cpu0.a,cpu0.b,cpu0.c,cx12} = cpu0.ir;
        cx24 = cpu0.ir[23:0];
        cx16 = cpu0.ir[15:0];
        cpu0.c5  = cpu0.ir[4:0];
        cpu0.c12 = cx12; // 取出 cx12 並轉為 32 位元有號數 c12
        cpu0.c16 = cx16; // 取出 cx16 並轉為 32 位元有號數 c16
        cpu0.c24 = cx24; // 取出 cx24 並轉為 32 位元有號數 c24
        $display("%-8d:idecode(mdr=%x ir=%x op=%x a=%x b=%x c=%x cx12=%x)", $stime, cpu0.mdr, cpu0.ir, cpu0.op, cpu0.a, cpu0.b, cpu0.c, cpu0.c12);
//      end
    end
endmodule

module cpu0(input clock, reset, input [1:0] m_state, output [31:0] pc, abus, dbus, output reg m_en, m_rw, output reg [1:0] m_w1);
    reg signed [31:0] R [0:15];
    reg [7:0] op;
    reg [3:0] a, b, c;
    reg [4:0] c5;
    reg signed [31:0] c12, c16, c24, Ra, Rb, Rc, ipc; // ipc:instruction PC
    reg [31:0] pc, ir, mar, mdr;

initial begin
  pc = 0;
  m_en = 0;
end

assign abus = mar;
always @(m_en, dbus) begin
    if (m_en && m_rw==`READ && dbus !== 32'hZ)
        mdr = dbus;
end

  ifetch if1(clock, reset);
  idecode id1(clock, reset);
//  tick2 t2(.clock(clock), .reset(reset), .dbus(dbus), .ir(ir), .m_en(m_en));
//  controller ctrl(.clock(clock), .reset(reset), .pc(pc), .abus(abus), .dbus(dbus), .ir(ir), .m_en(m_en), .m_rw(m_rw));
endmodule

module memory0(input clock, reset, m_en, m_rw, input [1:0] m_w1, 
                input [31:0] abus, inout [31:0] dbus, output [1:0] m_state);
reg [7:0] m [0:258];
reg [31:0] data;
reg m_state = `WAITING;

integer i;
initial begin
    $readmemh("cpu0p.hex", m);
    for (i=0; i < 255; i=i+4) begin
       $display("%8x: %8x", i, {m[i], m[i+1], m[i+2], m[i+3]});
    end
end

    always @(abus or m_en or m_rw or m_state or dbus) 
    begin
//        $display("%d:1 memory trigger(m_en=%b, m_rw=%b, m_state=%b, abus=%x)", $stime, m_en, m_rw, m_state, abus);
        if (abus >=0 && abus <= 255) begin
//            $display("%d:2 memory trigger(m_en=%b, m_rw=%b, m_state=%b)", $stime, m_en, m_rw, m_state);
            if (m_en == 1) begin
                if (m_rw == 0) begin // r_w==0:write
                    m_state = `WRITING;
                    #10;
                    data = dbus;
                    case (m_w1)
                        `BYTE:  {m[abus]} = dbus[7:0];
                        `INT16: {m[abus], m[abus+1] } = dbus[15:0];
                        `INT24: {m[abus], m[abus+1], m[abus+2]} = dbus[24:0];
                        `INT32: {m[abus], m[abus+1], m[abus+2], m[abus+3]} = dbus;
                    endcase
                    $display("%-8d:write(abus=%x data=%x)", $stime, abus, data);
                    m_state = `WAITING;
                end else begin// r_w==1:read
                    m_state = `READING;
                    #10;
                    case (m_w1)
                        `BYTE:  data = {8'h00  , 8'h00,   8'h00,   m[abus]      };
                        `INT16: data = {8'h00  , 8'h00,   m[abus], m[abus+1]    };
                        `INT24: data = {8'h00  , m[abus], m[abus+1], m[abus+2]  };
                        `INT32: data = {m[abus], m[abus+1], m[abus+2], m[abus+3]};
                    endcase
                    $display("%-8d:read(abus=%x data=%x)", $stime, abus, data);
                    m_state = `WAITING;
                end
            end else // m_en==0
                data = 32'hZZZZZZZZ;
        end else // a > 255
            data = 32'hZZZZZZZZ;
    end
    assign dbus = data;
endmodule

module main;
reg clock, reset;
wire [31:0] abus, dbus, pc;
wire m_en, m_rw;
wire [1:0] m_w1, m_state;

cpu0 cpu(.clock(clock), .reset(reset), .m_state(m_state), .pc(pc), .abus(abus), .dbus(dbus), .m_en(m_en), .m_rw(m_rw), .m_w1(m_w1));
memory0 mem(.clock(clock), .reset(reset), .m_en(m_en), .m_rw(m_rw), .m_state(m_state), .m_w1(m_w1), .abus(abus), .dbus(dbus));

initial
begin
  clock = 0;
  reset = 1;
  #10 reset=0;  
  #1000 $finish;
end

always #50 begin
  clock=clock+1;
//  $monitor("%4dns pc=%x", $stime, pc);  
end
endmodule

執行結果

D:\oc\pipepc>iverilog cpu0p.v -o cpu0p

D:\oc\pipepc>vvp cpu0p
WARNING: cpu0p.v:81: $readmemh(cpu0p.hex): Not enough words in the file for the
requested range [0:258].
00000000: 001f0024
00000004: 002f001c
00000008: 003f0020
0000000c: 0840000a
00000010: 13221000
00000014: 13332000
00000018: 10240000
0000001c: 21fffff0
00000020: 2c000000
00000024: 00000000
00000028: 00000001
0000002c: 00000000
00000030: xxxxxxxx
00000034: xxxxxxxx
00000038: xxxxxxxx
0000003c: xxxxxxxx
00000040: xxxxxxxx
00000044: xxxxxxxx
00000048: xxxxxxxx
0000004c: xxxxxxxx
00000050: xxxxxxxx
00000054: xxxxxxxx
00000058: xxxxxxxx
0000005c: xxxxxxxx
00000060: xxxxxxxx
00000064: xxxxxxxx
00000068: xxxxxxxx
0000006c: xxxxxxxx
00000070: xxxxxxxx
00000074: xxxxxxxx
00000078: xxxxxxxx
0000007c: xxxxxxxx
00000080: xxxxxxxx
00000084: xxxxxxxx
00000088: xxxxxxxx
0000008c: xxxxxxxx
00000090: xxxxxxxx
00000094: xxxxxxxx
00000098: xxxxxxxx
0000009c: xxxxxxxx
000000a0: xxxxxxxx
000000a4: xxxxxxxx
000000a8: xxxxxxxx
000000ac: xxxxxxxx
000000b0: xxxxxxxx
000000b4: xxxxxxxx
000000b8: xxxxxxxx
000000bc: xxxxxxxx
000000c0: xxxxxxxx
000000c4: xxxxxxxx
000000c8: xxxxxxxx
000000cc: xxxxxxxx
000000d0: xxxxxxxx
000000d4: xxxxxxxx
000000d8: xxxxxxxx
000000dc: xxxxxxxx
000000e0: xxxxxxxx
000000e4: xxxxxxxx
000000e8: xxxxxxxx
000000ec: xxxxxxxx
000000f0: xxxxxxxx
000000f4: xxxxxxxx
000000f8: xxxxxxxx
000000fc: xxxxxxxx
50      :idecode(mdr=xxxxxxxx ir=xxxxxxxx op=xx a=x b=x c=x cx12=xxxxxxxx)
50  :ifetch(abus=pc=00000004)
60      :read(abus=00000004 data=002f001c)
150     :idecode(mdr=002f001c ir=002f001c op=00 a=2 b=f c=0 cx12=0000001c)
250     :idecode(mdr=002f001c ir=002f001c op=00 a=2 b=f c=0 cx12=0000001c)
250 :ifetch(abus=pc=00000008)
260     :read(abus=00000008 data=003f0020)
350     :idecode(mdr=003f0020 ir=003f0020 op=00 a=3 b=f c=0 cx12=00000020)
450     :idecode(mdr=003f0020 ir=003f0020 op=00 a=3 b=f c=0 cx12=00000020)
450 :ifetch(abus=pc=0000000c)
460     :read(abus=0000000c data=0840000a)
550     :idecode(mdr=0840000a ir=0840000a op=08 a=4 b=0 c=0 cx12=0000000a)
650     :idecode(mdr=0840000a ir=0840000a op=08 a=4 b=0 c=0 cx12=0000000a)
650 :ifetch(abus=pc=00000010)
660     :read(abus=00000010 data=13221000)
750     :idecode(mdr=13221000 ir=13221000 op=13 a=2 b=2 c=1 cx12=00000000)
850     :idecode(mdr=13221000 ir=13221000 op=13 a=2 b=2 c=1 cx12=00000000)
850 :ifetch(abus=pc=00000014)
860     :read(abus=00000014 data=13332000)
950     :idecode(mdr=13332000 ir=13332000 op=13 a=3 b=3 c=2 cx12=00000000)
D:\oc\pipepc>

參考文獻

  1. Hardware pipelining example, Written by Yann Sionneau, Tuesday, 01 November 2011 11:24

Facebook

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