Cpu0p2

Verilog

基本語法

型態

全域變數

基本元件

多樣的寫法

指定

assign

always

initial

運算式

分枝

迴圈

模組

函數

Task

陣列

輸出入

觀察

真值表

測試程式

訊息顯示

注意事項

模擬程序

硬體工程

程式範例

Xor

Xor3

全加器

加法器

加減器

快速加法器

乘法器

ALU

閂鎖器

脈衝偵測

計數器

多工器

暫存器群

記憶體

延遲問題

浮點數

狀態機

程式計數器

CPU0-Mini

CPU0

pipeline

工具

QuartusII

Icarus

Veritek

訊息

相關網站

參考文獻

最新修改

簡體版

English

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

module ifetch(input clock, reset, i_ready, output o_ready, input next_ack, output ack_prev);
    always @(posedge clock) begin
//        $display("m_state=%d pc1=%x", m_state, pc1);
        case (state) 
            `IDLE: begin
                if (cpu.m_en == 0) begin
                    cpu.m_rw = `READ; // 讀取模式:read 
                    cpu.m_en = 1;     // 啟動讀取
                    cpu.m_w1 = `INT32;
                    cpu.pc = cpu.pc + 4;
                    cpu.mar = cpu.pc;
                    $display("%-4d:ifetch(abus=pc=%x)", $stime, cpu.pc);
                end
            end
            `WAIT_ACK: begin
                if (next_ack) begin
                    state <= IDLE;
                end
            end
        endcase
    end
endmodule

module idecode(input clock, reset, i_ready, output o_ready, input next_ack, output ack_prev);
    reg state
    reg signed [11:0] cx12;
    reg signed [15:0] cx16;
    reg signed [23:0] cx24;
    always @(posedge clock) begin
        case (state) 
            `IDLE: begin
                cpu.ir = cpu.mdr; // 取得指令
                cpu.m_en = 0; // 讀取完畢
                {cpu.op,cpu.a,cpu.b,cpu.c,cx12} = cpu.ir;
                cx24 = cpu.ir[23:0];
                cx16 = cpu.ir[15:0];
                cpu.c5  = cpu.ir[4:0];
                cpu.c12 = cx12; // 取出 cx12 並轉為 32 位元有號數 c12
                cpu.c16 = cx16; // 取出 cx16 並轉為 32 位元有號數 c16
                cpu.c24 = cx24; // 取出 cx24 並轉為 32 位元有號數 c24
                $display("%-8d:idecode(mdr=%x ir=%x op=%x a=%x b=%x c=%x cx12=%x)", $stime, cpu.mdr, cpu.ir, cpu.op, cpu.a, cpu.b, cpu.c, cpu.c12);
            end
            `WAIT_ACK:begin
                if (next_ack) begin
                    state <= IDLE;
                end
            end
        endcase
    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, m_state, );
  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 = `BUSY;
                    #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 = `IDLE;
                end else begin// r_w==1:read
                    m_state = `BUSY;
                    #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 = `IDLE;
                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

Facebook

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