加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權(quán)保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

從電路到Verilog | 數(shù)字電路設(shè)計:有理論、有電路、有代碼“三位一體”

2016/08/02
32
  • 2評論
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

?

書接上文,前面給大家介紹了時序邏輯電路的基本知識和代碼寫法。今天的講座更精彩,講數(shù)字電路設(shè)計的三種常用模式,有理論、有電路、有代碼“三位一體”。


1. 并行運轉(zhuǎn),靈活運用
在數(shù)字邏輯系統(tǒng)設(shè)計里面有三大實用的邏輯:并行化、流水線和時分復用。這些方法在《玩轉(zhuǎn) IP core》/《IP 核芯志》里面都有詳細介紹,下面不在細說理論,僅僅關(guān)注與代碼設(shè)計。


先用一個生活里面的例子,來說明一下“并行化”的思想。


盛夏,知了在樹梢頭不停名叫,日天吃西瓜是一種享受??上?,小明不僅吃不到西瓜,還得去搬西瓜。事情是這樣的,小明他爹大明到批發(fā)市場賣了 30 個西瓜,準備回去吃??墒悄兀蝗还居屑笔?,不能親自搬回家了。于是萬能的小明被委派來把這些西瓜搬回家。小明啊,還是小學生呢,力氣不大,一次只能搬一只西瓜,這個情節(jié)設(shè)計是比較符合場景的。從市場把一只西瓜搬回家要 10 分鐘時間,也就是說如果小明一個人搬的話,總共需要 300 分鐘,也就是 5 個小時。這個工作量也太大了。


小明可是會勻速運動的聰明娃,那是掐指一算計上心來。他招呼來了自家兄弟小亮、小光,還是好朋友小黑、小暗,還有女朋友小紅,大家一起搬。所謂人多好辦事,這樣算計下來只要不到 1 個小時就完事了。這個是基本的想法,下來明確幾個細節(jié)。


但是這個西瓜如何搬呢,自然不能都切開搬了。腦袋沒問題的人都知道,一個一個地搬運最靠譜。然后,搬西瓜有順序嗎?自然沒有,理論上沒說不搬地三號西瓜,第四號西瓜絕對不準動。可是考慮實際中西瓜被堆成一堆的情況,還是需要按照從外到里、從上到下的順序搬運的。最后,大家怎么一個操作順序最合適?你搬完,我再來?兄弟,忘了充值 IQ 卡了吧?當然是大家并行來搬最好?;静襟E設(shè)計階段結(jié)束了,下來加大難度考慮西瓜堆附近和小明家里的細節(jié)。


西瓜堆和小明家里都有一個問題:地方小,場地容不下 6 個人同時存在。那怎么辦呢?簡單大家排隊取,現(xiàn)在規(guī)定按照小明、小亮、小光、小黑、小暗,最后小紅的順序,大家依次搬西瓜。每個人操作間隔是 1 分鐘。


終于不存在搬西瓜的任何障礙了,這個搬西瓜的流程設(shè)計就是采用了“并行化”的思想。


抽象模型總給人虛無縹緲的感覺,初學者一定需要例子來看看到底如何實現(xiàn)。好吧,這就滿足你們的需求,給大伙兒一個工程化的例子。


一個簡化的不考慮溢出的累加器,如圖 4 所示。系統(tǒng)需求明確輸入信號為 7 比特,每輸入 128 個數(shù)據(jù)需要輸出一次累加結(jié)果。那么為了保險起見,輸出結(jié)果需要 14 個比特。


圖 4 待“并行化”的累加器


假設(shè)分成 4 個分路來處理,那么每個處理里面的加法器僅需 12 比特位寬即可。這個是計劃外的好處,一般的并行化是沒有的。


圖 5 是采用編碼方式的輸入分發(fā)模塊以及隨時計算的合并輸出輸出模塊的系統(tǒng)整體的結(jié)構(gòu)圖,不同模塊用虛線框出。這是大伙兒第一次遇到不同模塊組合而成的系統(tǒng),請稍稍注意自己好好分析一下。


圖 5 并行化累加器的結(jié)構(gòu)圖 1:定時器數(shù)值控制采樣相位

對應(yīng)圖 5 的代碼如例 3 所示。這個是大伙兒遇到的第一個這種設(shè)計模式的代碼,所以多浪費了一些紙張,拷貝的比較詳細,請大家別怪貧道浪費。


【例 3】并行化累加器的代碼:定時器數(shù)值控制采樣相位
module sum_parallel_timer
? (
??? input[7:0] input_data,
??? input data_start,
??? input CLK, input RST,
??? output reg[16:0] sum,
??? output reg sum_enable
? );

//Definition for Variables in the module
reg[7:0] count;
//For 7 bits timer
reg[2:0] count1;
//For 2 bits timer

reg[7:0] data1, data2, data3, data4;
//Sample for 4 parallel operation modules
reg [14:0] sum1, sum2,sum3, sum4;
//Result (sum) for 4 parallel operation modules

//Load other module(s)

//Logical

always @(posedge CLK or negedge RST)
//7 bits timer
begin
??? if (!RST)
??? //Reset
??? begin
??????? count <= 8'h00;
??? end
??? else if(data_start)
??? begin
??????? count <= 8'h7f + 8'h04;?
??????? //Constant 4 is for 4 clock delay for last 4 data input
??????? //Constant 7f for 128 total data?????
??? end
??? else if (count != 8'h00)
??? begin
??????? count <= count - 8'h01;??????
??? end
??? else
??? begin
??????? count <= 8'h00;??????
??? end
end

always @(posedge CLK or negedge RST)
//2 bits timer
begin
??? if (!RST)
??? //Reset
??? begin
??????? count1 <= 3'b000;
??? end
??? else if(count == 8'h01)
??? begin
??????? count1 <= 3'b111;???????
??? end
??? else if (count1 != 3'b000)
??? begin
??????? count1 <= count1 - 3'b001;??????
??? end
end

always @(posedge CLK or negedge RST)
//Sample for each operation
begin
??? if (!RST)
??? //Reset
??? begin
??????? data1 <= 8'h00;
??????? data2 <= 8'h00;??
??????? data3 <= 8'h00;
??????? data4 <= 8'h00;?????????????
??? end
??? else if(count != 8'h00)
??? begin
??????? case (count[1:0])
???????? 2'b11: data1 <= input_data;
???????? 2'b10: data2 <= input_data;
???????? 2'b01: data3 <= input_data;
???????? 2'b00: data4 <= input_data;
??????? endcase???????????????????????
??? end
??? else
??? begin
??????? data1 <= 8'h00;
??????? data2 <= 8'h00;??
??????? data3 <= 8'h00;
??????? data4 <= 8'h00;?????????????
??? end???
end

always @(posedge CLK or negedge RST)
//Parallel sum for each operation
begin
??? if (!RST)
??? //Reset
??? begin
??????? sum1 <= 15'h0000;
??????? sum2 <= 15'h0000;??
??????? sum3 <= 15'h0000;
??????? sum4 <= 15'h0000;?????????????
??? end
??? else
??? begin
??????? case (count[1:0])
???????? 2'b11: sum1 <= sum1 + {7'h00, data1};
???????? 2'b10: sum2 <= sum2 + {7'h00, data2};
???????? 2'b01: sum3 <= sum3 + {7'h00, data3};
???????? 2'b00: sum4 <= sum4 + {7'h00, data4};
??????? endcase????????????????????????
??? end
end


always @(posedge CLK or negedge RST)
//Sum
begin
??? if (!RST)
??? //Reset
??? begin
??????? sum <= 17'h0_0000;
??? end
??? else
??? begin
??????? sum <= {2'h0,sum1} + {2'h0,sum2} + {2'h0,sum3} + {2'h0,sum4};
??? end
end

always @(posedge CLK or negedge RST)
//Sum
begin
??? if (!RST)
??? //Reset
??? begin
??????? sum_enable <= 1'b0;
??? end
??? else if (count1 == 3'b001)
??? begin
??????? sum_enable <= 1'b1;
??? end
??? else
??? begin
??????? sum_enable <= 1'b0;
??? end
end
endmodule

?


2. 流水嘩嘩,奔騰不息
話接上文,還是搬西瓜。前面那講的設(shè)計就是沒人情味的家伙搞的,看看:要求系統(tǒng)里面人人都是埋頭跑圈。個人連面都見不到,更別說聊天了。這是典型的“反人類”,把人當機器?!耙匀藶楸尽睂τ诤芏喙径际钦f說說的,但是在老朽這里確實必須堅持的原則。


本人的系統(tǒng)設(shè)計是,搬運人員是小明等六人,就把把路程分為 6 段。沒人負責一段的運輸,到了交接點把西瓜面對面交給下一個人。當然除了交接西瓜,兩人聊聊也是不錯的。這樣傳遞下去,直到到達小明家為止。這樣還有一個附加的好處:哪里有跌破的瓜,是誰打破的一目了然。老夫這個系統(tǒng)里面,打破的地點屬于誰的一畝三分地,就該誰負責。


這里就用乘法器作為例子來說明流水線模式的代碼設(shè)計。利用乘法的交換律和結(jié)合律,可以把乘法轉(zhuǎn)化成了 b 的位寬個加法運算;第 k 次加法的加數(shù)是 b 的第 n 比特(bk)與 a 左移 k 位(a<<k)的乘積;這里面的乘積呢,又可以根據(jù) bk 的兩個可能的數(shù)值,通過選擇器實現(xiàn)。這般如此,如此這般……,可以得到了乘法器的流水線結(jié)構(gòu),如圖 6 所示。


圖 6 流水線形式乘法器的結(jié)構(gòu)圖


流水線形式的乘法器的代碼如例 4 所示。穆老道采用的是橫著寫的方式,和尚為了顯示區(qū)別,這次豎著來。這里只給出了關(guān)鍵部分的代碼。


【例 4】流水線形式乘法器的代碼(部分)
module multiplication_pipeline
//Multiplication in pipeline
? (
??? input[7:0] a,
??? input[7:0] b,
??? input CLK, input RST,
??? output[15:0] product
? );

//Definition for Variables in the module
wire[7:0] a0, a1, a2, a3, a4, a5, a6, a7;
//In a's delay chain
wire[7:0] b0;
wire[6:0] b1;
wire[5:0] b2;
wire[4:0] b3;
wire[3:0] b4;
wire[2:0] b5;
wire[1:0] b6;
wire b7;
//In b's delay chain
wire [7:0] result1;
wire [9:0] result2;
wire [10:0] result3;
wire [11:0] result4;
wire [12:0] result5;
wire [13:0] result6;
wire [14:0] result7;
wire [15:0] result8;
//In Result's Chain

//Load other module(s)
mul_pipe_step1 M1(.a_prev(a0),.b_prev(b0),
????????????????? .CLK(CLK), .RST(RST),
????????????????? .a_next(a1),.b_next(b1),.result_next(result1));
?????????????????
mul_pipe_step2 M2(.a_prev(a1),.b_prev(b1),.result_prev(result1),
????????????????? .CLK(CLK), .RST(RST),
????????????????? .a_next(a2),.b_next(b2),.result_next(result2));?????????????????

……
?????????????????
mul_pipe_step8 M8(.a_prev(a7),.b_prev(b7),.result_prev(result7),
????????????????? .CLK(CLK), .RST(RST),
????????????????? .result_next(result8));????
//Pipeline chain
????????????????????????????????????????????????????????????????????????????????
//Logical
assign a0 = a;
assign b0 = b;
assign product = result8;

endmodule

module mul_pipe_step1
//Step1 in pipeline
? (
??? input[7:0] a_prev,
??? input[7:0] b_prev,
//? input result_prev,
??? input CLK, input RST,
??? output reg[7:0] a_next,
??? output reg[6:0] b_next,
??? output reg[7:0] result_next
? );

//Definition for Variables in the module

//Load other module(s)

//Logical

always @(posedge CLK or negedge RST)
//Staoring for input delay
begin
??? if (!RST)
??? //Reset
??? begin
??????? a_next <= 8'h00;
??????? b_next <= 7'h00;
??? end
??? else
??? begin
??????? a_next <= a_prev;
??????? b_next <= b_prev[7:1];
??? end
end

always @(posedge CLK or negedge RST)
//Staoring for input delay
begin
??? if (!RST)
??? //Reset
??? begin
??????? result_next <= 9'h000;
??? end
??? else
??? begin
??????? if (b_prev[0])
??????? begin
??????????? result_next <= a_prev;
??????? end
??????? else
??????? begin
??????????? result_next <= 8'h00;
??????? end
??? end
end

endmodule

module mul_pipe_step2
//Step2 in pipeline
? (
??? input[7:0] a_prev,
??? input[6:0] b_prev,
??? input[7:0] result_prev,
??? input CLK, input RST,
??? output reg[7:0] a_next,
??? output reg[5:0] b_next,
??? output reg[9:0] result_next
? );

//Definition for Variables in the module

//Load other module(s)

//Logical

always @(posedge CLK or negedge RST)
//Staoring for input delay
begin
??? if (!RST)
??? //Reset
??? begin
??????? a_next <= 8'h00;
??????? b_next <= 6'h00;
??? end
??? else
??? begin
??????? a_next <= a_prev;
??????? b_next <= b_prev[6:1];
??? end
end

always @(posedge CLK or negedge RST)
//Staoring for input delay
begin
??? if (!RST)
??? //Reset
??? begin
??????? result_next <= 10'h000;
??? end
??? else
??? begin
??????? if (b_prev[0])
??????? begin
??????????? result_next <={2'b0, result_prev} + {1'b0, a_prev, 1'b0};
??????????? // = result + (a << 2)
??????????? //max bit width 10
??????? end
??????? else
??????? begin
??????????? result_next <= {1'b0, result_prev};
??????? end
??? end
end

endmodule

…….

module mul_pipe_step8
//Step7 in pipeline
? (
??? input[7:0] a_prev,
??? input b_prev,
??? input[14:0] result_prev,
??? input CLK, input RST,
//? output reg[7:0] a_next,
//? output reg b_next,
??? output reg[15:0] result_next
? );

//Definition for Variables in the module

//Load other module(s)

//Logical

always @(posedge CLK or negedge RST)
//Staoring for input delay
begin
??? if (!RST)
??? //Reset
??? begin
??????? result_next <= 16'h0000;
??? end
??? else
??? begin
??????? if (b_prev)
??????? begin
??????????? result_next <={1'b0, result_prev} + {1'b0, a_prev, 7'b000_0000};
??????????? // = result + (a << 1)
??????? end
??????? else
??????? begin
??????????? result_next <= {1'b0, result_prev};
??????? end
??? end
end

endmodule

?


3. 時分復用,節(jié)約成本
前面給大伙兒介紹了兩種設(shè)計模式,目的都是為了適應(yīng)更加快速數(shù)據(jù)輸入速度的要求。通過這兩個設(shè)計模式的架構(gòu)圖的分析,不難看出要想快是要付出代價的。但是老板卻不這樣想,他們的想法是:既要快又要省。這個老衲做不到??!但是,如果只是節(jié)約點成本,鄙人還有辦法,那就是這一講里面介紹的時分復用。時分復用需要在數(shù)據(jù)輸入比較慢的場景下使用,這個又快不起來了。天道循環(huán),有得必有失,即使是佛祖也不能避免。老板們,總是覺得自己是神,事實證明他們更像某種隊友。


敗家容易,節(jié)約難。設(shè)計者一旦掌握了“并行”處理的思想,有意無意的會喜歡用很多分枝的結(jié)構(gòu)來設(shè)計數(shù)字邏輯系統(tǒng)。這個錯是沒錯,但是在有些地方未免浪費?,F(xiàn)在不號召“顆粒歸倉”了。老衲是老派的人,還是喜歡能省就省的設(shè)計的。并行平鋪肯定是最簡單的設(shè)計了,但是這個太不體現(xiàn)水平了。因地制宜,因模塊速度制設(shè)計,才是高手本色啊。


時分復用的基本思想是:對于一些需要處理速度比較慢、有重復運算的單元,在可以接受的處理時間內(nèi),多次重復利用有關(guān)的運算器件,以達到減少整個單元面積的目的。
說了一堆嚴格的非人話,總結(jié)一下是必要的。


首先,時分復用的應(yīng)用的場合是“對于一些需要處理速度比較慢”,也就是需要的建立時間較長的單元。


其次,這些單元里面,必須“有重復運算的單元”。例如:在 FIR 濾波器里面存在很多相同位數(shù)的加法,就合適采用時分復用。


最后,時分復用的手段是“多次重復利用有關(guān)的運算器件”。


復數(shù)乘法就是一個很好的例子,里面有四個乘法呢!復數(shù)乘法,上過高中的施主都曉得的:


?


其中,real_x 表示復數(shù) x 的實部,image_x 表示復數(shù) x 的虛部?,F(xiàn)在小孩子也能數(shù)出來,公式里面存在四個乘法運算,兩個加 / 減法運算。這就是基本算法,上面的公式就是《算法說明書》的核心內(nèi)容。


僅僅依靠算法是沒法設(shè)計數(shù)字邏輯系統(tǒng)的,還需要輸入信號的性質(zhì)和輸出信號的需求等信息。連上面的假設(shè)也敢做,所謂“債多了不愁,虱子多了不癢”,對于接口信號的假設(shè)沒有理由不敢做了。假設(shè),輸入信號為 4 比特有符號數(shù),取值范圍為[-7, +7],每 8 個時鐘周期變換一次,連續(xù)輸入;對于輸出信號要求 8 比特有符號數(shù),在 8 個時鐘周期里面至少一個固定的時鐘周期 ---- 而且這個固定的時鐘周期是已知的 ---- 內(nèi)有效。這樣系統(tǒng)的輸入輸出接口基本清楚了。但是對于這種多個時鐘有效的輸入信號,必須要有一個同步信號標記輸入開始有效的時刻。這里設(shè)計這個同步信號在輸入數(shù)據(jù)有效的第一個時鐘節(jié)拍為高電平,其他時刻為低電平,如圖 7 所示。


圖 7 數(shù)據(jù)與同步信號的時序關(guān)系


現(xiàn)在是“萬事俱備只欠東風”的節(jié)奏了,開始排時序,如表 2。考慮到同步信號與數(shù)據(jù)同時到達,在下一個時鐘周期調(diào)度用的計數(shù)器才能被清零,所以有一個 -1 時刻。


表 2 時分復用的時序表

時刻

輸入選擇

運算

輸出分配

加減運算

輸入

輸出

狀態(tài)名

輸入

輸出

輸入

輸出

狀態(tài)名

-1

狀態(tài)計數(shù)清零

0

real_a

real_b

無效

REAL_REAL

無效

無效

無效

?

?

1

image_a

image_b

real_a

real_b

IMAGE_IMAGE

real_a * real_b

無效

無效

無效

?

?

2

real_a

image_b

image_a

image_b

REAL_IMAGE

image_a * image_b

real_a * real_b

real_a * real_b

無效

REAL_1

?

3

image_a

real_b

real_a

image_b

IMAGE_ REAL

real_a * image_b

image_a * image_b

image_a * image_b

real_a*

real_b

REAL_2

?

4

?

image_a

real_b

?

image_a * real_b

real_a * image_b

real_a * image_b

image_a*

image_b

IMAGE_1

?

5

?

?

?

?

image_a * real_b

image_a * real_b

real_a*

image_b

IMAGE_2

?

6

?

?

?

?

?

?

image_a *

real_b

?

有效結(jié)果輸出


還好,還好,8 個時鐘周期就可以得到有效結(jié)果的輸出。有時候,時序排不開,可是容易失眠的。實際上,上面的時序還可以優(yōu)化,但是反正滿足輸入數(shù)據(jù)頻率要求了。優(yōu)化的意義不大,這里就得過且過了。


按照表 2 總時序設(shè)計的、時分復用乘法器的復數(shù)乘法的代碼見例 5。

?


【例 5】復數(shù)乘法模塊
`define REAL_REAL?? 0
`define IMAGE_IMAGE 1
`define REAL_IMAGE? 2
`define IMAGE_REAL? 3
//Input statements

`define REAL_1????? 2
`define REAL_2????? 3
`define IMAGE_1???? 4
`define IMAGE_2???? 5
//Output statements

module complex_multiplication
//Multiplication in pipeline
? (
??? input signed[3:0] real_a,
??? input signed[3:0] image_a,
??? input signed[3:0] real_b,
??? input signed[3:0] image_b,
??? input CLK, input RST,
??? input data_start,
??? output reg signed[7:0] product_real,
??? output reg signed[7:0] product_image
? );

//Definition for Variables in the module
reg signed[6:0] real_1, real_2;
//Two operents for real part
reg signed[6:0] image_1, image_2;
//Two operents for image part
reg signed[3:0] a, b;
//Operents for signed multiplication
reg signed[6:0] product;
//Result for multiplication
reg[2:0] state_counter;
//Counter for scheduling statements

//Load other module(s)
??????????????????????????????????????????????????????????????????????????????????
//Logical
always @(posedge CLK or negedge RST)
//Multiplication to be reused
begin
??? if (!RST)
??? begin
??????? product <= 7'sh0;
??? end
??? else
??? //Statement counting
??? begin
??????? product <= a * b;
??? end
end

always @(posedge CLK or negedge RST)
//Statement management
begin
??? if (!RST)
??? begin
??????? state_counter <= 3'h7;
??? end
??? else if (data_start)
??? //New data and start the statement counting
??? begin
??????? state_counter <= 3'h0;
??? end
??? else
??? //Statement counting
??? begin
??????? state_counter <= state_counter + 3'h1;
??? end
end

//Reused multiplication part
always @(posedge CLK or negedge RST)
//Input Part
begin
??? if (!RST)
??? begin
??????? a <= 4'h0;
??????? b <= 4'h0;
??? end
??? else
??? //Input Operations
??? begin
??????? case (state_counter)
??????????? `REAL_REAL:
??????????? begin
??????????????? a <= real_a;
??????????????? b <= real_b;
??????????? end
??????????? `IMAGE_IMAGE:
??????????? begin
??????????????? a <= image_a;
??????????????? b <= image_b;
??????????? end
??????????? `REAL_IMAGE:
??????????? begin
??????????????? a <= real_a;
??????????????? b <= image_b;
??????????? end?
??????????? `IMAGE_REAL:
??????????? begin
??????????????? a <= image_a;
??????????????? b <= real_b;
??????????? end?????????????????????????????????
??????? endcase
??? end
end

always @(posedge CLK or negedge RST)
//Output Part
begin
??? if (!RST)
??? begin
??????? real_1 <= 7'h0;
??????? real_2 <= 7'h0;
??????? image_1 <= 7'h0;??
??????? image_2 <= 7'h0;????????????????????????????
??? end
??? else
??? //Input Operations
??? begin
??????? case (state_counter)
??????????? `REAL_1:
??????????? begin
??????????????? real_1 <= product;
??????????? end
??????????? `REAL_2:
??????????? begin
??????????????? real_2 <= product;
??????????? end
??????????? `IMAGE_1:
??????????? begin
??????????????? image_1 <= product;
??????????? end?
??????????? `IMAGE_2:
??????????? begin
??????????????? image_2 <= product;
??????????? end?????????????????????????????????
??????? endcase
??? end
end

//Adder part
always @(posedge CLK or negedge RST)
//Input Part
begin
??? if (!RST)
??? begin
??????? product_real <= 8'sh0;
??????? product_image <= 8'sh0;
??? end
??? else
??? //Input Operations
??? begin
??????? product_real <= real_1 - real_2;
??????? product_image <= image_1 + image_2;
??? end
end
endmodule


親們,請注意代碼里面乘號“*”只能出現(xiàn)一次,這樣是復用。如果寫成
real_1 <= a * b;
real_2 <= a * b;
image_1 <= a * b;
iamge_2 <= a * b;
或者類似的樣子,綜合軟件會毫不猶豫的給您產(chǎn)生四個乘法的,這樣就不叫時分復用了。


這正是:

時序邏輯顯神通,時鐘節(jié)拍叮叮咚。邊沿觸發(fā)生意隆,信號采樣中間空。
設(shè)計模式有三種,小心選擇變無窮。頻率面積考慮中,小心選擇變網(wǎng)紅。

與非網(wǎng)原創(chuàng)內(nèi)容,謝絕轉(zhuǎn)載!

與非網(wǎng)原創(chuàng)內(nèi)容,謝絕轉(zhuǎn)載!

系列匯總:

之一:溫故而知新:從電路里來,到 Verilog 里去!

之二:Verilog 編程無法一蹴而就,語言層次講究“名正則言順”

之三:數(shù)字邏輯不容小窺,電路門一統(tǒng)江湖

之四:Verilog 語言:還真的是人格分裂的語言

之五:Verilog 不難學,聊聊時序邏輯那些事兒

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

本名:吳濤,通信專業(yè)博士,畢業(yè)后十多年從事無線通訊產(chǎn)品的研發(fā)工作。了解W-CDMA、TDS-CDMA和LTE的標準協(xié)議、接收機算法以及系統(tǒng)架構(gòu)和開發(fā)。從事過關(guān)于W-CDMA的FPGA IP core設(shè)計工作,也完成過W-CDMA和TDS-CDMA的接收機理論研究和鏈路仿真工作。綜合上面的工作,最終選擇了無線通訊的系統(tǒng)設(shè)計和標準設(shè)計工作。目前擁有100多個已授權(quán)的發(fā)明專利,是某通訊行業(yè)標準文件的第一作者,亦有專利思想被寫入3GPP協(xié)議。已出版FPGA設(shè)計專業(yè)著作《IP核芯志-數(shù)字邏輯設(shè)計思想》和《Verilog傳奇-從電路出發(fā)的HDL代碼設(shè)計》。