2014年12月29日 星期一

J1 Forth CPU 研究之五:算術邏輯單元(ALU)

這是一系列文章中的第五篇,這系列的文章是要解讀 J1 CPU 的設計以及在其上的 Forth 語言的使用法。

這篇談的是 j1 CPU 的 Verilog 程式中的算術邏輯單元(ALU),請見以下檔案:

src/hardware/verilog/j1.v


為了方便說明,以下程式的次序不一定和 j1.v 中一致。

  wire [15:0] insn;
  wire [15:0] immediate = { 1'b0, insn[14:0] };
  wire is_alu = (insn[15:13] == 3'b011);
  wire is_lit = (insn[15]);


  reg [3:0] st0sel;
  always @*
  begin
    case (insn[14:13])
      2'b00: st0sel = 0;          // ubranch
      2'b01: st0sel = 1;          // 0branch
      2'b10: st0sel = 0;          // call
      2'b11: st0sel = insn[11:8]; // ALU
      default: st0sel = 4'bxxxx;
    endcase
  end



  always @*
  begin
    if (insn[15])
      _st0 = immediate;
    else
      case (st0sel)
        4'b0000: _st0 = st0;
        4'b0001: _st0 = st1;
        4'b0010: _st0 = st0 + st1;
        4'b0011: _st0 = st0 & st1;
        4'b0100: _st0 = st0 | st1;
        4'b0101: _st0 = st0 ^ st1;
        4'b0110: _st0 = ~st0;
        4'b0111: _st0 = {16{(st1 == st0)}};
        4'b1000: _st0 = {16{($signed(st1) < $signed(st0))}};
        4'b1001: _st0 = st1 >> st0[3:0];
        4'b1010: _st0 = st0 - 1;
        4'b1011: _st0 = rst0;
        4'b1100: _st0 = |st0[15:14] ? io_din : ramrd;
        4'b1101: _st0 = st1 << st0[3:0];
        4'b1110: _st0 = {rsp, 3'b000, dsp};
        4'b1111: _st0 = {16{(st1 < st0)}};
        default: _st0 = 16'hxxxx;
      endcase
  end

以上總共 40 行,加上之前的 90 行,我們已經看懂了 j1.v 的 130/200。接下來的兩篇處理RAM 及 memory mapped I/O,我們對 j1.v 的探索就算完成。

沒有留言:

張貼留言