2012年6月29日 星期五

Top-Down程式策略

程式變數的功能和用途。
1.計數器(counter):用來標示次數、序號,如工作次數和資料的序號。
2.累積器(ccumulator):用來存放計算結果、累算結果。
3.旗標(flag、indicator):用來標示狀態。
其中計數器為進行累加、減的變數。為能清楚表現其次序、經常執行加一或減一的運算。;
而累積器則是用來暫存各種累算的結果,無法由計數器來得。
//每仰臥起坐,每得相對的$.

獎金=0;

for(口令=1;口令<=100;口令=口令+1)

做一次仰臥起坐;

獎金=獎金+口令;

}

口令為計數值,每變化一次即為為仰臥起坐。

口令也為累積器,代表做過的仰臥起坐總數。

獎金為累積器,代表為其獎金總數。(已無法直接由計數器(口令)的最終值推算出來。

而在旗標,標示不同狀態來執行不同程序,而在設定旗標的初始化值的設定上。

需依程式來決定,初始值否定原則


//任意指定127給整數變數no,判斷是否為質數

1.判斷(no-1)是否可整除no,如果可以,no就不為質數

2.判斷(no-2)是否可整除no,如果可以,no就不為質數

 

n-2.判斷(2)是否可整除no,如果可以,no就不為質數


初始值否定原則,故我們先設為no為質數,然後在程序中去檢測來推翻。


no=127;

prime=1; //1為質數;0反之.

for(k=no-1;k>1;k--)

    if(no%k==0) prime=0; //推翻

if(prime)

  為質數

else

  不為質數




Top-Down程式策略:


1.寫出解決問題的外迴圈敘述,必要時可先用中文及(工作)數數描朮要重複執行的工作

2.逐步將迴圈內的中文句子轉成C語言,必要時使用直線方程式決定(工作)變數迴圈變數間的關係(方程式)

即類似系統分析的Top-Down,先寫出解決問題的幾個大步驟,再分若干小步驟,直到可用C描述為之。

而其中直線方程式最為重要。

EX:

印出:

image

1.由最外圍的for,可先用中文及(工作)數數描朮要重複執行的工作


for(i=0;i<5;i++)

{

印出空白;

印出*;

/n;

}

2.轉成C語言,必要時使用直線方程式決定(工作)變數迴圈變數間的關係(方程式)

(i可由0開始,除了在C語中是以從0開始外。還可方便計算出其直線關係方程。

















i012
" "864
*147

3.其" "中,其之間的直線關係式

8=a*0+b;

6=a+b;

a=-2; b=8;

其*中,其之間的直線關係式

1=a*0+b;

4=a+b;

b=1,a=3

4.

for(i=0;i<5;i++)

    印出(-2i+8)個" ";

    印出(3i+1)個*;

    \n;

5.轉換成C


#include <stdio.h>

#include <stdlib.h>

 

int main(int argc, char *argv[])

{

  int i;

  for(i=0;i<5;i++)

  {

  //space=-2i+8;

  int j;

  for(j=0;j< -2*i+8;j++) 

    printf(" ");

  //start=3i+1    

  for(j=0;j<3*i+1;j++)  

    printf("*"); 

  printf("\n"); 

                  }                   

  system("PAUSE");    

  return 0;

}



EX:求面積:

求y=x^2和y=0以x=1所來之面積

1.求其切割的次數

   因為最好為可整除的,故令1/5

   故為

iSum=0;

   for(i=0;i<=5;i++)


{

所在的面積,並做累加的動作 。y=x^2

}

2.其i與x之間的線性方程.












i013
y0.20.40.6

  故為z=0.2i+0.2

iSum=0;

   for(i=0;i<=5;i++)


{

x=(0.2*i+0.2); //x

y=x*x;//y

sum=sum+y*0.2;

}

//在未接觸Bottom-UP程式策略的什都是使用Top-Down程式策略來撰寫程式。

且少先去規劃其程式流程,而在Top-Down程式策略與規劃流程圖一樣,需要程式的經驗、直觀與巧技。

所以用Top-Down時,若寫不出時,可改以Bottom-UP程式策略。

2012年6月26日 星期二

queue

佇列;

定義

,只允許在一端進行插入操作,而在另一端中進行刪除操作的線性表(有限、有序)
其為一種先進先出(FIFO,first in first out)的線性表。
q=(a1,a2,...,an-1,an);則可設定a1為首,而an為尾。
image

queue的ADT(抽象資料類型)

ADT queue

Data

    元素為相同的類型,相鄰元素具有前後關係.

Operater

    InitQueue(*Q);//初始化,建立一個空queue

    DestoryQueue(*Q);//若queue存在,則刪除

    ClearQueue(*Q);//清除queue.

    QueueEmpty(Q);//若Q存在且為空,則回傳true

    GetHead(Q,*e);//若queue且非空,則e傳回Q首

    EndQueue(*Q,e);//若queue存在,插入新元素e到queue中.其e成為queue尾

    DeQueue(*Q,*e);//刪除queue首元素,並用e傳回

    QueueLenght(Q);//反回queue中的元素個數.

 

endADT


因為是線性表,故相同地有


順序儲存



其順序存儲時,有下列問題


image


其加入元素時,其時間O(1)


image


刪除時,則時間變為O(n)。這是因為使其queue首必須要在前面的位置上,所導致的。


而其可以改為下列,用二個變數指標來指定其首'尾.

(front,rear,front則是指下一次可讀(刪)的位置;rear指下一次可寫的位置)
以此來避免每刪一次,則需花O(n)來搬移資料。

image

1.空


image


2.滿


image


3.非空非滿


image


在此時,會出現"虛溢出",指還有空間(0)。但無法存放。


image


而為了改進此我們把rear放在0來形成循環,稱為循環queue


image


但其該如何來判斷其是是滿或空


方法1:


加一個flag


在初始時front==rear,flag=0.為空


若下次出現front==rear且flag==0.則改flag=1(滿)


方2:


保留一個空間。如下圖的情況即代表為滿。


image


image


而其


判斷是否為滿



(rear+1)%QueueSize==front


EX:


rear=0,front=1


((0+1)%5==1)?滿:非滿


rear=4,front=0


(4+1)%5==0? 滿


rear=4,front=1


(4+1)%5==1?非滿





長度



(rear-front+QueueSize)%QueueSize




typedef int QElemType;

typedef struct

{

QElemType data[MAXSIZE];

int front;

int rear;

}SqQueue;




Status InitQueue(SqQueue *Q)

{

Q->front=0;

Q->rear=0;

return OK;

}




int QueueLength(Q)

{

return (Q.rear-Q.front+MAXSIZE)%MAXSIZE);




Status EnQueue(SqQueue *q,QElemType e)

{

if((q->rear+1)%MAXSIZE==q->front))

  return ERROR;

q->data[q->rear]=e;

q->rear=q->rear+1%MAXSIZE;

}




Status DeQueue(SqQueue *q, QElemType *e)

{

if(q->rear==q->front)

    return ERROR;

*e=q->data[q->front];

q->front=q->front+1%MAXSIZE;

return OK;

}




queue link list


queue link list,與一般的link list之間.差在於 queue link list中,只會記錄其front,rear.及在新增'刪除時的操作的不同.

一般link list

image
  1: typedef int Status; 
  2: 
  3: typedef int QElemType; /* QElemType類型根據實際情形而定,這裡假設為int */
  4: 
  5: typedef struct QNode /* 節點結構 */
  6: {
  7:    QElemType data;
  8:    struct QNode *next;
  9: }QNode,*QueuePtr



而為了以link list來構成queue

則需記錄link list 的front,rear
  1: typedef struct   /* 佇列的鏈結串列結構 */
  2: {
  3:    QueuePtr front,rear; /* 隊首、隊尾指標 */
  4: }LinkQueue;
  5: 


1.空queue

image

2.新增element(rear)

image

3.刪除element(front)

image
  1: #include "stdio.h"
  2: #include "stdlib.h"
  3: #include "io.h"
  4: #include "math.h"
  5: #include "time.h"
  6: 
  7: #define OK 1
  8: #define ERROR 0
  9: #define TRUE 1
 10: #define FALSE 0
 11: #define MAXSIZE 20 /* 儲存空間初始分配量 */
 12: 
 13: typedef int Status;
 14: 
 15: typedef int QElemType; /* QElemType類型根據實際情形而定,這裡假設為int */
 16: 
 17: typedef struct QNode  /* 節點結構 */
 18: {
 19:    QElemType data;
 20:    struct QNode *next;
 21: }QNode,*QueuePtr;
 22: 
 23: typedef struct      /* 佇列的鏈結串列結構 */
 24: {
 25:    QueuePtr front,rear; /* 隊首、隊尾指標 */
 26: }LinkQueue;
 27: 
 28: Status visit(QElemType c)
 29: {
 30:   printf("%d ",c);
 31:   return OK;
 32: }
 33: /* 初始化一個空佇列Q */
 34: Status InitQueue(LinkQueue *Q)
 35: {
 36:   Q->front=Q->rear=(QueuePtr)malloc(sizeof(QNode));
 37:   if(!Q->front)
 38:     exit(OVERFLOW);
 39:   Q->front->next=NULL;
 40:   return OK;
 41: }
 42: 
 43: /* 銷毀佇列Q */
 44: Status DestroyQueue(LinkQueue *Q)
 45: {
 46:   QueuePtr p;
 47:   //已為空Q
 48:   if(Q->front==Q->rear)
 49:     return OK;
 50:   else
 51:   {
 52: 
 53:   }
 54: }
 55: /* 將佇列Q清空 */
 56: Status ClearQueue(LinkQueue *Q)
 57:   {
 58:   if(Q->front==Q->rear)
 59:     return OK;
 60:   QueuePtr p=Q->front->next;
 61:   QueuePtr q;
 62:   Q->rear=Q->front;
 63:   //**
 64:   Q->front->next=NULL;
 65:   while(p)
 66:   {
 67:     q=p->next;
 68:     free(p);
 69:     p=q;
 70:   }
 71:   return OK;
 72:   }
 73: /* 若佇列Q為空佇列,回傳TRUE,否則回傳FALSE */
 74: Status QueueEmpty(LinkQueue Q)
 75:   {
 76:     if(Q.front==Q.rear)
 77:       return TRUE;
 78:     else
 79:       return FALSE;
 80:   }
 81: /* 求佇列長度 */
 82: int QueueLength(LinkQueue Q)
 83:   {
 84:     int iCo=0;
 85:     QueuePtr p=(Q.front)->next;
 86:     for(iCo=0;p!=NULL;p=p->next,iCo++)
 87:       ;
 88:     return iCo;
 89:     //  p=Q.front;
 90:     //  while(Q.rear!=p)
 91:   }
 92: /* 若佇列Q非為空,用e返回佇列Q的隊首元素,回傳TRUE,否則回傳FALSE */
 93: Status GetHead(LinkQueue Q,QElemType *e)
 94:   {
 95:   if(Q.rear==Q.front)
 96:     return ERROR; //emty
 97:   QueuePtr p;
 98:   p=(Q.front)->next;
 99:   *e=p->data;
100:   return OK;
101:   }
102: /* 插入元素e為Q的新的隊尾元素 */
103: Status EnQueue(LinkQueue *Q,QElemType e)
104: {
105:   QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
106:   if(p==NULL)
107:     return ERROR;
108:   p->data=e;
109:   p->next=Q->rear->next;
110:   Q->rear->next=p;
111:   Q->rear=p;
112:   return OK;
113: }
114: /* 若佇列不空,刪除Q的隊首元素,用e回傳其值,並回傳OK,否則回傳ERROR */
115: Status DeQueue(LinkQueue *Q,QElemType *e)
116: {
117:   if(Q->rear==Q->front)
118:     return ERROR; //emty
119:   QueuePtr p;
120:   p=Q->front->next;
121:   *e=p->data;
122:   Q->front->next=p->next;
123:   //**
124:   if(Q->rear==p)
125:     Q->rear=Q->front;
126:   free(p);
127:   return OK;
128: }
129: /* 從隊首到隊尾依次對佇列Q中每個元素輸出 */
130: Status QueueTraverse(LinkQueue Q)
131:   {
132:     QueuePtr p=(Q.front)->next;
133:     while(p!=NULL)
134:     {
135:       visit(p->data);
136:       p=p->next;
137:     }
138:     printf("\n");
139:     return OK;
140:   }
141: int main()
142: {
143:   int i;
144:   QElemType d;
145:   LinkQueue q;
146:   i=InitQueue(&q);
147:   if(i)
148:     printf("成功建立了一個空佇列!\n");
149:   printf("是否為空佇列?%d(1:空 0:否)  ",QueueEmpty(q));
150:   printf("佇列的長度為%d\n",QueueLength(q));
151:   EnQueue(&q,-5);
152:   EnQueue(&q,5);
153:   EnQueue(&q,10);
154:   printf("插入3個元素(-5,5,10)後,佇列的長度為%d\n",QueueLength(q));
155:   printf("是否為空佇列?%d(1:空 0:否)  ",QueueEmpty(q));
156:   printf("佇列的元素依次為:");
157:   QueueTraverse(q);
158:   i=GetHead(q,&d);
159:   if(i==OK)
160:    printf("隊首元素是:%d\n",d);
161:   DeQueue(&q,&d);
162:   printf("刪除了隊首元素%d\n",d);
163:   i=GetHead(q,&d);
164:   if(i==OK)
165:     printf("新的隊首元素是:%d\n",d);
166:   ClearQueue(&q);
167:   printf("清空佇列後,q.front=%u q.rear=%u q.front->next=%u\n",q.front,q.rear,q.front->next);
168:   DestroyQueue(&q);
169:   printf("銷毀佇列後,q.front=%u q.rear=%u\n",q.front, q.rear);
170: 
171:   return 0;
172: }
173: 

stack是只限定在list的尾進行新增、刪除動作的線性表。

queue則是只可在線性表一端做新增;而在另一端做刪除動作。

Verilog basic

Various stages of ASIC/FPGA
image
Specification :
This is the stage at which we define what are the important parameters of the system/design that you are planning to design. A simple example would be: I want to design a counter; it should be 4 bit wide, should have synchronous reset, with active high enable; when reset is active, counter output should go to "0".
High Level Design:
This is the stage at which you define various blocks in the design and how they communicate. Let's assume that we need to design a microprocessor: high level design means splitting the design into blocks based on their function; in our case the blocks are registers, ALU, Instruction Decode, Memory Interface, etc
image
Micro Design/Low level design:
Low level design or Micro design is the phase in which the designer describes how each block is implemented. It contains details of State machines, counters, Mux, decoders, internal registers. It is always a good idea to draw waveforms at various interfaces. This is the phase where one spends lot of time.
image
RTL Coding:
In RTL coding, Micro design is converted into Verilog/VHDL code, using synthesizable constructs of the language. Normally we like to lint the code, before starting verification or synthesis.
Simulation :
Simulation is the process of verifying the functional characteristics of models at any level of abstraction. We use simulators to simulate the Hardware models. To test if the RTL code meets the functional requirements of the specification, we must see if all the RTL blocks are functionally correct. To achieve this we need to write a testbench, which generates clk, reset and the required test vectors. A sample testbench for a counter is shown below. Normally we spend 60-70% of time in design verification.
 
We use the waveform output from the simulator to see if the DUT (Device Under Test) is functionally correct. Most of the simulators come with a waveform viewer. As design becomes complex, we write self checking testbench, where testbench applies the test vector, then compares the output of DUT with expected values.
space.gif
There is another kind of simulation, called timing simulation, which is done after synthesis or after P&R (Place and Route). Here we include the gate delays and wire delays and see if DUT works at rated clock speed. This is also called as SDF simulation or gate level simulation.
Synthesis :
Synthesis is the process in which synthesis tools like design compiler or Synplify take RTL in Verilog or VHDL, target technology, and constrains as input and maps the RTL to target technology primitives. Synthesis tool, after mapping the RTL to gates, also do the minimal amount of timing analysis to see if the mapped design is meeting the timing requirements
image
Place & Route
image
image
Post Si Validation
Once the chip (silicon) is back from fab, it needs to be put in a real environment and tested before it can be released into Market. Since the simulation speed (number of clocks per second) with RTL is very slow, there is always the possibility to find a bug in Post silicon validation
---------------------------------
0.可合成的
/*    module
                |----------------------- |   
net/reg    |                             |
=======>   |net        net/reg   |===>net
input        |                             |    outport
port          |      /\                    |
                 |      ||net             |
                |-----------------------|
                        ||net
                        \/inout port
synthesis verilog:
include;;define;module'endmodule;parameter;input'output'inout;wire'wand'wor
reg;begin'end;always;assign;@'posedge'negedge;for;if'else;case'casex'casez;
function;task;defparam'#;?:;{{}};{}
binary bit-wise operators
~;&;|;^;~^;
logical operators:
!;&&;||
2's complement:
|;-;*
relational operators:
>;<;>=;<=
equality operators:
==;!=
logical shift operatos:
>>;<<
*/
1.data type(drive)
  reg ,wire;
reg和wire的主要區別是,reg類型的訊號只能在過程塊(後面會談到)中賦值,而wire類型的訊號只能在過程塊外賦值。這兩種訊號類型都可以出現在過程塊內部和外部的賦值運算符右邊。
使用關鍵字reg並不一定意味著編譯器會製作一個暫存器,理解這一點是非常重要的。清單2的程式碼中有一個reg類型8位元寬的內部訊號out。該模組使用暫存器源於always模組(過程塊的一種)的編程方式。值得注意的是,訊號a是一個wire類型,因此只能在連續賦值(continuous assignment)語句中賦值,而reg類型的out訊號只能在always塊中賦值。
2.variable assignment
在verilog 中
  組合邏輯combinational logic,有二個方法來model
使用assign 及always statement
  循序邏輯sequential logic,只有一個model
只能用always statement
而在initial statement中,只能用在test bench而已
3.
always block
always block should have a sensitive list or a delay associated with it.
There are two types of sensitive list: level sensitive (for combinational circuits) and edge sensitive (for flip-flops).
level sensitive:即指說是由組合邏輯產生的H,L
edge sensitive:則是由flip-flops,邊緣
在always中,it can not drive wire data type, but can drive reg and integer data types.
always  @ (a or b or sel)
begin
  y = 0;
  if (sel == 0) begin
    y = a;
  end else begin
    y = b;
  end
end
always  @ (posedge clk )
if (reset == 0) begin
  y <= 0;
end else if (sel == 0) begin
  y <= a;
end else begin
  y <= b;
end
We can have an always block without sensitive list, in this case we need to have a delay as shown in the code below.
always  begin
  #5 clk = ~clk;
end
4.
Assign Statement
only combinational logic and it is executed continuously.
 
5.funcion and task


Functions and tasks have the same syntax; one difference is that tasks can have delays, whereas functions can not have any delay. This means that function can be used for modeling combinational logic. 組合邏輯不會有delay的。
space.gif

A second difference is that functions can return a value, whereas tasks can not.

 
6.Numbers in Verilog



  • Sized or unsized numbers (Unsized size is 32 bits)
  • In a radix of binary, octal, decimal, or hexadecimal
  • Radix and hex digits (a,b,c,d,e,f) are case insensitive
  • Spaces are allowed between the size, radix and value


Syntax: <size>'<radix><value>;



  • When <size> is smaller than <value>, then leftmost bits of <value> are truncated
  • When <size> is larger than <value>, then leftmost bits are filled, based on the value of the leftmost bit in <value>.



    • Leftmost '0' or '1' are filled with '0'
    • Leftmost 'Z' are filled with 'Z'
    • Leftmost 'X' are filled with 'X'


image


Real Numbers




  • Verilog supports real constants and variables
  • Verilog converts real numbers to integers by rounding
  • Real Numbers can not contain 'Z' and 'X'
  • Real numbers may be specified in either decimal or scientific notation
  • < value >.< value >
  • < mantissa >E< exponent >
  • Real numbers are rounded off to the nearest integer when assigning to an integer.


image


Signed and Unsigned Numbers


Any number that does not have negative sign prefix is a positive number. Or indirect way would be "Unsigned".


minus sign before the size for a constant number, thus they become signed numbers.(2's complement)


image



7.Modules


  • Modules are the building blocks of Verilog designs
  • You create the design hierarchy by instantiating modules in other modules.
  • You instance a module when you use that module in another, higher-level modul

image

Ports


  • Ports allow communication between a module and its environment.
  • All but the top-level modules in a hierarchy have ports.
  • Ports can be associated by order or by name.
  1: module addbit (
  2: a      , // first input
  3: b      , // Second input
  4: ci     , // Carry input
  5: sum    , // sum output
  6: co       // carry output
  7: );
  8: //Input declaration
  9: input a;
 10: input b;
 11: input ci;
 12: //Ouput declaration
 13: output sum;
 14: output co;
 15: //Port Data types
 16: wire  a;
 17: wire  b;
 18: wire  ci;
 19: wire  sum;
 20: wire  co;
 21: //Code starts here
 22: assign {co,sum} = a + b + ci;
 23: 
 24: endmodule // End of Module addbit
  1: //-----------------------------------------------------
  2: // This is simple adder Program
  3: // Design Name : adder_explicit
  4: // File Name   : adder_explicit.v
  5: // Function    : Here the name should match 
  6: // with the leaf module, the order is not important.
  7: // Coder       : Deepak Kumar Tala
  8: //-----------------------------------------------------
  9: module adder_explicit (
 10: result        , // Output of the adder
 11: carry         , // Carry output of adder
 12: r1            , // first input
 13: r2            , // second input
 14: ci              // carry input
 15: );
 16: 
 17: // Input Port Declarations       
 18: input    [3:0]   r1         ;
 19: input    [3:0]   r2         ;
 20: input            ci         ;
 21: 
 22: // Output Port Declarations
 23: output   [3:0]  result      ;
 24: output          carry       ;
 25: 
 26: // Port Wires
 27: wire     [3:0]    r1        ;
 28: wire     [3:0]    r2        ;
 29: wire              ci        ;
 30: wire     [3:0]    result    ;
 31: wire              carry     ;
 32: 
 33: // Internal variables
 34: wire              c1        ;
 35: wire              c2        ;
 36: wire              c3        ;
 37: 
 38: // Code Starts Here
 39: addbit u0 (
 40: .a           (r1[0])        ,
 41: .b           (r2[0])        ,
 42: .ci          (ci)           ,
 43: .sum         (result[0])    ,
 44: .co          (c1)
 45: );
 46: 
 47: addbit u1 (
 48: .a           (r1[1])        ,
 49: .b           (r2[1])        ,
 50: .ci          (c1)           ,
 51: .sum         (result[1])    ,
 52: .co          (c2)
 53: );
 54: 
 55: addbit u2 (
 56: .a           (r1[2])        ,
 57: .b           (r2[2])        ,
 58: .ci          (c2)           ,
 59: .sum         (result[2])    ,
 60: .co          (c3)
 61: );
 62: 
 63: addbit u3 (
 64: .a           (r1[3])        ,
 65: .b           (r2[3])        ,
 66: .ci          (c3)           ,
 67: .sum         (result[3])    ,
 68: .co          (carry)
 69: );
 70: 
 71: endmodule // End Of Module adder

Port Connection Rules

image


  • Inputs : internally must always be of type net, externally the inputs can be connected to a variable of type reg or net.
  • Outputs : internally can be of type net or reg, externally the outputs must be connected to a variable of type net.
  • Inouts : internally or externally must always be type net, can only be connected to a variable net type.


  • Width matching : It is legal to connect internal and external ports of different sizes. But beware, synthesis tools could report problems.
  • Unconnected ports : unconnected ports are allowed by using a ",".
  • The net data types are used to connect structure.
  • A net data type is required if a signal can be driven a structural connection.
  1: module explicit();
  2: reg clk,d,rst,pre;
  3: wire q;
  4: 
  5: // Here q_bar is not connected
  6: // We can connect ports in any order
  7: dff u0 (  
  8: .q   (q),
  9: .d  (d),
 10: .clk  (clk),
 11: .q_bar  (),
 12: .rst  (rst),
 13: .pre  (pre)
 14: );
 15: 
 16: endmodule
 17: 
 18: // D fli-flop
 19: module dff (q, q_bar, clk, d, rst, pre);
 20: input clk, d, rst, pre;
 21: output q, q_bar;
 22: reg q;
 23: 
 24: assign q_bar = ~q;
 25: 
 26: always @ (posedge clk)
 27: if (rst == 1'b1) begin
 28:   q <= 0;
 29: end else if (pre == 1'b1) begin
 30:   q <= 1;
 31: end else begin
 32:   q <= d;
 33: end
 34: 
 35: endmodule




Flip-flop (electronics)

http://en.wikipedia.org/wiki/Flip-flop_(electronics)


http://opencores.org/project,gpio
http://www.fpga4fun.com/MusicBox1.html
http://www.knjn.com/FPGA-FX2.html
http://www.public.tw/prog/lock/subsite/front/Index01_Content.aspx?sid=12&aid=A&tid=3&nid=18&cid=181
http://www.asic-world.com/verilog/syntax2.html
http://www.rose-hulman.edu/~doering/PLD_Oasis/verilog_examples.htm