Outline — click to expand大綱 — 點擊展開アウトライン — クリックで展開
1. FIFO1. FIFO1. FIFO
2. Temperature Monitor2. 溫度監測系統2. 温度モニタ
3. AMD2901 Microcontroller3. AMD2901 微控制器3. AMD2901 マイクロコントローラ
4. Summary4. 總結4. まとめ
← DCIC Study Guides← DCIC 自學指南← DCIC 自学ガイド
EE5733 Digital Communication IC Design · Lecture 7EE5733 數位通訊積體電路設計 · 第 7 講EE5733 デジタル通信 IC 設計 · 第 7 講

Design Examples設計範例設計例

A FIFO-based temperature monitor system and the AMD2901 4-bit bit-slice microcontroller, built module by module in synthesizable Verilog.以 FIFO 為核心的溫度監測系統,以及 AMD2901 四位元 bit-slice 微控制器,逐一模組地用可合成的 Verilog 建構 —— 設計範例自學指南。FIFO を中核とする温度モニタシステムと、AMD2901 4 ビット・ビットスライス・マイクロコントローラを、合成可能な Verilog でモジュールごとに組み上げる。

Contents目錄目次

  1. First-In First-Out (FIFO)先進先出緩衝器(FIFO)先入れ先出し(FIFO)
  2. Design Example I: Temperature Monitor System設計範例一:溫度監測系統設計例 I:温度モニタシステム
  3. Design Example II: AMD2901 4-Bit Microcontroller設計範例二:AMD2901 四位元微控制器設計例 II:AMD2901 4 ビット・マイクロコントローラ
  4. Summary and Exam Checklist總結與考前檢查清單まとめと試験前チェックリスト

1. First-In First-Out (FIFO)1. 先進先出緩衝器(FIFO)1. 先入れ先出し(FIFO)

1.1 Interface and internal organization1.1 介面與內部組織1.1 インタフェースと内部構成

Port埠ポートDirection方向方向Meaning意義意味
Data_in[11:0]in輸入入力Data path into the FIFO進入 FIFO 的資料路徑FIFO への入力データパス
Data_out[11:0]out輸出出力Data path from the FIFO自 FIFO 輸出的資料路徑FIFO からの出力データパス
stack_empty, stack_fullout輸出出力Flags asserted high when empty / full空/滿時被拉高的旗標空/満杯のとき High になるフラグ
clk, rstin輸入入力External clock and reset外部時脈與重置訊號外部クロックとリセット
write_to_stack, read_from_stackin輸入入力Write / read requests寫入/讀出請求書き込み/読み出し要求
stack[7]...stack[1]stack[0] write_ptrread_ptr Data_in[11:0]write_to_stackread_from_stackData_out[11:0] ptr_diff = number of stored words
Circular buffer: write_ptr points to the next free slot, read_ptr to the oldest word. Both wrap from 7 to 0 automatically because they are 3 bits wide.環狀緩衝區:write_ptr 指向下一個空的位置,read_ptr 指向最舊的資料字。兩者都是 3 位元寬,所以會自動由 7 繞回 0。リングバッファ:write_ptr は次の空きスロットを、read_ptr は最も古いワードを指す。いずれも 3 ビット幅なので 7 から 0 へ自動的に折り返す。

1.2 Verilog model1.2 Verilog 模型1.2 Verilog モデル

module FIFO (Data_out, Data_in, stack_empty, stack_full,
             clk, rst, write_to_stack, read_from_stack);
  parameter stack_width     = 12;   // width of stack and data paths
  parameter stack_height    = 8;    // height of stack (in # of words)
  parameter stack_ptr_width = 3;    // width of pointer to address stack

  output [stack_width-1:0]   Data_out;
  output                     stack_empty, stack_full;
  input  [stack_width-1:0]   Data_in;
  input                      clk, rst;
  input                      write_to_stack, read_from_stack;

  reg    [stack_ptr_width-1:0] read_ptr, write_ptr;   // pointers for reading and writing
  reg    [stack_ptr_width:0]   ptr_diff;              // gap between ptrs (0..8 needs 4 bits)
  reg    [stack_width-1:0]     Data_out;
  reg    [stack_width-1:0]     stack [stack_height-1:0];   // memory array

  assign stack_empty = (ptr_diff == 0)            ? 1'b1 : 1'b0;
  assign stack_full  = (ptr_diff == stack_height) ? 1'b1 : 1'b0;

  always @ (posedge clk or posedge rst) begin: data_transfer
    if (rst) Data_out = 0;
    else if ((read_from_stack) && (!write_to_stack) && (!stack_empty))
      Data_out <= stack[read_ptr];
    else if ((write_to_stack) && (!read_from_stack) && (!stack_full))
      stack[write_ptr] <= Data_in;
  end  // data_transfer

  always @ (posedge clk or posedge rst) begin: update_stack_ptrs
    if (rst) begin
      read_ptr  <= 0;
      write_ptr <= 0;
      ptr_diff  <= 0;
    end
    else if ((write_to_stack) && (!stack_full) && (!read_from_stack)) begin
      write_ptr <= write_ptr + 1;     // address for next clock edge
      ptr_diff  <= ptr_diff + 1;
    end
    else if ((!write_to_stack) && (!stack_empty) && (read_from_stack)) begin
      read_ptr  <= read_ptr + 1;
      ptr_diff  <= ptr_diff - 1;
    end
  end  // update_stack_ptrs
endmodule
Design points設計要點設計のポイント
  • ptr_diff is one bit wider than the pointers so it can tell empty (0) from full (8).ptr_diff 比指標多一個位元,才能區分空(0)與滿(8)。ptr_diff はポインタより 1 ビット広く、空(0)と満杯(8)を区別できる。
  • Writes into a full FIFO and reads from an empty FIFO are ignored.對已滿的 FIFO 寫入、對已空的 FIFO 讀出,都會被忽略。満杯の FIFO への書き込みと、空の FIFO からの読み出しは無視される。
  • Simultaneous read and write requests do nothing in this model (both branches require the other request low).在這個模型中,同時提出讀與寫請求不會有任何動作(兩個分支都要求對方的請求為低電位)。このモデルでは読み出しと書き込みを同時に要求しても何も起きない(どちらの分岐も相手の要求が Low であることを条件にしている)。
  • Data_out is registered: data appears one clock after the read request is sampled.Data_out 是暫存輸出:資料在讀出請求被取樣後的下一個時脈才出現。Data_out はレジスタ出力であり、読み出し要求がサンプルされた 1 クロック後にデータが現れる。
Practice 1 — FIFO trace練習 1 — FIFO 追蹤練習 1 — FIFO トレース

Problem: After reset, the following requests are sampled on successive rising edges: W(10), W(20), W(30), R, R+W(40), R, R, R. Give ptr_diff, stack_empty and Data_out after each edge.問題:重置之後,下列請求依序在連續的上升邊緣被取樣:W(10)、W(20)、W(30)、R、R+W(40)、R、R、R。請寫出每個邊緣之後的 ptr_diff、stack_empty 與 Data_out。問題:リセット後、次の要求が連続する立ち上がりエッジでサンプルされる:W(10)、W(20)、W(30)、R、R+W(40)、R、R、R。各エッジ後の ptr_diff、stack_empty、Data_out を示せ。

Click to reveal solution點擊展開解答クリックで解答を表示
Edge時脈邊緣エッジRequest請求要求ptr_diffemptyempty(空)empty(空)Data_out
1W 10100
2W 20200
3W 30300
4R2010
5R + W2010 (ignored)10(被忽略)10(無視)
6R1020
7R0130
8R0130 (empty, ignored)30(已空,被忽略)30(空のため無視)

Word 40 is lost at edge 5 because the model discards simultaneous requests.資料 40 在第 5 個邊緣遺失,因為這個模型會丟棄同時發生的讀寫請求。この模型は同時要求を破棄するため、ワード 40 は 5 番目のエッジで失われる。

2. Design Example I: Temperature Monitor System2. 設計範例一:溫度監測系統2. 設計例 I:温度モニタシステム

2.1 System overview2.1 系統概觀2.1 システム概要

Temperature Monitor Unit DataGenerator_1DataGenerator_2 (1) DataRegister(1) DataRegister (2) DataConverter(2) DataConverter (3) DataFilter(3) DataFilter (5) FIFO(5) FIFO (4) FIFOControllerselect, read
Two 12-bit channels, each: register → °C-to-°F converter → 4-sample averaging filter → FIFO. The FIFO controller chooses which FIFO to read (select) and drives data_out.兩條 12 位元通道,每條依序為:暫存器 → 攝氏轉華氏轉換器 → 四筆平均濾波器 → FIFO。FIFO 控制器以 select 決定讀取哪一個 FIFO,並驅動 data_out。12 ビットのチャネルが 2 本あり、各チャネルはレジスタ → ℃→℉ 変換器 → 4 サンプル平均フィルタ → FIFO の順に並ぶ。FIFO コントローラは select でどちらの FIFO を読むかを選び、data_out を駆動する。

2.2 Ckt 1 — data register2.2 電路 1 — 資料暫存器2.2 回路 1 — データレジスタ

module temp_register (temp_out, temp_in, clk, rst);
  output [11:0] temp_out;
  input  [11:0] temp_in;
  input         clk, rst;
  reg    [11:0] temp_out;

  always @ (posedge clk or posedge rst)
    begin
      if (rst == 1) temp_out = 0;
      else          temp_out = temp_in;
    end
endmodule

Stores (latches) the input data: twelve DFFs with asynchronous reset (the netlist shows an inverter on rst because the library flip-flops have active-low reset).把輸入資料存起來:十二個帶非同步重置的 D 型正反器(netlist 上 rst 前多了一個反相器,因為元件庫裡的正反器是低電位有效重置)。入力データを保持する。非同期リセット付きの D フリップフロップ 12 個である(ライブラリのフリップフロップがアクティブ Low リセットのため、netlist では rst にインバータが付く)。

2.3 Ckt 2 — data converter2.3 電路 2 — 資料轉換器2.3 回路 2 — データ変換器

Celsius to Fahrenheit攝氏轉華氏摂氏から華氏へ $$T_F = \tfrac{9}{5}\,T_C + 32,\qquad \tfrac{9}{5} = 1.8 \approx 1.75 = 1 + \tfrac12 + \tfrac14 = 2 - \tfrac14$$
Description寫法記述Status狀態可否
assign temp_out = temp_in * 9 / 5 + 32;Non-synthesizable (general divider)不可合成(需要通用除法器)合成不可(汎用の除算器が必要)
assign temp_out = (9 * temp_in) / 5 + 32;Non-synthesizable不可合成合成不可
parameter k1 = 2'b10; k2 = 3'b100; k32 = 6'b100000;
assign temp_out = (temp_in + temp_in / k1 + temp_in / k2) + k32;
Synthesizable (divide by powers of 2) but incorrect: computes 1.75·T + 32, the common approximation in IC design可合成(除數都是 2 的冪次),但結果不精確:算出的是 1.75·T + 32,這是 IC 設計裡常用的近似合成可能(除数が 2 のべき乗)だが正確ではない。計算されるのは 1.75·T + 32 で、IC 設計でよく使われる近似である
Alternative 1: 1.75 = 1 + 0.5 + 0.25寫法一:1.75 = 1 + 0.5 + 0.25方式 1:1.75 = 1 + 0.5 + 0.25
module temp_converter (temp_out, temp_in);
  input  [11:0] temp_in;
  output [11:0] temp_out;
  parameter k32 = 6'b100000;    // decimal 32

  // F = 9/5 C + 32, 9/5 = 1.8 ~ 1 + .5 + .25
  assign temp_out = temp_in + (temp_in >> 1)
                  + (temp_in >> 2) + k32;
endmodule
Alternative 2: 1.75 = 2 − 0.25寫法二:1.75 = 2 − 0.25方式 2:1.75 = 2 − 0.25
assign temp_out = ((temp_in << 1)
                 - (temp_in >> 2)) + k32;

Shifts are free wiring, so each version costs only adders / one subtractor. Alternative 2 uses one fewer adder.移位只是接線,不花面積,所以兩種寫法的成本只有加法器/一個減法器。寫法二少用一個加法器。シフトは配線だけで済むため、どちらの方式も加算器(と減算器 1 個)しか必要としない。方式 2 は加算器が 1 個少ない。

2.4 Ckt 3 — data filter2.4 電路 3 — 資料濾波器2.4 回路 3 — データフィルタ

module temp_filter (av_temp, clk, rst, temp_data);
  output [11:0] av_temp;
  input         clk;
  input  [11:0] temp_data;
  reg    [11:0] temp [3:0];

  always @ (negedge clk or posedge rst)
    if (rst) begin
      temp[0] <= 0; temp[1] <= 0; temp[2] <= 0; temp[3] <= 0;
    end
    else begin: data_pipeline
      temp[3] <= temp_data;
      temp[2] <= temp[3];
      temp[1] <= temp[2];
      temp[0] <= temp[1];
    end

  assign av_temp = (temp[3] + temp[2] + temp[1] + temp[0]) >> 2;
endmodule

A 4-deep, 12-bit shift register (48 flip-flops, clocked on the falling edge) and an adder tree followed by >> 2 = divide by 4: a moving average of the last four samples. (rst is missing from the slide's port declarations; add input rst;.)一個 4 級、12 位元的移位暫存器(48 個正反器,以時脈下降緣觸發),後面接加法樹再做 >> 2,也就是除以 4:最近四筆樣本的移動平均。(投影片的埠宣告漏了 rst,要補上 input rst;。)4 段・12 ビットのシフトレジスタ(フリップフロップ 48 個、クロックの立ち下がりエッジ動作)に加算器ツリーを続け、最後に >> 2(4 で割る)を行う。すなわち直近 4 サンプルの移動平均である。(スライドのポート宣言には rst が抜けているので input rst; を追加する。)

Width of the sum總和的位元寬度総和のビット幅

The operands of >> are context-determined: the sum is computed at the width of the largest operand / target, 12 bits, so it overflows before the shift when the samples are large. Safe form: wire [13:0] sum = temp[3] + temp[2] + temp[1] + temp[0]; assign av_temp = sum[13:2];>> 的運算元寬度是由上下文決定的:總和會以最寬的運算元/目標寬度(這裡是 12 位元)計算,所以樣本一大就會在移位之前先溢位。安全的寫法是:wire [13:0] sum = temp[3] + temp[2] + temp[1] + temp[0]; assign av_temp = sum[13:2];>> のオペランド幅は文脈で決まる。総和は最も広いオペランド/代入先の幅、すなわち 12 ビットで計算されるため、サンプルが大きいとシフトの前にオーバフローする。安全な書き方は wire [13:0] sum = temp[3] + temp[2] + temp[1] + temp[0]; assign av_temp = sum[13:2]; である。

2.5 Ckt 4 — FIFO controller2.5 電路 4 — FIFO 控制器2.5 回路 4 — FIFO コントローラ

module fifo_controller (data_out, data_1, data_2, select, read, write,
                        empty_1, full_1, read_1, empty_2, full_2, read_2);
  input  [11:0] data_1, data_2;
  input  [1:0]  select;
  input         read, full_1, empty_1, full_2, empty_2;
  output [11:0] data_out;
  output        read_1, read_2, write;
  reg    [11:0] data_out;
  reg           read_1, read_2, write;

  always @ (select or data_1 or data_2 or read or full_1
            or empty_1 or full_2 or empty_2) begin
    read_1 = 0;
    read_2 = 0;
    if (read == 1)
      begin
        write = 0;
        case (select)
          2'b01: begin data_out = data_1; read_1 <= 1; end
          2'b10: begin data_out = data_2; read_2 <= 1; end
          2'b00: begin data_out = {empty_1, empty_2, full_1, full_2}; end
          default: data_out = 12'bz;
        endcase
      end
    else if (read == 0)
      begin
        data_out = 12'bz;
        write = 1;
      end
    else data_out = 12'bz;
  end
endmodule
readselectdata_outread_1 / read_2write
101data from FIFO 1來自 FIFO 1 的資料FIFO 1 からのデータ1 / 00
110data from FIFO 2來自 FIFO 2 的資料FIFO 2 からのデータ0 / 10
100status {empty_1, empty_2, full_1, full_2} (zero-extended)狀態 {empty_1, empty_2, full_1, full_2}(高位元補 0)ステータス {empty_1, empty_2, full_1, full_2}(上位をゼロ拡張)0 / 00
111high-Z高阻抗ハイインピーダンス0 / 00
0—high-Z高阻抗ハイインピーダンス0 / 01 (both FIFOs write)1(兩個 FIFO 都寫入)1(両方の FIFO が書き込む)

A combinational block: every output is assigned on every 0/1 path, so no latches. The final else only covers read = x in simulation. The 12'bz assignments become tri-state output buffers.這是一個組合邏輯區塊:每條 0/1 路徑都指定了所有輸出,所以不會推論出閂鎖(latch)。最後那個 else 只是為了模擬時的 read = x。12'bz 的指定會合成為三態輸出緩衝器。これは組合せ論理ブロックである。0/1 のどの経路でもすべての出力に代入しているため、ラッチは推論されない。最後の else はシミュレーション時の read = x に備えるだけである。12'bz の代入はトライステート出力バッファになる。

2.6 Top level2.6 頂層模組2.6 トップレベル

module temp_monitor_unit (channel_1, channel_2, select, clk, rst, read, data_out);
  output [11:0] data_out;
  input  [11:0] channel_1, channel_2;
  input  [1:0]  select;
  input         clk, rst, read;
  wire   [11:0] temp1_out, temp2_out, temp_conv1, temp_conv2, av_temp1, av_temp2;
  wire   [11:0] Data_out1, Data_out2;

  temp_register   M1 (temp1_out, channel_1, clk, rst);      // (1)
  temp_register   M2 (temp2_out, channel_2, clk, rst);
  temp_converter  M3 (temp_conv1, temp1_out);              // (2)
  temp_converter  M4 (temp_conv2, temp2_out);
  temp_filter     M5 (av_temp1, clk, rst, temp_conv1);      // (3)
  temp_filter     M6 (av_temp2, clk, rst, temp_conv2);

  FIFO M7 (Data_out1, av_temp1, stack_empty1, stack_full1, clk, rst,
           write_to_stack, read_from_stack1);               // (5)
  FIFO M8 (Data_out2, av_temp2, stack_empty2, stack_full2, clk, rst,
           write_to_stack, read_from_stack2);

  fifo_controller M9 (data_out, Data_out1, Data_out2,       // (4)
           select, read, write_to_stack, stack_empty1, stack_full1,
           read_from_stack1, stack_empty2, stack_full2, read_from_stack2);
endmodule
Implicit nets and port order隱含接線與埠的順序暗黙のネットとポート順序

stack_empty1, write_to_stack etc. are never declared, so they become implicit 1-bit wires — fine here, but a typo would silently create a new net. Also check the positional order against each module header: M9's list is (..., write, empty_1, full_1, read_1, ...), which must match the controller's port order exactly. Named port binding (.write(write_to_stack)) avoids this class of bug.stack_empty1、write_to_stack 等從未宣告,所以會變成隱含的 1 位元 wire —— 在這裡沒問題,但打錯字就會悄悄生出一條新的 net。另外要把位置式連接的順序對照各模組的標頭:M9 的清單是 (..., write, empty_1, full_1, read_1, ...),必須與控制器的埠順序完全一致。改用具名連接(.write(write_to_stack))就能避開這一類錯誤。stack_empty1 や write_to_stack などは宣言されていないため、暗黙の 1 ビット wire になる。ここでは問題ないが、綴りを誤ると新しいネットが黙って作られてしまう。位置指定による接続順序も各モジュールのヘッダと照合すること。M9 のリストは (..., write, empty_1, full_1, read_1, ...) であり、コントローラのポート順序と完全に一致していなければならない。名前付きポート接続(.write(write_to_stack))を使えば、この種のバグは避けられる。

Practice 2 — Conversion error練習 2 — 轉換誤差練習 2 — 変換誤差

Problem: Compute the exact °F and the alternative-1 result for $T_C$ = 10, 37, 100 (integer arithmetic, shifts truncate). Suggest a closer shift-add approximation of 1.8.問題:對 $T_C$ = 10、37、100,分別算出精確的華氏值與寫法一的結果(整數運算,移位會無條件捨去)。並提出一個更接近 1.8 的移位相加近似。問題:$T_C$ = 10、37、100 について、正確な華氏の値と方式 1 の結果を求めよ(整数演算、シフトは切り捨て)。さらに 1.8 により近いシフト加算近似を提案せよ。

Click to reveal solution點擊展開解答クリックで解答を表示
TCExact精確值厳密値T + T>>1 + T>>2 + 32Error誤差誤差
105010 + 5 + 2 + 32 = 49−1
3798.637 + 18 + 9 + 32 = 96−2.6
100212100 + 50 + 25 + 32 = 207−5

The error grows as 0.05·T plus truncation. Closer: $1 + \tfrac12 + \tfrac14 + \tfrac1{32} + \tfrac1{64} = 1.796875$, i.e. add (temp_in >> 5) + (temp_in >> 6) — two more adders; T = 100 gives 100 + 50 + 25 + 3 + 1 + 32 = 211.誤差大約以 0.05·T 的速度增加,再加上截斷的部分。更接近的近似是 $1 + \tfrac12 + \tfrac14 + \tfrac1{32} + \tfrac1{64} = 1.796875$,也就是再加上 (temp_in >> 5) + (temp_in >> 6) —— 多兩個加法器;T = 100 時得到 100 + 50 + 25 + 3 + 1 + 32 = 211。誤差は 0.05·T に切り捨て分を加えた大きさで増えていく。より近い近似は $1 + \tfrac12 + \tfrac14 + \tfrac1{32} + \tfrac1{64} = 1.796875$、すなわち (temp_in >> 5) + (temp_in >> 6) を加える形で、加算器が 2 個増える。T = 100 では 100 + 50 + 25 + 3 + 1 + 32 = 211 となる。

Practice 3 — Filter overflow練習 3 — 濾波器溢位練習 3 — フィルタのオーバフロー

Problem: All four filter registers hold 2000. What does the slide's av_temp evaluate to, and what does the 14-bit version give?問題:濾波器的四個暫存器都存著 2000。投影片版本的 av_temp 會算出多少?14 位元的版本又會得到多少?問題:フィルタの 4 つのレジスタがすべて 2000 を保持している。スライド版の av_temp はいくつになるか。14 ビット版ではどうか。

Click to reveal solution點擊展開解答クリックで解答を表示

Sum = 8000, which needs 13 bits. At 12 bits: 8000 − 4096 = 3904; 3904 >> 2 = 976. With a 14-bit sum: 8000 >> 2 = 2000, the correct average.總和 = 8000,需要 13 位元。在 12 位元下:8000 − 4096 = 3904;3904 >> 2 = 976。改用 14 位元的總和:8000 >> 2 = 2000,才是正確的平均值。総和は 8000 で 13 ビットを要する。12 ビットでは 8000 − 4096 = 3904、3904 >> 2 = 976 となる。14 ビットの総和なら 8000 >> 2 = 2000 で、これが正しい平均である。

Practice 4 — Controller outputs練習 4 — 控制器輸出練習 4 — コントローラ出力

Problem: FIFO 1 is empty, FIFO 2 is full. Give data_out (hex) for read = 1, select = 2'b00, and state what happens to new samples while read = 1.問題:FIFO 1 為空、FIFO 2 已滿。請寫出 read = 1, select = 2'b00 時的 data_out(十六進位),並說明 read = 1 期間新進來的樣本會怎麼樣。問題:FIFO 1 は空、FIFO 2 は満杯である。read = 1, select = 2'b00 のときの data_out を 16 進で示し、read = 1 の間に新しく到着するサンプルがどうなるかを述べよ。

Click to reveal solution點擊展開解答クリックで解答を表示

{empty_1, empty_2, full_1, full_2} = 4'b1001 → 12'h009.{empty_1, empty_2, full_1, full_2} = 4'b1001 → 12'h009。{empty_1, empty_2, full_1, full_2} = 4'b1001 → 12'h009。

While read = 1, write = 0, so the filtered samples are not stored — data arriving during reads is dropped. (And when read = 0, both FIFOs write every clock until full.)在 read = 1 期間 write = 0,所以濾波後的樣本不會被存進去 —— 讀取期間送到的資料會被丟掉。(而 read = 0 時,兩個 FIFO 會每個時脈都寫入,直到滿為止。)read = 1 の間は write = 0 なので、フィルタ後のサンプルは格納されない。すなわち読み出し中に到着したデータは捨てられる。(逆に read = 0 のときは、両方の FIFO が満杯になるまで毎クロック書き込む。)

3. Design Example II: AMD2901 4-Bit Microcontroller3. 設計範例二:AMD2901 四位元微控制器3. 設計例 II:AMD2901 4 ビット・マイクロコントローラ

3.1 Architecture3.1 架構3.1 アーキテクチャ

(1) Register File16 × 4 bits, dual address a / b (4) Q Register4 bits + shifter (2) Operand Selector (3) ALU (5) Output Selector a[3:0], b[3:0]ram0, ram3 d[3:0]i[2:0] → r, si[5:3], c_in alu_outi[8:6], enable → yad qqs0, qs3
AMD2901 bit slice: the ALU result can go to the output selector, the register file (address b) and/or the Q register; ad/bd are the words at addresses a/b.AMD2901 bit slice:ALU 的結果可以送往輸出選擇器、暫存器檔(位址 b)以及/或是 Q 暫存器;ad/bd 則是位址 a/b 上的資料字。AMD2901 のビットスライス。ALU の結果は出力セレクタ、レジスタファイル(アドレス b)、および/または Q レジスタへ送られる。ad/bd はアドレス a/b のワードである。

3.2 The 9-bit instruction word3.2 九位元的指令字3.2 9 ビットの命令語

instruction[8:0] $$\underbrace{i[8:6]}_{\text{destination}}\ \ \underbrace{i[5:3]}_{\text{ALU function}}\ \ \underbrace{i[2:0]}_{\text{operand source}}$$
Operand source i[2:0]運算元來源 i[2:0]オペランド源 i[2:0]
Mnemonic助記符ニーモニックOctal八進位8 進rs
aq0aq
ab1ab
zq20q
zb30b
za40a
da5da
dq6dq
dz7d0
ALU function i[5:3]ALU 功能 i[5:3]ALU 機能 i[5:3]
Mnemonic助記符ニーモニックOctal八進位8 進Operation運算演算Verilog
add0r + sr+s
subr1s − rs-r
subs2r − sr-s
or3r or sr|s
and4r and sr&s
notrs5(not r) and s~r&s
exor6r xor sr^s
exnor7r xnor sr~^s

In the table a, b, q, d mean the register-file word at address a (ad), at address b (bd), the Q register and the direct data input; o/z means zero. (The slide's ALU column writes ||, &&; the bitwise operators are meant.)表中的 a、b、q、d 分別指位址 a 的暫存器檔資料字(ad)、位址 b 的資料字(bd)、Q 暫存器,以及直接資料輸入;o/z 代表零。(投影片的 ALU 欄寫成 ||、&&,其實要的是逐位元運算子。)表中の a、b、q、d は、それぞれアドレス a のレジスタファイルのワード(ad)、アドレス b のワード(bd)、Q レジスタ、直接データ入力を表し、o/z はゼロを意味する。(スライドの ALU 欄は ||、&& と書かれているが、意図はビット単位の演算子である。)

Destination i[8:6]目的地 i[8:6]デスティネーション i[8:6]

Mnemonic助記符ニーモニックOctal八進位8 進Output y輸出 y出力 yRAM shiftRAM 移位RAM シフトRAM loads (addr b)RAM 載入(位址 b)RAM ロード(アドレス b)Q shiftQ 移位Q シフトQ loadsQ 載入Q ロードRAM bit 3 / bit 0RAM 位元 3/位元 0RAM ビット 3/ビット 0Q bit 3 / bit 0Q 位元 3/位元 0Q ビット 3/ビット 0
qreg0alu_out—none無なしnone無なしalu_out— / —— / —
nop1alu_out—none無なし—none無なし— / —— / —
rama2reg_f[a]none無なしalu_out—none無なし— / —— / —
ramf3alu_outnone無なしalu_out—none無なし— / —— / —
ramqd4alu_outdown下移下へalu_out >> 1down下移下へQ >> 1ram3 / d[1]q3 / d[1]
ramd5alu_outdown下移下へalu_out >> 1—none無なしram3 / d[1]n/a不適用該当なし
ramqu6alu_outup上移上へalu_out << 1up上移上へQ << 1d[2] / ram0d[2] / q0
ramu7alu_outup上移上へalu_out << 1—none無なしd[2] / ram0n/a不適用該当なし

The shift occurs before the load. "—" is don't care; reg_f[a] is the register-file word at address a. In the bit columns, d[i] is bit i of the data being shifted; ram3/ram0 and q3/q0 are the serial in/out pins that chain neighbouring slices.移位發生在載入之前。「—」表示不在意(don't care);reg_f[a] 是位址 a 的暫存器檔資料字。位元欄中的 d[i] 是被移位資料的第 i 位元;ram3/ram0 與 q3/q0 是把相鄰 bit slice 串接起來的序列輸入/輸出腳位。シフトはロードより先に行われる。「—」はドントケアを表し、reg_f[a] はアドレス a のレジスタファイルのワードである。ビット欄の d[i] はシフトされるデータの第 i ビットであり、ram3/ram0 と q3/q0 は隣接するスライスを連結するシリアル入出力ピンである。

3.3 Mnemonic definitions with `define3.3 用 `define 定義助記符3.3 `define によるニーモニックの定義

// amd2901 bit slice microprocessor
// operands: instruction[2:0]
`define aq    3'b000
`define ab    3'b001
`define zq    3'b010
`define zb    3'b011
`define za    3'b100
`define da    3'b101
`define dq    3'b110
`define dz    3'b111
// opcodes: instruction[5:3]
`define add   3'b000
`define subr  3'b001
`define subs  3'b010
`define orrs  3'b011
`define andrs 3'b100
`define notrs 3'b101
`define exor  3'b110
`define exnor 3'b111
// destination mnemonics: instruction[8:6]
`define qreg  3'b000
`define nop   3'b001
`define rama  3'b010
`define ramf  3'b011
`define ramqd 3'b100
`define ramd  3'b101
`define ramqu 3'b110
`define ramu  3'b111

Compiler directives are honored by synthesis (Lecture 7), so the code reads `ramqd instead of a magic number. Note or / and are Verilog keywords, hence `orrs / `andrs.合成工具會處理編譯器指令(第 7 講),所以程式碼裡寫的是 `ramqd 而不是一個沒頭沒腦的數字。注意 or 與 and 是 Verilog 的保留字,因此才改用 `orrs 與 `andrs。コンパイラ指令は合成でも解釈される(第 7 講)ため、コードではマジックナンバーではなく `ramqd と書ける。or と and は Verilog の予約語なので、`orrs / `andrs という名前になっている点に注意する。

3.4 Ckt 1 — register file3.4 電路 1 — 暫存器檔3.4 回路 1 — レジスタファイル

module Register_file (clk, rst, a, b, f, dest_ctl, ram0, ram3, ad, bd);
  input        clk, rst;
  input  [3:0] a, b, f;
  input  [2:0] dest_ctl;
  inout        ram0, ram3;
  output [3:0] ad, bd;
  reg    [3:0] ab_data [15:0];   // memory: 16 elements
  wire   [3:0] data;
  wire         ram_en;
  reg    [4:0] row_index;        // note: size of row_index is critical

  assign ram_en = ((dest_ctl == `qreg) || (dest_ctl == `nop)) ? 0 : 1;

  always @ (posedge clk or posedge rst)
    if (rst == 1) for (row_index = 0; row_index < 16; row_index = row_index + 1)
                    ab_data[row_index] = 0;
    else if (ram_en) ab_data[b] = data;

  assign data = (dest_ctl == `ramqu || dest_ctl == `ramu) ? {f[2], f[1], f[0], ram0} :
                (dest_ctl == `ramqd || dest_ctl == `ramd) ? {ram3, f[3], f[2], f[1]} :
                (dest_ctl == `rama  || dest_ctl == `ramf) ? f : 4'bxxxx;

  assign ad   = ab_data[a];
  assign bd   = ab_data[b];
  assign ram3 = (dest_ctl == `ramu || dest_ctl == `ramqu) ? f[3] : 1'bz;
  assign ram0 = (dest_ctl == `ramd || dest_ctl == `ramqd) ? f[0] : 1'bz;
endmodule

3.5 Ckt 2 — operand selector3.5 電路 2 — 運算元選擇器3.5 回路 2 — オペランドセレクタ

module operand_selector (d, ad, bd, q, op_sel, r, s);
  input  [3:0] d, ad, bd, q;
  input  [2:0] op_sel;
  output [3:0] r, s;
  reg    [3:0] r, s;

  // operand codes
  always @ (op_sel) begin
    case (op_sel)
      `aq, `ab:      assign r = ad;
      `zq, `zb, `za: assign r = 4'b0;
      default:       assign r = d;
    endcase
    case (op_sel)
      `aq, `zq, `dq: assign s = q;
      `ab, `zb:      assign s = bd;
      `za, `da:      assign s = ad;
      default:       assign s = 4'b0;
    endcase
  end
endmodule

Uses the "simulation efficient" procedural continuous assignment style from Lecture 5 §5.2: the block wakes only on op_sel, yet r/s keep following d, ad, bd, q. It synthesizes to two 4-bit muxes, but PCA support is tool dependent; always @* with plain = is the portable form.這裡用的是第 5 講 §5.2 那種「模擬效率高」的程序式連續指定(procedural continuous assignment, PCA)寫法:區塊只在 op_sel 變動時被喚醒,但 r/s 仍會持續跟著 d、ad、bd、q 改變。它會合成成兩個 4 位元多工器,不過各家工具對 PCA 的支援程度不一;用 always @* 搭配單純的 = 才是可攜的寫法。第 5 講 §5.2 の「シミュレーション効率のよい」手続き的連続代入(PCA)のスタイルを使っている。ブロックは op_sel の変化でしか起動しないが、r/s は d、ad、bd、q を追従し続ける。合成すると 4 ビットのマルチプレクサ 2 個になるが、PCA の対応はツール依存である。always @* と通常の = を使う書き方のほうが移植性が高い。

3.6 Ckt 3 — ALU3.6 電路 3 — ALU3.6 回路 3 — ALU

module ALU_amd2901 (r, s, c_in, ctl, alu_out, g_bar, p_bar, ovr, c_out);
  input  [3:0] r, s;
  input        c_in;
  input  [2:0] ctl;
  output [3:0] alu_out;
  output       g_bar, p_bar, ovr, c_out;
  reg    [3:0] alu_out;
  reg          c_out;

  always @ (r or s or c_in or ctl)
    case (ctl)
      `add:    {c_out, alu_out} = r + s + c_in;
      `subr:   {c_out, alu_out} = r + ~s + c_in;
      `subs:   {c_out, alu_out} = s + ~r + ~c_in;
      `orrs:   {c_out, alu_out} = {1'b0, r | s};
      `andrs:  {c_out, alu_out} = {1'b0, r & s};
      `notrs:  {c_out, alu_out} = {1'b0, (~r) & s};
      `exor:   {c_out, alu_out} = {1'b0, r ^ s};
      `exnor:  {c_out, alu_out} = {1'b0, r ~^ s};
      default: {c_out, alu_out} = 5'bx;
    endcase

  assign ovr   = c_out ^ alu_out[3];
  assign g_bar = ~( (r[3] & s[3]) |
                    ((r[3] | s[3]) & (r[2] & s[2])) |
                    ((r[3] | s[3]) & (r[2] | s[2]) & (r[1] & s[1])) |
                    ((r[3] | s[3]) & (r[2] | s[2]) & (r[1] | s[1]) & (r[0] & s[0])) );
  assign p_bar = ~((r[3] ^ s[3]) & (r[2] ^ s[2]) & (r[1] ^ s[1]) & (r[0] ^ s[0]));
endmodule
Read the code, not just the table要看程式碼,不能只看功能表表だけでなくコードを読む
  • As written, `subr computes $r + \bar s + c_{in} = r - s$ (when $c_{in}=1$) and `subs computes $s + \bar r + \bar c_{in}$ — the operand order is swapped relative to the table (subr = s − r), and `subs inverts the carry. Check whichever convention your exam uses.照程式碼寫的,`subr 算的是 $r + \bar s + c_{in} = r - s$(當 $c_{in}=1$),而 `subs 算的是 $s + \bar r + \bar c_{in}$ —— 運算元順序和功能表(subr = s − r)相反,而且 `subs 把進位取反。考試時要先確認採用哪一套慣例。コードのとおりなら `subr は $r + \bar s + c_{in} = r - s$($c_{in}=1$ のとき)を、`subs は $s + \bar r + \bar c_{in}$ を計算する。表(subr = s − r)に対してオペランドの順序が入れ替わっており、`subs では桁上げも反転している。試験ではどちらの規約を使うか確認すること。
  • ovr = c_out ^ alu_out[3] is not the usual two's-complement overflow (carry into the MSB XOR carry out of it). See Practice 6.ovr = c_out ^ alu_out[3] 並不是一般的二補數溢位判斷(應該是進入 MSB 的進位 XOR 由 MSB 送出的進位)。見練習 6。ovr = c_out ^ alu_out[3] は通常の 2 の補数オーバフロー(MSB への桁上げ XOR MSB からの桁上げ)ではない。練習 6 を参照のこと。
  • g_bar / p_bar are the inverted group generate / propagate for a 74182-style look-ahead unit across slices. p_bar here uses XOR (half-sum) propagate; the OR form r | s is also common.g_bar/p_bar 是跨 slice 的 74182 式進位預看單元所需的群組 generate/propagate 的反相訊號。這裡的 p_bar 用 XOR(半加和)形式的 propagate;用 OR 的 r | s 形式也很常見。g_bar/p_bar は、スライス間にまたがる 74182 形式の桁上げ先見ユニット向けのグループ generate/propagate を反転した信号である。ここでの p_bar は XOR(半加算)形の propagate を使っているが、OR 形の r | s もよく用いられる。

3.7 Ckt 4 — Q register3.7 電路 4 — Q 暫存器3.7 回路 4 — Q レジスタ

module Q_register (clk, rst, data_in, dest_ctl, qs0, qs3, q);
  // parameterized register with shift left (up), shift right (down)
  // and transfer of interface bits to/from companion slices
  input        clk, rst;
  input  [3:0] data_in;
  input  [2:0] dest_ctl;
  inout        qs0, qs3;
  output [3:0] q;
  reg    [3:0] data;
  reg          q_en;

  reg_load_R #(4) M1 (data, clk, rst, q_en, q);
  bufif1 (qs3, data_in[3], (dest_ctl == `ramu || dest_ctl == `ramqu));
  bufif1 (qs0, data_in[0], (dest_ctl == `ramd || dest_ctl == `ramqd));

  always @ (dest_ctl)
    case (dest_ctl)
      `qreg, `ramqd, `ramqu: assign q_en = 1;
      default:               assign q_en = 0;
    endcase

  always @ (dest_ctl or qs0 or qs3)
    case (dest_ctl)
      // shift left (up)
      `ramqu:  assign data = {data_in[2], data_in[1], data_in[0], qs0};
      // shift right (dn)
      `ramqd:  assign data = {qs3, data_in[3], data_in[2], data_in[1]};
      // pass through
      `qreg:   assign data = data_in;
      default: assign data = 4'bx;
    endcase
endmodule

module reg_load_R (data, clk, reset, load, q);
  parameter size = 8;
  input  [size-1:0] data;
  input             clk, reset, load;
  output [size-1:0] q;
  reg    [size-1:0] q;

  always @ (posedge clk or posedge reset)
    if (reset == 1) q = 0; else if (load == 1) q = data;
endmodule

reg_load_R loads the target data when load is high and otherwise holds (an enable register, not a latch — Lecture 6 §4.4). The Q register instantiates it with #(4) to override size. bufif1 primitives drive the serial pins only while shifting in the matching direction.reg_load_R 在 load 為高時載入資料,否則保持原值(這是帶致能的暫存器,不是閂鎖 —— 第 6 講 §4.4)。Q 暫存器用 #(4) 實體化它以覆寫 size。bufif1 原語只有在對應方向的移位期間才會驅動序列腳位。reg_load_R は load が High のときデータを取り込み、それ以外では値を保持する(ラッチではなくイネーブル付きレジスタである。第 6 講 §4.4)。Q レジスタは #(4) を付けてインスタンス化し、size を上書きしている。bufif1 プリミティブは、対応する方向へシフトしている間だけシリアルピンを駆動する。

Differences from the destination table與目的地功能表的差異デスティネーション表との相違

The top level connects data_in to alu_out, so on `ramqd/`ramqu this model loads alu_out shifted, whereas the table says the Q register loads Q shifted (the original AMD2901 behavior). Also the bufif1 enables include `ramu/`ramd, which the table marks "not applicable" for Q. Feeding q instead of data_in into the shift paths would match the datasheet.頂層把 data_in 接到 alu_out,所以在 `ramqd/`ramqu 時,這個模型載入的是移位後的 alu_out;但功能表說 Q 暫存器載入的應該是移位後的 Q(這才是 AMD2901 原本的行為)。另外 bufif1 的致能條件還包含 `ramu/`ramd,而功能表對 Q 欄把這兩項標為「不適用」。把 q 而不是 data_in 送進移位路徑,才會符合資料手冊。トップレベルでは data_in が alu_out に接続されているため、`ramqd/`ramqu のときこのモデルはシフトした alu_out をロードする。しかし表では、Q レジスタがロードするのはシフトした Q(AMD2901 本来の動作)である。さらに bufif1 のイネーブル条件には `ramu/`ramd も含まれるが、表では Q について「該当なし」とされている。シフト経路に data_in ではなく q を与えれば、データシートどおりになる。

3.8 Ckt 5 — output selector3.8 電路 5 — 輸出選擇器3.8 回路 5 — 出力セレクタ

module output_selector (mux_out, channel_1, channel_2, sel, enable);
  input  [3:0] channel_1, channel_2;
  input  [2:0] sel;
  input        enable;           // active low
  output [3:0] mux_out;

  assign mux_out = (enable == 0 && sel == `rama) ? channel_1 :
                   (enable == 0)                  ? channel_2 : 4'bz;
endmodule

Connected as (y, ad, alu_out, instruction[8:6], enable): y = ad for destination rama, otherwise alu_out, and high-Z when enable = 1.接線為 (y, ad, alu_out, instruction[8:6], enable):目的地是 rama 時 y = ad,否則為 alu_out;而 enable = 1 時輸出高阻抗。接続は (y, ad, alu_out, instruction[8:6], enable) である。デスティネーションが rama なら y = ad、それ以外は alu_out となり、enable = 1 のときはハイインピーダンスになる。

3.9 Top-level module3.9 頂層模組3.9 トップレベル・モジュール

module amd2901 (clk, rst, enable, c_in, a, b, d, instruction, ram0, ram3,
                qs0, qs3, y, g_bar, p_bar, ovr, c_out, f_0, f_3);
  input        clk, rst, c_in, enable;
  input  [3:0] a, b, d;
  input  [8:0] instruction;
  inout        ram0, ram3;
  inout        qs0, qs3;
  output [3:0] y;
  output       g_bar, p_bar, ovr, c_out, f_0, f_3;
  wire   [3:0] ad, bd, q, r, s, alu_out;

  Register_file M1 (
    clk,                // system clock
    rst,                // global reset
    a, b,               // addresses to memory
    alu_out,            // data path from ALU
    instruction[8:6],   // micro instruction bits for destination
    ram0, ram3,         // LSB and MSB from memory word
    ad, bd              // memory output words (4 bits each)
  );
  ALU_amd2901      M2 (r, s, c_in, instruction[5:3], alu_out, g_bar, p_bar, ovr, c_out);
  output_selector  M3 (y, ad, alu_out, instruction[8:6], enable);
  operand_selector M4 (d, ad, bd, q, instruction[2:0], r, s);
  Q_register       M5 (clk, rst, alu_out, instruction[8:6], qs0, qs3, q);

  assign f_0 = (alu_out == 4'b0) ? 0 : 1'bz;
  assign f_3 = alu_out[3];
endmodule

f_0 is an open-drain-style zero flag (drives 0 or floats, so several slices can share one wired line with a pull-up); f_3 is the sign bit. The overall netlist is five sub-blocks plus a 4-input OR and an inverting tri-state (invtn_c) for f_0.f_0 是開汲極式的零旗標(只會拉低或浮接,所以多片 slice 可以共用一條接上提升電阻的線);f_3 則是正負號位元。整體 netlist 就是五個子區塊,再加上一個 4 輸入 OR 與一個反相三態閘(invtn_c)來產生 f_0。f_0 はオープンドレイン形式のゼロフラグである(0 を駆動するか浮かせるかなので、複数のスライスがプルアップ付きの 1 本の線を共有できる)。f_3 は符号ビットである。全体の netlist は 5 つのサブブロックに、f_0 用の 4 入力 OR と反転トライステート(invtn_c)を加えたものになる。

Key points at a glance (click to expand)重點回顧(點擊展開)要点まとめ(クリックで展開)
  • FIFO: a circular buffer driven by read_ptr / write_ptr, with ptr_diff one bit wider so empty (0) and full (8) can be told apart.FIFO:用 read_ptr / write_ptr 做環狀緩衝,ptr_diff 多一位元以區分空(0)與滿(8)。FIFO:read_ptr / write_ptr で動くリングバッファ。ptr_diff を 1 ビット広くして、空(0)と満杯(8)を区別する。
  • Temperature monitor: register → Celsius-to-Fahrenheit conversion (1.8 approximated by 1 + 1/2 + 1/4, so only shifts and adds) → 4-sample moving average → FIFO → controller selecting the output.溫度監測:暫存 → 攝氏轉華氏(1.8 用 1 + 1/2 + 1/4 近似,只需移位與加法)→ 四筆移動平均 → FIFO → 控制器選擇輸出。温度モニタ:レジスタ → 摂氏から華氏への変換(1.8 を 1 + 1/2 + 1/4 で近似し、シフトと加算だけで済ませる)→ 4 サンプル移動平均 → FIFO → コントローラによる出力選択。
  • AMD2901: the 9-bit instruction splits into destination i[8:6], ALU function i[5:3] and operand source i[2:0]; the mnemonics are declared with `define.AMD2901:9 位元指令分成 目的地 i[8:6]、ALU 功能 i[5:3]、運算元來源 i[2:0];用 `define 定義助記符。AMD2901:9 ビット命令はデスティネーション i[8:6]、ALU 機能 i[5:3]、オペランド源 i[2:0] に分かれる。ニーモニックは `define で定義する。
  • The register file is 16 × 4, read out at two addresses as ad/bd and written at address b; ram0/ram3 and qs0/qs3 are bidirectional pins that chain several bit slices together for shifting.暫存器檔 16×4,雙位址讀出 ad/bd,寫入位址 b;ram0/ram3、qs0/qs3 為雙向腳,用來串接多片 bit slice 做移位。レジスタファイルは 16×4 で、2 つのアドレスから ad/bd として読み出し、アドレス b へ書き込む。ram0/ram3 と qs0/qs3 は双方向ピンで、複数のビットスライスを連結してシフトを行う。
  • When reading the slide code, watch out: the operand order of subr/subs, the ovr formula, and the Q register's shift source do not fully agree with the function table.閱讀投影片程式碼時要注意:subr/subs 運算順序、ovr 公式、Q 暫存器移位來源與功能表不完全一致。スライドのコードを読むときは、subr/subs のオペランド順序、ovr の式、Q レジスタのシフト元が機能表と完全には一致しない点に注意する。
Practice 5 — Decode instructions練習 5 — 指令解碼練習 5 — 命令のデコード

Problem: Describe what each instruction does (octal digits are i[8:6], i[5:3], i[2:0]): (a) 1 0 1 (b) 3 4 5 (c) 0 6 7 (d) 6 0 3.問題:說明下列各指令的作用(三個八進位數字依序是 i[8:6]、i[5:3]、i[2:0]):(a) 1 0 1 (b) 3 4 5 (c) 0 6 7 (d) 6 0 3。問題:次の各命令が何を行うかを述べよ(3 つの 8 進数字は順に i[8:6]、i[5:3]、i[2:0]):(a) 1 0 1 (b) 3 4 5 (c) 0 6 7 (d) 6 0 3。

Click to reveal solution點擊展開解答クリックで解答を表示

(a) nop, add, ab: y = RAM[a] + RAM[b] + c_in; nothing stored.(a) nop、add、ab:y = RAM[a] + RAM[b] + c_in;不寫回任何地方。(a) nop、add、ab:y = RAM[a] + RAM[b] + c_in。どこにも格納しない。

(b) ramf, and, da: RAM[b] ← d & RAM[a]; y = the same value.(b) ramf、and、da:RAM[b] ← d & RAM[a];y 也是同一個值。(b) ramf、and、da:RAM[b] ← d & RAM[a]。y も同じ値になる。

(c) qreg, exor, dz: Q ← d ^ 0 = d; y = d. A way to load Q from the data bus.(c) qreg、exor、dz:Q ← d ^ 0 = d;y = d。這是從資料匯流排載入 Q 的一種做法。(c) qreg、exor、dz:Q ← d ^ 0 = d、y = d。データバスから Q をロードする手段である。

(d) ramqu, add, zb: ALU = 0 + RAM[b] + c_in; RAM[b] ← that value shifted up (ram0 enters bit 0), Q shifted up as well; y = alu_out. With c_in = 0 this doubles RAM[b] — the core step of shift-and-add multiplication.(d) ramqu、add、zb:ALU = 0 + RAM[b] + c_in;RAM[b] ← 該值上移一位(ram0 進入位元 0),Q 也同樣上移;y = alu_out。當 c_in = 0 時,這等於把 RAM[b] 乘以 2 —— 正是移位相加乘法的核心步驟。(d) ramqu、add、zb:ALU = 0 + RAM[b] + c_in。RAM[b] ← その値を 1 ビット左シフトしたもの(ram0 がビット 0 に入る)。Q も同様に左シフトされ、y = alu_out となる。c_in = 0 なら RAM[b] が 2 倍になり、これはシフト加算乗算の中心的な手順である。

Practice 6 — ALU flags練習 6 — ALU 旗標練習 6 — ALU フラグ

Problem: With r = 4'b0011, s = 4'b0101, c_in = 1, evaluate the slide's `subr line: alu_out, c_out, ovr. Is there a real signed overflow?問題:取 r = 4'b0011、s = 4'b0101、c_in = 1,計算投影片中 `subr 那一行的 alu_out、c_out、ovr。真的發生有號數溢位了嗎?問題:r = 4'b0011、s = 4'b0101、c_in = 1 のとき、スライドの `subr の行について alu_out、c_out、ovr を求めよ。本当に符号付きオーバフローが起きているか。

Click to reveal solution點擊展開解答クリックで解答を表示

$r + \bar s + 1 = 3 + 10 + 1 = 14$ → alu_out = 4'b1110 (−2 signed), c_out = 0 (borrow: r < s). Indeed 3 − 5 = −2.$r + \bar s + 1 = 3 + 10 + 1 = 14$ → alu_out = 4'b1110(有號數為 −2),c_out = 0(有借位:r < s)。確實 3 − 5 = −2。$r + \bar s + 1 = 3 + 10 + 1 = 14$ → alu_out = 4'b1110(符号付きで −2)、c_out = 0(借りが発生:r < s)。たしかに 3 − 5 = −2 である。

Slide formula: ovr = c_out ^ alu_out[3] = 0 ^ 1 = 1. But −2 fits in 4-bit two's complement, so there is no overflow. Quick check: overflow is only possible when the two adder inputs have the same sign; here $r = 0011$ is positive and $\bar s = 1010$ is negative, so overflow cannot occur. The correct flag is carry-into-MSB XOR carry-out. Bit by bit: $0011 + 1010 + 1$: bit 0: 1+0+1 = 0 c1 = 1; bit 1: 1+1+1 = 1 c2 = 1; bit 2: 0+0+1 = 1 c3 = 0; bit 3: 0+1+0 = 1 c4 = 0. $c_3 \oplus c_4 = 0$ — no overflow. The slide's ovr is really "c_out XOR sign".投影片的公式:ovr = c_out ^ alu_out[3] = 0 ^ 1 = 1。但 −2 在 4 位元二補數裡放得下,所以其實沒有溢位。快速判斷:只有當加法器的兩個輸入同號時才可能溢位;這裡 $r = 0011$ 是正數、$\bar s = 1010$ 是負數,所以不可能溢位。正確的旗標是「進入 MSB 的進位 XOR 由 MSB 送出的進位」。逐位元計算 $0011 + 1010 + 1$:位元 0:1+0+1 = 0,c1 = 1;位元 1:1+1+1 = 1,c2 = 1;位元 2:0+0+1 = 1,c3 = 0;位元 3:0+1+0 = 1,c4 = 0。$c_3 \oplus c_4 = 0$ —— 沒有溢位。投影片的 ovr 其實是「c_out XOR 正負號位元」。スライドの式では ovr = c_out ^ alu_out[3] = 0 ^ 1 = 1 となる。しかし −2 は 4 ビットの 2 の補数で表せるので、実際にはオーバフローは起きていない。簡便な判定:加算器の 2 入力が同符号のときにしかオーバフローは起こり得ない。ここでは $r = 0011$ が正、$\bar s = 1010$ が負なので起こり得ない。正しいフラグは「MSB への桁上げ XOR MSB からの桁上げ」である。$0011 + 1010 + 1$ をビットごとに見ると、ビット 0:1+0+1 = 0、c1 = 1。ビット 1:1+1+1 = 1、c2 = 1。ビット 2:0+0+1 = 1、c3 = 0。ビット 3:0+1+0 = 1、c4 = 0。$c_3 \oplus c_4 = 0$ でオーバフローはない。スライドの ovr は実質「c_out XOR 符号ビット」である。

Practice 7 — RAM shift練習 7 — RAM 移位練習 7 — RAM シフト

Problem: alu_out = 4'b1011. Give the word written to RAM[b] and the values on ram3/ram0 for destinations (a) ramu with ram0 = 1, (b) ramd with ram3 = 0, (c) ramf.問題:alu_out = 4'b1011。請寫出下列各目的地寫進 RAM[b] 的資料字,以及 ram3/ram0 上的值:(a) ramu 且 ram0 = 1,(b) ramd 且 ram3 = 0,(c) ramf。問題:alu_out = 4'b1011 とする。次の各デスティネーションについて、RAM[b] に書き込まれるワードと ram3/ram0 の値を示せ。(a) ram0 = 1 の ramu、(b) ram3 = 0 の ramd、(c) ramf。

Click to reveal solution點擊展開解答クリックで解答を表示

(a) {f[2], f[1], f[0], ram0} = 4'b0111; ram3 drives f[3] = 1 out to the next slice; ram0 is an input.(a) {f[2], f[1], f[0], ram0} = 4'b0111;ram3 把 f[3] = 1 送往下一片 slice;ram0 此時是輸入。(a) {f[2], f[1], f[0], ram0} = 4'b0111。ram3 は f[3] = 1 を次のスライスへ出力し、ram0 は入力となる。

(b) {ram3, f[3], f[2], f[1]} = 4'b0101; ram0 drives f[0] = 1; ram3 is an input.(b) {ram3, f[3], f[2], f[1]} = 4'b0101;ram0 送出 f[0] = 1;ram3 此時是輸入。(b) {ram3, f[3], f[2], f[1]} = 4'b0101。ram0 が f[0] = 1 を出力し、ram3 は入力となる。

(c) 4'b1011 unshifted; both pins high-Z.(c) 4'b1011 原封不動;兩支腳都是高阻抗。(c) 4'b1011 がそのまま書き込まれ、両方のピンはハイインピーダンスになる。

4. Summary and Exam Checklist4. 總結與考前檢查清單4. まとめと試験前チェックリスト

FIFOFIFOFIFO
  • Circular buffer, two pointers.環狀緩衝區,兩個指標。リングバッファとポインタ 2 本。
  • Count one bit wider than pointers.計數值要比指標多一個位元。カウントはポインタより 1 ビット広く取る。
  • Block writes when full, reads when empty.滿了就擋寫入,空了就擋讀出。満杯なら書き込みを、空なら読み出しを止める。
Arithmetic tricks算術技巧算術のテクニック
  • Constant × / ÷ by shift-and-add.常數乘除用移位加法實現。定数の乗除算はシフトと加算で行う。
  • 1.8 ≈ 1 + ½ + ¼ (or 2 − ¼).1.8 ≈ 1 + ½ + ¼(或 2 − ¼)。1.8 ≈ 1 + ½ + ¼(または 2 − ¼)。
  • Average of 4 = sum >> 2; size the sum.四筆平均 = 總和 >> 2;總和的寬度要夠。4 個の平均は総和 >> 2。総和のビット幅に注意する。
System integration系統整合システム統合
  • One module per block, then a top level.一個方塊一個模組,最後再寫頂層。ブロックごとに 1 モジュール、最後にトップレベルをまとめる。
  • Watch implicit nets and port order.小心隱含接線與埠的順序。暗黙のネットとポート順序に注意する。
  • Tri-state for shared outputs.共用的輸出用三態閘。共有する出力にはトライステートを使う。
AMD2901AMD2901AMD2901
  • i[8:6] dest, i[5:3] ALU, i[2:0] source.i[8:6] 目的地、i[5:3] ALU、i[2:0] 來源。i[8:6] がデスティネーション、i[5:3] が ALU、i[2:0] がオペランド源。
  • 16×4 dual-port RAM, Q register.16×4 雙埠 RAM,加上 Q 暫存器。16×4 のデュアルポート RAM と Q レジスタ。
  • ram0/3, qs0/3 chain bit slices.ram0/3、qs0/3 用來串接 bit slice。ram0/3、qs0/3 でビットスライスを連結する。
Coding style程式風格コーディングスタイル
  • `define mnemonics.用 `define 定義助記符。`define でニーモニックを定義する。
  • Loop index wide enough to exit.迴圈索引要夠寬才跳得出來。ループ変数は抜けられる幅を確保する。
  • #(4) parameter override.用 #(4) 覆寫參數。#(4) によるパラメータの上書き。
Flags旗標フラグ
  • c_out, ovr, g_bar / p_bar (look-ahead).c_out、ovr、g_bar/p_bar(進位預看)。c_out、ovr、g_bar/p_bar(桁上げ先見)。
  • f_0 zero (open drain), f_3 sign.f_0 為零旗標(開汲極),f_3 為正負號。f_0 はゼロフラグ(オープンドレイン)、f_3 は符号。