2014年6月7日 星期六

Verilog ----基礎6

Verilog ----基礎6

【例9.1】基本門電路的幾種描述方法 
  1)門級結構描述 
module gate1(F,A,B,C,D); 
input A,B,C,D; 
output F; 
nand (F1,A,B);            //調用門元件 
and (F2,B,C,D); 
or (F,F1,F2); 
endmodule 

  2 )資料流程描述 
module gate2(F,A,B,C,D); 
input A,B,C,D; 
output F; 
assign F=(A&B)|(B&C&D);         //assign持續賦值 
endmodule 

  3 )行為描述 
 module gate3(F,A,B,C,D); 
 input A,B,C,D; 
 output F; 
     reg F; 
     always @(A or B or C or D)                 //過程賦值 
           begin 
           F=(A&B)|(B&C&D); 
           end 
     endmodule 

      
   【例9.2 】用bufif1 關鍵字描述的三態門 
    module tri_1(in,en,out); 
     input in,en; 
     output out; 
     tri out; 
    bufif1 b1(out,in,en);      //注意三態門埠的排列順序 
    endmodule 

      
      【例9.3 】用assign 語句描述的三態門 
    module tri_2(out,in,en); 
     output out; 
     input in,en; 
     assign out = en ? in : 'bz; 
           //en=1,則out=in;若en=0,則out 為高阻態 
     endmodule 
      
   【例9.4 】三態雙向驅動器 
    module bidir(tri_inout,out,in,en,b); 
     inout tri_inout; 
     output out; 
     input in,en,b; 
     assign tri_inout = en ? in : 'bz; 
     assign out = tri_inout ^ b; 
    endmodule 

      
   【例9.5 】三態雙向驅動器 
    module bidir2(bidir,en,clk); 
     inout [7:0] bidir; 
     input en,clk; 
     reg [7:0] temp; 
     assign bidir= en ? temp : 8'bz; 
     always @(posedge clk) 
     begin 
      if (en)  temp=bidir; 
      else      temp=temp+1; 
     end 
endmodule 

  
  【例9.6 3-8 解碼器 
 module decoder_38(out,in); 
 output [7:0] out; 
 input [2:0] in; 
 reg [7:0] out; 
 always @(in) 
   begin 
    case (in) 
      3'd0: out=8'b11111110; 
      3'd1: out=8'b11111101; 
      3'd2: out=8'b11111011; 
      3'd3: out=8'b11110111; 
      3'd4: out=8'b11101111; 
      3'd5: out=8'b11011111; 
      3'd6: out=8'b10111111; 
      3'd7: out=8'b01111111; 
    endcase 
   end 
 endmodule 

  
  【例9.7 8-3 優先編碼器 
 module encoder8_3(none_on,outcode,a,b,c,d,e,f,g,h); 
 output none_on; 
 output [2:0] outcode; 
 input a,b,c,d,e,f,g,h; 
 reg [3:0] outtemp; 
 assign {none_on,outcode}=outtemp; 
 always @(a or b or c or d or e or f or g or h) 
   begin 
      if (h)              outtemp=4'b0111; 
      else if (g)         outtemp=4'b0110; 
      else if (f)         outtemp=4'b0101; 
      else if (e)         outtemp=4'b0100; 
      else if (d)         outtemp=4'b0011; 
      else if (c)         outtemp=4'b0010; 
      else if (b)          outtemp=4'b0001; 
      else if (a)          outtemp=4'b0000;    
      else                 outtemp=4'b1000; 
      end 
     endmodule 
      
 【例9.8】用函數定義的8-3 優先編碼器 
    module code_83(din, dout); 
     input [7:0] din; 
     output [2:0] dout; 
     function[2:0] code;       //函數定義 
     input [7:0] din;       //函數只有輸入埠,輸出為函數名本身 
     if (din[7])                code = 3'd7; 
    else if (din[6])            code = 3'd6; 
    else if (din[5])            code = 3'd5; 
    else if (din[4])            code = 3'd4; 
    else if (din[3])            code = 3'd3; 
    else if (din[2])            code = 3'd2; 
    else if (din[1])            code = 3'd1; 
    else                        code = 3'd0; 
    endfunction 
    assign  dout = code(din);   //函數調用 
    endmodule 
      
      【例9.9 】七段數碼管解碼器 
     module decode47(a,b,c,d,e,f,g,D3,D2,D1,D0); 
     output a,b,c,d,e,f,g; 
     input D3,D2,D1,D0;                         //輸入的4BCD 
     reg a,b,c,d,e,f,g; 
     always @(D3 or D2 or D1 or D0) 
       begin 
           case ({D3,D2,D1,D0})                 //case語句進行解碼 
           4'd0: {a,b,c,d,e,f,g}=7'b1111110; 
           4'd1: {a,b,c,d,e,f,g}=7'b0110000; 
           4'd2: {a,b,c,d,e,f,g}=7'b1101101; 
           4'd3: {a,b,c,d,e,f,g}=7'b1111001; 
           4'd4: {a,b,c,d,e,f,g}=7'b0110011; 
           4'd5: {a,b,c,d,e,f,g}=7'b1011011; 
      4'd6: {a,b,c,d,e,f,g}=7'b1011111; 
      4'd7: {a,b,c,d,e,f,g}=7'b1110000; 
      4'd8: {a,b,c,d,e,f,g}=7'b1111111; 
      4'd9: {a,b,c,d,e,f,g}=7'b1111011; 
      default: {a,b,c,d,e,f,g}=7'bx; 
      endcase 
   end 
 endmodule 

  
  【例9.10】奇偶校驗位產生器 
 module parity(even_bit,odd_bit,input_bus); 
 output even_bit,odd_bit; 
 input [7:0] input_bus; 
 assign odd_bit = ^ input_bus;             //產生奇校驗位 
 assign even_bit = ~odd_bit;           //產生偶校驗位 
 endmodule 

  
  【例9.11】用if-else 語句描述的4 1 MUX 
module mux_if(out,in0,in1,in2,in3,sel); 
output out; 
input in0,in1,in2,in3; 
input [1:0] sel; 
reg out; 
always @(in0 or in1 or in2 or in3 or sel) 
     begin 
     if (sel==2'b00)         out=in0; 
     else if (sel==2'b01)    out=in1; 
     else if (sel==2'b10)    out=in2; 
     else                   out=in3; 
     end 
endmodule 

  
  【例9.12】用case 語句描述的4 1 MUX 
module mux_case(out,in0,in1,in2,in3,sel); 
output out; 
input in0,in1,in2,in3; 
input [1:0] sel; 
reg out; 
always @(in0 or in1 or in2 or in3 or sel) 
  begin 
     case (sel) 
                         2'b00: out=in0; 
                         2'b01: out=in1; 
                         2'b10: out=in2; 
                         default: out=in3; 
     endcase 
 end 
endmodule 

          
           【例9.13】用組合電路實現的ROM 
         module rom(addr,data); 
         input [3:0] addr; 
         output [7:0] data; 
         function[7:0] romout; 
         input [3:0] addr; 
                  case (addr) 
                  0 : romout = 0; 
                  1 : romout = 1; 
                  2 : romout = 4; 
                  3 : romout = 9; 
                  4 : romout = 16; 
                  5 : romout = 25; 
                  6 : romout = 36; 
                  7 : romout = 49; 
                  8 : romout = 64; 
                  9 : romout = 81; 
                  10 : romout = 100; 
                  11 : romout = 121; 
                  12 : romout = 144; 
                  13 : romout = 169; 
                  14 : romout = 196; 
                  15 : romout = 225; 
                  default : romout = 8'hxx; 
                  endcase 
         endfunction 
         assign data = romout(addr); 
         endmodule 
          
 【例9.14】基本D 觸發器 
module DFF (Q,D,CLK); 
output Q; 
input D,CLK; 
reg Q; 
always @(posedge CLK) 
     begin 
     Q <= D; 
     end 
endmodule 

 
 【例9.15】帶非同步清0、非同步置1 D 觸發器 
module DFF1 (q,qn,d,clk,set,reset); 
input d,clk,set,reset; 
output q,qn; 
reg q,qn; 
always @(posedge clk or negedge set or negedge reset) 
  begin 
     if (!reset) begin 
                    q <= 0;             //非同步清0,低電平有效 
                    qn <= 1; 
              end 
     else if (!set)  begin 
                    q <= 1;             //非同步置1,低電平有效 
                    qn <= 0; 
                    end 
     else       begin 
                    q <= d; 
                    qn <= ~d; 
                end 
  end 
endmodule 

 
 【例9.16】帶同步清0、同步置1 D 觸發器 
module DFF2(q,qn,d,clk,set,reset); 
input d,clk,set,reset; 
output q,qn; 
reg q,qn; 
always @(posedge clk) 
  begin 
     if  (reset)  begin                                                                                        
             q <= 0; qn <= 1;      //同步清0,高電平有效 
                  end 
          else if (set) begin 
             q <=1;  qn <=0;        //同步置1,高電平有效 
                      end 
          else   begin 
              q <= d;  qn <= ~d; 
                 end 
    end 
 endmodule 

      
      【例9.17】帶非同步清0、非同步置1 JK 觸發器 
     module JK_FF(CLK,J,K,Q,RS,SET); 
     input CLK,J,K,SET,RS; 
     output Q; 
     reg Q; 
     always @(posedge CLK or negedge RS or negedge SET) 
       begin 
          if (!RS)  Q <= 1'b0; 
          else if (!SET) Q <= 1'b1; 
          else case ({J,K}) 
               2'b00 :  Q <= Q; 
               2'b01 :  Q <= 1'b0; 
               2'b10 : Q <= 1'b1; 
               2'b11 : Q <= ~Q; 
               default: Q<= 1'bx; 
               endcase 
     end 
     endmodule 
      
      【例9.18】電平敏感的1 位元資料鎖存器 
    module latch_1(q,d,clk); 
    output q; 
    input d,clk; 
    assign q = clk ? d : q;   //時鐘信號為高電平時,將輸入端資料鎖存 
    endmodule 
      
      【例9.19】帶置位和復位端的1 位元數據鎖存器 
module latch_2(q,d,clk,set,reset); 
output q; 
input d,clk,set,reset; 
assign q = reset ? 0 : (set ? 1 : (clk ? d : q)); 
endmodule 

  
  【例9.20 8 位元數據鎖存器 
module latch_8(qout,data,clk); 
output [7:0] qout; 
input [7:0] data; 
input clk; 
reg [7:0] qout; 
always @(clk or data) 
     begin 
      if (clk) qout<=data; 
     end 
endmodule 

  
  【例9.21 8 位元資料寄存器 
module reg8(out_data,in_data,clk,clr); 
output[7:0] out_data; 
input [7:0] in_data; 
input clk,clr; 
reg [7:0] out_data; 
always @(posedge clk or posedge clr) 
     begin 
      if (clr)  out_data <=0; 
      else     out_data <=in_data; 
     end 
endmodule 

  
  【例9.22 8 位移位寄存器 
module shifter(din,clk,clr,dout); 
input din,clk,clr; 
output [7:0] dout; 
reg [7:0] dout; 
always @(posedge clk) 
     begin 
      if (clr)  dout<= 8'b0;     //同步清0,高電平有效 
      else 
          begin 
           dout <= dout << 1;                       //輸出信號左移一位元 
           dout[0] <= din;        //輸入信號補充到輸出信號的最低位元 
         end 
    end 
endmodule 

      
      【例9.23 】可變模加法/減法計數器 
    module updown_count(d,clk,clear,load,up_down,qd); 
    input [7:0] d; 
    input clk,clear,load; 
    input up_down; 
    output [7:0] qd; 
    reg [7:0] cnt; 
    assign qd = cnt; 
    always @(posedge clk) 
         begin 
          if  (!clear)   cnt = 8'h00;       //同步清0,低電平有效 
          else  if (load)        cnt = d;       //同步預置 
          else  if (up_down)   cnt = cnt + 1;      //加法計數 
          else          cnt = cnt - 1;           //減法計數 
         end 
 endmodule 

      
      【例9.24 4 位元Johnson 計數器(非同步重定) 
    module johnson(clk,clr,out); 
    input clk,clr; 
    output [3:0] out; 
    reg [3:0] out; 
    always @(posedge clk or posedge clr) 
         begin 
          if (clr)     out<= 4'h0; 
          else 
               begin   out<= out<< 1; 
                       out[0]<= ~out[3]; 
             end 
         end 
    endmodule 
      
      【例9.25 256 ×8 RAM 模組 
  module ram256x8(data,address,we,inclock,outclock,q); 
 input [7:0] data; 
  input [7:0] address; 
  input we,inclock,outclock; 
  output [7:0] q; 
  lpm_ram_dq myram (.q(q),.data(data),.address(address), 
                .we(we),.inclock(inclock),.outclock(outclock)); 
  defparam myram.lpm_width=8;               //定義資料寬度 
  defparam myram.lpm_widthad=8;                //定義地址寬度 
  endmodule 
    
    【例9.26 256 ×16 RAM  
  module map_lpm_ram(dataout,datain,addr,we,inclk,outclk); 
  input [15:0] datain;                      //埠定義 
  input [7:0] addr; 
  input we,inclk,outclk; 
  output [15:0] dataout; 
        //lpm_ram_dq 元件例化 
  lpm_ram_dq ram(.data(datain),.address(addr),.we(we),.inclock(inclk), 
     .outclock(outclk),.q(dataout)); 
  defparam ram.lpm_width=16;                    //參數賦值 
  defparam ram.lpm_widthad=8; 
  defparam ram.lpm_indata="REGISTERED"; 
  defparam ram.lpm_outdata="REGISTERED"; 
  defparam ram.lpm_file="map_lpm_ram.mif"; //RAM塊中的內容取自該檔 
endmodule 

    
    【例9.27 4 位串並轉換器 
  module serial_pal(clk,reset,en,in,out); 
  input clk,reset,en,in; 
  output [3:0] out; 
 reg [3:0] out; 
  always @ (posedge clk) 
       begin 
        if (reset)    out<=4'h0; 
      else if (en)    out<={out,in};     //使用連接運算符 
       end 
  endmodule 

    
    【例9.28 】用函數實現簡單的處理器 
  module mpc(instr,out); 
  input [17:0] instr;          //instr 為輸入的指令 
  output[8:0] out;             //輸出結果 
    reg [8:0] out; 
    reg func; 
    reg [7:0] op1,op2;        //從指令中提取的兩個運算元 
    function[16:0] code_add;       //函數的定義 
    input [17:0] instr; 
    reg add_func; 
    reg [7:0] code,opr1,opr2; 
        begin 
         code=instr[17:16];    //輸入指令instr 的高2位元是操作碼 
         opr1=instr[7:0];    //輸入指令instr 的低8位元是運算元opr1 
         case (code) 
          2'b00:  
             begin 
             add_func=1; 
             opr2=instr[15:8];     //instr 中取第二個運算元 
             end 
          2'b01: 
             begin 
              add_func=0; 
              opr2=instr[15:8];    //instr 中取第二個運算元 
             end 
          2'b10: 
             begin 
              add_func=1; 
              opr2=8'd1;     //第二個運算元取為1,實現+1操作 
             end 
         default: 
             begin 
              add_func=0; 
              opr2=8'd1;        //實現-1操作 
             end 
         endcase 
         code_add={add_func,opr2,opr1}; 
      end 
     endfunction 
   always @(instr) 
        begin 
     {func,op2,op1}=code_add(instr);      //調用函數 
     if (func==1)  out=op1+op2;      //實現兩數相加、運算元1 1操作 
     else         out=op1-op2;       //實現兩數相減、運算元11操作 
     end 
endmodule 

  
  【例9.29 】微處理器的測試代碼 
`timescale 10ns/1ns 
`include "mpc.v" 
module mpc_tp; 
reg [17:0] instr; 
wire [8:0] out; 
parameter DELY=10; 
mpc m1(instr,out);             //調用待測試模組 
initial begin 
      instr=18'd0; 
#DELY instr=18'b00_01001101_00101111; 
#DELY instr=18'b00_11001101_11101111; 
#DELY instr=18'b01_01001101_11101111; 
#DELY instr=18'b01_01001101_00101111; 
#DELY instr=18'b10_01001101_00101111; 
#DELY instr=18'b11_01001101_00101111; 
#DELY instr=18'b00_01001101_00101111; 
#DELY $finish; 
end 
initial $monitor($time,,,"instr=%b out=%b",instr,out); 
endmodule 

  
  【例9.30 】乘累加器(MAC )代碼 
module MAC(out,opa,opb,clk,clr); 
output [15:0] out; 
input [7:0] opa,opb; 
input clk,clr; 
wire [15:0] sum; 
reg [15:0] out; 
function[15:0] mult;    //函數定義,mult 函數完成乘法操作 
input [7:0] opa,opb;    //函數只能定義輸入端,輸出埠為函數名本身 
reg [15:0] result; 
    integer i; 
    begin 
       result = opa[0]? opb : 0; 
       for (i= 1; i <= 7; i = i+1) 
       begin 
        if (opa[i]==1)  result=result+(opb<<(i-1)); 
       end 
       mult=result; 
    end 
    endfunction 
    assign sum=mult(opa,opb)+out; 
    always @(posedge clk or posedge clr) 
        begin 
         if (clr)   out<=0; 
         else        out<=sum; 
        end 
    endmodule 

      
      【例9.31 】乘累加器的測試代碼 
     'timescale 1ns/1ns 
     'include "mac.v" 
    module mac_tp; 
    reg [7:0] opa,opb;         //測試輸入信號用reg 型變數 
    reg clr,clk; 
    wire [15:0] out;       //測試輸出信號用wire 型變數  
    parameter DELY = 100;  
     //測試物件調用 
    MAC m1(out,opa,opb,clk,clr); 
    always #(DELY) clk = ~clk;                 //產生時鐘波形 
    initial begin                              //激勵波形定義 
          clr=1;clk=0;opa=8'd0; opb=8'd0; 
     #DELY clr=0;opa=8'd1; opb=8'd10; 
     #DELY opa=8'd2; opb=8'd10; 
     #DELY opa=8'd3; opb=8'd10; 
#DELY opa=8'd4; opb=8'd10; 
     #DELY opa=8'd5; opb=8'd10; 
#DELY opa=8'd6; opb=8'd10; 
#DELY opa=8'd7; opb=8'd10; 
#DELY opa=8'd8; opb=8'd10; 
#DELY opa=8'd9; opb=8'd10; 
#DELY opa=8'd10; opb=8'd10; 
#DELY $finish; 
end 

                  //結果顯示 
initial $monitor($time,,,"clr=%b opa=%d opb=%d out=%d",clr,opa,opb,out); 
endmodule 


沒有留言:

張貼留言