2014年6月7日 星期六

Verilog ----基礎7

  

Verilog ----基礎7

【例10.1】非流水線方式8 位元元元全加器 
module adder8(cout,sum,ina,inb,cin,clk); 
output [7:0] sum; 
output cout; 
input [7:0] ina,inb; 
input cin,clk; 
reg [7:0] tempa,tempb,sum; 
reg cout; 
reg tempc; 
always @(posedge clk) 
      begin 
      tempa=ina;  tempb=inb;  tempc=cin;     //輸入資料鎖存 
      end 
 always @(posedge clk) 
      begin 
      {cout,sum}=tempa+tempb+tempc; 
      end 
endmodule 

  
  【例10.2 4 級流水方式的8 位元元元全加器 
module pipeline(cout,sum,ina,inb,cin,clk); 
output [7:0] sum; 
output cout; 
input [7:0] ina,inb; 
input cin,clk; 
reg [7:0] tempa,tempb,sum; 
reg tempci,firstco,secondco,thirdco,cout; 
reg [1:0] firsts,thirda,thirdb; 
reg [3:0] seconda,secondb,seconds; 
reg [5:0] firsta,firstb,thirds; 

    always @(posedge clk) 
         begin 
         tempa=ina;  tempb=inb;  tempci=cin;     //輸入資料緩存 
         end 
     always @(posedge clk) 
         begin 
          {firstco,firsts}=tempa[1:0]+tempb[1:0]+tempci; 
                                     //第一級加(低2位) 
          firsta=tempa[7:2];           //未參加計算的資料緩存 
          firstb=tempb[7:2]; 
         end 
     always @(posedge clk) 
     begin 
         {secondco,seconds}={firsta[1:0]+firstb[1:0]+firstco,firsts};  
                                          //第二級加(第23位相加) 
          seconda=firsta[5:2];                      //數據緩存 
          secondb=firstb[5:2]; 
         end 
     always @(posedge clk) 
         begin 
        {thirdco,thirds}={seconda[1:0]+secondb[1:0]+secondco,seconds}; 
                                          //第三級加(第45位相加) 
         thirda=seconda[3:2];             //數據緩存 
         thirdb=secondb[3:2]; 
         end 
     always @(posedge clk) 
         begin 
          {cout,sum}={thirda[1:0]+thirdb[1:0]+thirdco,thirds}; 
                                          //第四級加(高兩位相加) 
         end 
  endmodule 

      
      【例10.3 】兩個加法器和一個選擇器的實現方式 
module resource1(sum,a,b,c,d,sel); 
parameter size=4; 
output [size:0] sum; 
input sel; 
input [size-1:0] a,b,c,d; 
reg [size:0] sum; 
always @(a or b or c or d or sel) 
      begin 
      if (sel)  sum=a+b; 
      else    sum=c+d; 
      end 
 endmodule 

  
  【例10.4 】兩個選擇器和一個加法器的實現方式 
module resource2(sum,a,b,c,d,sel); 
parameter size=4; 
output [size-1:0] sum; 
input sel; 
input [size-1:0] a,b,c,d; 
reg [size-1:0] atemp,btemp; 
reg [size:0] sum; 
always @(a or b or c or d or sel) 
      begin 
      if (sel)  begin  atemp=a;  btemp=b;  end 
      else    begin  atemp=c;  btemp=d;  end 
      sum=atemp+btemp; 
      end 
endmodule 

  
  【例10.5 】狀態機設計的例子 
module FSM(clk,clr,out,start,step2,step3); 
input clk,clr,start,step2,step3; 
output [2:0] out; 
reg [2:0] out; 
reg [1:0] state,next_state; 
parameter    state0=2'b00,state1=2'b01, 
                state2=2'b11,state3=2'b10; 
          /*狀態編碼,採用格雷(Gray)編碼方式*/ 
always @(posedge clk or posedge clr)       /*該進程定義起始狀態*/ 
begin 
      if  (clr) state <= state0; 
      else state <= next_state; 
    end 
 always @(state or start or step2 or step3) /*該進程實現狀態的轉換*/ 
    begin     
    case (state) 
          state0: begin 
               if (start)   next_state <=state1; 
               else           next_state <=state0; 
               end 
          state1: begin 
                          next_state <= state2; 
               end 
          state2: begin 
               if (step2)   next_state <=state3; 
               else           next_state <=state0; 
               end 
          state3: begin 
               if (step3)   next_state <=state0; 
               else           next_state <=state3;  
               end 
          default:          next_state <=state0;      /*default語句*/ 
     endcase 
    end 

    always @(state)           /*該進程定義組合邏輯(FSM 的輸出)*/ 
    begin 
    case (state) 
               state0: out=3'b001; 
               state1: out=3'b010; 
               state2: out=3'b100; 
               state3: out=3'b111; 
               default:out=3'b001;  /*default語句,避免鎖存器的產生*/ 
    endcase 
    end 
 endmodule 

      
      【例10.6 】自動轉換量程頻率計控制器 
    /*信號定義: 
clk            輸入時鐘; 
clear         為整個頻率計的非同步重定信號; 
reset         用來在量程轉換開始時復位計數器; 
std_f_sel  用來選擇標準時基; 
cntover       代表超量程; 
cntlow        代表欠量程。 
狀態ABCDEF採用一位元熱碼編碼  */ 

module control(std_f_sel,reset,clk,clear,cntover,cntlow); 
output [1:0] std_f_sel; 
output reset; 
input clk,clear,cntover,cntlow; 
reg [1:0] std_f_sel; 
reg reset; 
reg [5:0] present,next;     //用於保存當前狀態和次態的中間變數 
parameter start_fl00k=6'b000001,     //狀態A 編碼,採用1位元熱碼 
          fl00k_cnt=6'b000010,             //狀態
          start_fl0k=6'b000100,            //狀態
          fl0k_cnt=6'b001000,              //狀態
          start_flk=6'b010000,             //狀態
          flk_cnt=6'b100000;               //狀態
always @(posedge clk or posedge clear) 
     begin  
      if (clear)   present<=start_fl0k;    //start_fl0k為起始狀態 
     else          present<=next; 
     end 
always @(present or cntover or cntlow) 
     begin 
      case (present)                 //case語句描述狀態轉換 
      start_fl00k:      next<=fl00k_cnt; 
      fl00k_cnt: 
               begin 
               if (cntlow)   next<=start_fl0k; 
               else          next<=fl00k_cnt; 
               end 
      start_fl0k:       next<=fl0k_cnt; 
      fl0k_cnt: 
               begin 
               if (cntlow)            next<=start_flk; 
               else  if (cntover)    next<=start_fl00k; 
               else                 next<=fl0k_cnt; 
           end 
          start_flk:          next<=flk_cnt; 
          flk_cnt: 
                    begin 
                    if (cntover)        next<=start_fl0k; 
                    else                next<=flk_cnt; 
                    end 
          default:next<=start_fl0k;        //缺省狀態為起始狀態 
          endcase 
          end 
 

    always @(present)          //該進程產生各狀態下的輸出 
          begin 
          case (present) 
          start_fl00k:
               begin     reset=1;  std_f_sel=2'b00;  end 
          fl00k_cnt:     
         begin     reset=0;  std_f_sel=2'b00;  end 
          start_fl0k:     
   begin     reset=1;  std_f_sel=2'b01;  end 
          fl0k_cnt:         
 begin     reset=0;  std_f_sel=2'b01;  end 
          start_flk:        
begin   reset=1;  std_f_sel=2'b11;  end 
          flk_cnt:          
               begin     reset=0;  std_f_sel=2'b11;  end 
          default:         
  begin     reset=1;  std_f_sel=2'b01;  end 
          endcase 
          end 
    endmodule 

      
      【例10.7 8 位全加器 
    module add8(sum,cout,b,a,cin); 
    output [7:0] sum; 
    output cout; 
    input [7:0] a,b; 
    input cin; 
         assign {cout,sum}=a+b+cin; 
    endmodule 

      
      【例10.88 位寄存器 
     module reg8(qout,in,clk,clear); 
     output [7:0] qout; 
     input [7:0] in; 
     input clk,clear; 
reg [7:0] qout; 
     always @(posedge clk or posedge clear) 
     begin 
      if (clear)    qout=0;          //非同步清
      else           qout=in; 
     end 
 endmodule  

  
  【例10.9 】累加器頂層連接文本描述 
module acc(accout,cout,accin,cin,clk,clear); 
output [7:0] accout; 
output cout; 
input [7:0] accin; 
input cin,clk,clear; 
wire [7:0] sum; 
add8 accadd8(sum,cout,accout,accin,cin);      //調用add8 子模組 
reg8 accreg8(accout,sum,clk,clear);            //調用reg8 子模組 
endmodule 

  
  【例10.10】用`include 描述的累加器 
`include “add8.v”; 
`include “reg8.v”; 
module accn(accout,cout,accin,cin,clk,clear); 
output [7:0] accout; 
output cout; 
input [7:0] accin; 
input cin,clk,clear; 
wire [7:0] sum; 


add8 accadd8(sum,cout,accout,accin,cin);        //調用add8 子模組 
reg8 accreg8(accout,sum,clk,clear);       //調用reg8 子模組 
endmodule 

  
  【例10.11】阻塞賦值方式描述的移位寄存器
 module block1(Q0,Q1,Q2,Q3,din,clk); 
 output Q0,Q1,Q2,Q3; 
 input clk,din; 
 reg Q0,Q1,Q2,Q3; 
     always @(posedge clk) 
          begin 
          Q3=Q2;                 //注意賦值語句的順序 
           Q2=Q1; 
           Q1=Q0; 
           Q0=din; 
          end 
     endmodule 

      
 【例10.12】阻塞賦值方式描述的移位寄存器
     module block2(Q0,Q1,Q2,Q3,din,clk); 
     output Q0,Q1,Q2,Q3; 
     input clk,din; 
     reg Q0,Q1,Q2,Q3; 
     always @(posedge clk) 
          begin 
          Q3=Q2; 
           Q1=Q0;         //該句與下句的順序與例10.11顛倒 
           Q2=Q1; 
           Q0=din; 
          end 
     endmodule 
      
       【例10.13】阻塞賦值方式描述的移位寄存器
     module block3(Q0,Q1,Q2,Q3,din,clk); 
     output Q0,Q1,Q2,Q3; 
     input clk,din; 
     reg Q0,Q1,Q2,Q3; 
     always @(posedge clk) 
         begin 
          Q0=din;//4條賦值語句的順序與例10.11 完全顛倒 
          Q1=Q0; 
          Q2=Q1; 
          Q3=Q2; 
          end 
     endmodule 
      
       【例10.14】非阻塞賦值方式描述的移位寄存器 
module block4(Q0,Q1,Q2,Q3,din,clk); 
output Q0,Q1,Q2,Q3; 
input clk,din; 
reg Q0,Q1,Q2,Q3; 
 always @(posedge clk) 
     begin 
      Q3<=Q2; 
      Q1<=Q0; 
      Q2<=Q1; 
      Q0<=din; 
     end 
endmodule 

  
  【例10.15】長幀同步時鐘的產生 
 module longframe1(clk,strb); 
 parameter delay=8; 
 input clk; 
 output strb; 
reg strb; 
 reg [7:0] counter; 
 always@(posedge clk) 
      begin 
      if (counter==255)    counter=0; 
       else                counter=counter+1; 
     end 
 always@(counter) 
     begin 
      if (counter<=(delay-1))  strb=1; 
      else             strb=0; 
      end 
 endmodule 
  
  【例10.16】引入了D 觸發器的長幀同步時鐘的產生 
 module longframe2(clk,strb); 
 parameter delay=8;  
 input clk; 
 output strb; 
 reg [7:0] counter; 
 reg temp; 
 reg strb; 
 always@(posedge clk)   
     begin 
        if (counter==255)      counter=0; 
        else                counter=counter+1; 
      end 

     always@(posedge clk) 
         begin 
         strb=temp;          //引入一個觸發器 
         end 
     always@(counter) 
        begin  
         if (counter<=(delay-1))  temp=1; 
         else                        temp=0; 
         end 


     endmodule  

沒有留言:

張貼留言