1. 程式人生 > >每天學一點verilog(一)

每天學一點verilog(一)

幾個經典的簡單例程

一、 /*四選一多路選擇器 */

 module MUX41a(a,b,c,d,s1,s0,y);  input a,b,c,d;  input s0,s1;  output y;    reg y;//變數有兩種,暫存器型別(reg)和線型(wire),沒有特意定義的,一般預設為wire型別  //只能對暫存器型別埠賦值    [email protected](a,b ,c ,d ,s1 ,s0)//必須列入所有輸入埠    begin : MUX41      case({s1,s0})          2'b00: y<=a;          2'b01: y<=b;          2'b10: y<=c;          2'b11: y<=d;          default: y<=a;      endcase    end  //case是一種全等比較,必須每一位都相同 //casez語句用來處理不考慮高阻態z的比較過程 //casex語句用來處理不考慮高阻值Z和不定值x的情況

二、/*D觸發器基本模組*/

module DFF1 (CLK,D,Q);    output Q;    input  CLK,D;    reg Q;    [email protected] (posedge CLK)       Q<=D; endmodule /*時序模組的簡單識別,   1、always的敏感訊號列表含有posedge或者negedge   2、always語句中有不完整的條件語句,例如if(CLK) Q<D;   3、門邏輯電路圖中有輸出到輸入的反饋   */  //一般,組合電路用阻塞式賦值,時序電路用非阻塞式賦值        /*含非同步清零和時鐘同步使能的D觸發器*/ module DFF2 (CLK,D,Q,RST,EN);//同步,依賴時鐘;非同步,不依賴時鐘    output Q;    input CLK,D,RST,EN;    

[email protected](posedge CLK or negedge RST)     //非同步清零,該復位訊號出現在always中,與時鐘在一起,說明不依賴時鐘,為非同步       begin         if(!RST) Q<=0;         else if(EN) Q<=D;       end endmodule

三、/*帶有非同步復位,同步計數使能和可預置型十進位制計數器*/

module CNT10 (CLK,RST,EN,LOAD,COUT,DOUT,DATA);     input CLK,EN,RST,LOAD;     input [3:0] DATA;//4位並行載入資料     output [3:0] DOUT;//計數資料輸出     output COUT;     reg [3:0] Q1; reg COUT;     assign DOUT=Q1;//將內部暫存器的計數結果輸出至DOUT     

[email protected](posedge CLK or negedge RST) begin             if(!RST) Q1<=0;//非同步清零             //RST下降沿時,清零,             //之後,若RST一直低電平,則一直清零狀態             //當CLK上升沿,並且RST=1,EN=1時,看LOAD的值             //LOAD=0時,置數,LOAD=1時,累加1        else if(EN) begin //同步使能EN=1,此時允許載入或計數                  if(!LOAD) Q1<=DATA;//當LOAD=0,向內部暫存器載入資料             else if(Q1<9)  Q1<=Q1+1;//當Q1小於9時,允許累加,此時為十進位制計數器             else Q1<=4'b0000; end             end           [email protected] (Q1)//組合邏輯電路         if(Q1==4'h9) COUT=1'b1;  //當Q1=1001時,COUT輸出進位標誌1            else     COUT=1'b0;  //否則,輸出進位標誌0 endmodule

四、/*移位模式可控的8位移位暫存器*/

module SHFT2(CLK,C0,MD,D,QB,CN);     output CN;//進位輸出     output [7:0] QB;//移位資料輸出     input [7:0] D;//待載入移位的資料輸入     input [2:0] MD;//移位模式控制字     input  CLK,C0;//時鐘和進位輸入     reg [7:0] REG; reg CY;        [email protected](posedge CLK) begin     case(MD)     1:begin REG[0]<=C0;REG[7:1]<=REG[6:0]; CY<=REG[7];end //帶進位迴圈左移     2:begin REG[0]<=REG[7]; REG[7:1]<=REG[6:0]; end //自迴圈左移     3:begin REG[7]<=REG[0]; REG[6:0]<=REG[7:1]; end //自迴圈右移     4:begin REG[7]<=C0; REG[6:0]<=REG[7:1]; CY=REG[0]; end //帶進位迴圈右移     5:begin REG<=D; end //載入待移數     default:begin REG<=REG;CY<=CY;end //過程結束     endcase end       assign QB=REG;//移位資料並行輸出       assign CN=CY;//左移高位輸出 endmodule

五、/*同步FIFO*/

module sc_fifo( input clk,rst,

input [7:0] din,  input wr, output full,

output reg [7:0] dout, input rd, output empty );

//1,需要一個buff雙口儲存器做儲存載體,當地址有n位,就有2^N個儲存單元,標號從0到(2^N-1)。三位地址儲存地址就是從0到7。 reg [7:0] buff[0:7];

//2,需要wr_ptr指標,與地址位數相同,指向下個可以寫的地址。 reg [2:0] wr_ptr; //3,需要rd_ptr指標,與地址位數相同,指向下個可以讀的地址。 reg [2:0] rd_ptr; //4,需要fifo_cntr計數器,比地址位數多一位,指示當前可讀的資料個數。 reg [3:0] fifo_cntr; //5,full和empty由fifo_cntr生成。 assign full=fifo_cntr==8; assign empty=fifo_cntr==0; //6,區別讀寫操作是否有效。 wire valid_rd=~empty &rd; wire valid_wr=~full&wr; //7,實現以上功能 [email protected](posedge clk) if(rst) wr_ptr<=0;else if (valid_wr) wr_ptr<=wr_ptr+1; [email protected](posedge clk) if(rst) rd_ptr<=0;else if (valid_rd) rd_ptr<=rd_ptr+1;

[email protected](posedge clk) if(rst) fifo_cntr<=0;else if ((valid_rd==0)&&(valid_wr==1)) fifo_cntr<=fifo_cntr+1; else if ((valid_rd==1)&&(valid_wr==0)) fifo_cntr<=fifo_cntr-1; /*用case語句寫 [email protected](posedge clk)  casex ({rst,valid_wr,valid_rd}) 3'b1xx : fifo_cntr<=0; 3'b010 : fifo_cntr<=fifo_cntr+1; 3'b001 : fifo_cntr<=fifo_cntr-1; 3'b011 ,3'b000 :fifo_cntr<=fifo_cntr ; endcase  */

[email protected](posedge clk) if(valid_wr) buff[wr_ptr]<=din; [email protected](posedge clk) if(valid_rd) dout<=buff[rd_ptr];

endmodule