顯示具有 verilog 標籤的文章。 顯示所有文章
顯示具有 verilog 標籤的文章。 顯示所有文章

2008年8月27日 星期三

Verilog Levels of Abstraction

  1. Behavioral Representation(Architecture/System/Algorithmic Level)

  2. 這是Verilog中最高層次,在這個層次中我們會依據系統需求,來考慮模組或函式的功能而不去考慮硬體方面詳細的電路是如何運作的。所以會專注在系統架構或演算法的實現,因此在這個階段設計工作就會像在寫C。通常在此層次中所做的是用來模擬並且多半無法合成的,也無法看出電路特性。
  3. Functional Representation(RTL/Dataflow Level)

  4. 在這個層次中,我們必需要指定資料處理的方式,明確的說明資料如何在暫存器及模組間儲存與傳送的流程。在此層次中可看出電路特性。
  5. Structural Representation(Gate Level)

  6. 這個層次中的模組是由邏輯閘連接而成,所以設計的工作就會像以前用描繪邏輯閘來設計線路一樣,所以可以了解實際的硬體線路,但無法很快速的了解高階的行為。在這個層次中我們可以用內建的verilog原生元件來設計,不過由於在不同的製程下,各種的邏輯閘大小、延遲時間等等,也會跟著有所不同,所以此層次通常交由工具程式下去產生。
  7. Physical Representation(Switch/Transistor Level)

  8. 這是Verilog最低階的層次,線路是由開關與儲存點組合而成。在此層次設計時必需清楚知道電晶體的元件特性,但此處寫出的Verilog是無法合成的。


從Behavioral->Functional->Structural->Physical皆可使用Verilog去描述出來,尤其是Behavioral是Verilog的強項。


Verilog in Behavioral Level – NAND Module

module NANDGATE (A, B, F);
input A;
input B;
output F;
reg F;

always @(A or B)
begin
F=~(A & B);
end
endmodule

Verilog in Functional Level – AND Module
module ANDGATE (A, B, F);
input A;
input B;
output F;
wire F;

assign F=A&B;
endmodule

Verilog in Structural Level – OR Module
module ORGATE (A, B, F);
input A;
input B;
output F;

or u1(F, A, B);
endmodule

Verilog in Physical Level – NOT Module
module inv (ina, out);
input ina;
output out;
supply1 vcc;
supply0 gnd;

pmos (out, vcc, ina);
nmos (gnd, out, ina);
endmodule

2-bit Left Shift

32位元左移2位元
// 32-bit Shift left by 2
module leftShift2 (in,out);
input [31:0] in;
output [31:0] out;
reg [31:0] out;
out = { in[29:0], 1'b0, 1'b0 };
endmodule // leftShift2

module leftShift2 (in,out);
input [31:0] in;
output [31:0] out;
reg [31:0] out;
out = in << 2;
endmodule

參考來源:
http://inst.eecs.berkeley.edu/~cs61c/fa04/lectures/L26-dg-singlecpu.pdf

16-bits Sign Extender to 32-bits

這個Sign Extender主要是希望把16bits的有號數變成32bits的有號數
verilog範例程式如下:
// Sign extender from 16- to 32-bits.
module signExtend (in,out);
input [15:0] in;
output [31:0] out;
reg [31:0] out;
out = { in[15], in[15], in[15], in[15],
in[15], in[15], in[15], in[15],
in[15], in[15], in[15], in[15],
in[15], in[15], in[15], in[15],
in[15:0] };
endmodule // signExtend

另一個比較好的寫法
// Sign Extender
module SignExtend(In, Out);
input [15:0] In;
output [31:0] Out;
assign Out = {{16{In[15]}},In[15:0]};
endmodule

Joint(Concatenation) Operation - Joint different operands as one by { and }
Example 1:
// A = 1'b1, B = 2'b00, C = 2'b10, D = 3'b110
Y = { B, C} // Y is 4'b0010
Y = { A, B, C, D, 3'b001} // Y is 11'b10010110001
Y = { A, B[0], C[1]} // Y is 3'b101
Example 2:
wire [1:0] a, b; wire [2:0] x; wire [3;0] y, Z;
assign x = {1’b0, a}; // x[2]=0, x[1]=a[1], x[0]=a[0]
assign y = {a, b}; /* y[3]=a[1], y[2]=a[0], y[1]=b[1],
y[0]=b[0] */
assign {cout, y} = x + Z; // Concatenation of a result

Replication Operation - Repetition operand several times
Example 1:
A = 1'b1; B = 2'b00; C = 2'b10; D = 3'b110;
Y = { 4{A} } // Y is 4'b1111
Y = { 4{A}, 2{B}, C} //Y is 8'b1111000010

Example 2:
wire [1:0] a, b; wire [4:0] x;
assign x = {2{1’b0}, a}; // Equivalent to x = {0,0,a }
assign y = {2{a}, 3{b}}; //Equivalent to y = {a,a,b,b,b}

有parameter的寫法
<code>module SIGN_EXTEND(in, out);
parameter INSIZE = 16, OUTSIZE = 32;

input [INSIZE-1:0] in;
output [OUTSIZE-1:0] out;
assign out = {{ OUTSIZE-INSIZE {in[INSIZE-1]}}, in};
endmodule // SIGN_EXTEND</code>

資料來源:
berkeley Single Cycle CPU Datapath with Verilog
Multicycle Processor Design in Verilog

2008年8月26日 星期二

Register File in Verilog

在CPU裏面最重要的結構就是暫存器檔案(Register File)。Reading the Register FileWriting into the Register File底下列出簡單的Register File的Verilog範例程式碼

I/O Input
(1)Clock Signal(時脈訊號):clk
(2)Write Enable Signal(寫入暫存器訊號):en_write
(3)Address Bus(指定暫存器編號,需要3個5位元):ra1、ra2、wa
(4)Input Data Bus(寫入的資料,需要1個32位元):wd

I/O Output
(1)Output Data Bus(輸出的資料,需要2個32位元):rd1,rd2
module regfile
(
input [4:0] ra1,output [31:0] rd1,
input [4:0] ra2,output [31:0] rd2,
input clk,
input en_write,
input [4:0] wa,input [31:0] wd
);

reg [31:0] registers[31:0];
// 暫存器0永遠輸出0
assign rd1 = (ra1 == 5'b00000) ? 32'h00000000 : registers[ra1];
assign rd2 = (ra2 == 5'b00000) ? 32'h00000000 : registers[ra2];
// 當en_write=1時,執行將wd寫入暫存器的動作
always @(posedge clk)
begin
if ( en_write )
registers[wa] <= wd;
end

endmodule

2008年8月7日 星期四

Verilog Procedural Blocks

  1. 以initial為主體的程式區塊,每次一開始執行後,只會在最一開始執行一次。

  2. initial通常用於Testbench使用,它屬於不可合成的區塊。
  3. 以always為主體的程式區塊,則是每當觸發條件成立時,執行一次,執行完後,等待下一次的觸發條件成立。

  4. 所有的程式區塊(Procedural Blocks)皆是以同時性(concurrently)的方式,同時執行所有的程式。
原則上在Blocks裏是依序執行,當然還要看你是寫Blocking還是NonBlocking啦,但只有在Blocks裏才有機會依序執行,其它的全部都是同時執行。
上圖的C表示的是Conditions of Execution執行條件囉!

2008年8月6日 星期三

多工器4對1

設計一個一位元的四對一多工器,也就是四個訊號輸入,再用兩個bit去控制訊號去選擇一個訊號輸出
verilog程式碼如下:
module  mux4_to_1 (out , i0, i1, i2 , i3 , s1 , s0);
//一個輸出訊號
output out;
//四個輸入訊號
input i0, i1, i2 ,i3;
//兩個選擇訊號
input s1,s0 ;
wire s1n ,s0n ;
wire y0 ,y1 ,y2 ,y3;
not(sln, s1);
not(s0n, s0);
and (y0, i0, s1n , s0n);
and (y1, i1, s1n , s0);
and (y2, i2, s1 , s0n);
and (y3, i3, s1 , s0);
or (out, y0 ,y1 ,y2 ,y3);
endmodule

2008年8月5日 星期二

blocking與nonblocking的使用時機

一般而言:
  1. 在同一個always區塊中,blocking與nonblocking assignment不可以混合使用。

  2. 具有Clock的循序電路,建議採用nonblocking assignment(<=)的寫法。

  3. 如:
    always@(posedge clk or negedge reset_n) begin
    if (!reset_n)
    counter <= 8'b00;
    else
    counter <= counter + 1;
    end
  4. 如果是組合電路,則建議採用blocking assignment(=)的寫法。

  5. 如:
    always@(sel or a or b) begin
    case (sel)
    2'b00 : c = a;
    2'b01 : c = b;
    endcase
    end
  6. 在continuous assignment則使用blocking的寫法。

  7. 如:
    assign y = a&b;

    這個主要的目的是用以明顯的區分出不同電路的設計,以必免不必要的麻煩。

nonblocking assignment(<=)的使用方法

看完blocking assignment後,再來看看何謂nonblocking assignment吧!verilog跟一般寫程式最大的其中一個差異點就是,硬體描述語言有同時性(concurrently)的情況,簡單的講就是假設你寫了三行程式,verilog可以讓這三行程式同時執行,或許你會講,現在的程式不是都是多工在執行嗎?同時跑一堆程式呀,但是你如果以微觀的角度來看,其實同一個時間點,CPU還是只有執行一道指令的。而verilog的nonblocking assignment的用法就是用來描述這種情況。
好啦,我們再拿Verilog數位電路設計-範例寶典的範例來介紹吧!

底下有兩段程式
----------------
第一個範例
begin
q_a1_reg <= #1 data;
q_a2_reg <= #1 q_a1_reg;
q_a3_reg <= #1 q_a2_reg;
end
----------------
第二個範例
begin
q_b3_reg <= #1 q_b2_reg;
q_b2_reg <= #1 q_b1_reg;
q_b1_reg <= #1 data;
end
----------------
我們一直在講同時執行程式,所以囉!範例一跟範例二會產生出一樣的結果
我們來看看它所代表的硬體線路吧!再看看下圖是ModelSim跑的模擬結果有沒有對blocking vs nonblocking有更進一步的了解了呢?

blocking assignment (=) 的使用方法

blocking assignment一般來講都翻成阻斷賦值,聽起來是不是有點抽象不太懂呢?
我們拿Verilog數位電路設計-範例寶典的範例來介紹吧!因為我覺得它的例子蠻容易讓人理解。

看一下底下兩段程式
---------------
第一個範例
begin
q_a1_reg = data;
q_a2_reg = q_a1_reg;
q_a3_reg = q_a2_reg;
end
---------------
第二個範例
begin
q_b3_reg = q_b2_reg;
q_b2_reg = q_b1_reg;
q_b1_reg = data;
end
---------------
看起來是不是差不多呢?我們不管命名的差別,則差異只在順序的不相同而以,這個部份就跟我們寫一般的程式沒兩樣,這就是所謂的blocking assignment,就是由上往下執行,一行做完接著一行做。

但我們先來比較一下它所代表的硬體線路差異
下圖是跑ModelSim的結果
所以看懂差異了嗎?很有趣吧^^

FullAdder4:4位元串接全加器


由一位元全加器組成的四位元串接全加器程式碼
//定義四位元全加器
module fulladder4 (sum , c_out, a , b , c_in);
output [3:0] sum;
output c_out;
input [3:0] a, b;
input c_in;
wire c1,c2,c3;
//四個一位元全加器的別名
fulladder fa0(sum[0],c1,a[0],b[0],c_in);
fulladder fa1(sum[1],c2,a[1],b[1],c1);
fulladder fa2(sum[2],c3,a[2],b[2],c2);
fulladder fa3(sum[3],c_out,a[3],b[3],c3);
endmodule

FullAdder:一位元全加器


一位元全加器的Verilog程式碼
//定義一位元全加器
module fulladder (sum , c_out, a , b , c_in)
//宣告輸出入埠
output sum,c_out;
input a, b, c_in;
//宣告內部接線
wire s1,c1,c2 ;
xor(sl, a,b) ;
and(c1, a,b);
xor (sum, s1, c_in) ;
and (c2, s1, c_in) ;
xor (c_out, c2, c1) ;
endmodule

真值表如下
ABC_INSUMC_OUT
00000
01010
10010
11001
00110
01101
10101
11111

一個小故事讓我們明白資金流通的意義

“又是炎熱小鎮慵懶的一天。太陽高掛,街道無人,每個人都債台高築,靠信用度日。這時,從外地來了一位有錢的旅客,他進了一家旅館,拿出一張1000 元鈔票放在櫃檯,說想先看看房間,挑一間合適的過夜,就在此人上樓的時候---- 店主抓了這張1000 元鈔,跑到隔壁屠戶那裡支付了他欠的肉錢...