【FPGA課程—Verilog設計】實驗彙總,10個經典數字系統電路

文章目錄

一、4位半加法器的Verilog實現

二、138譯碼器的Verilog實現

三、並行輸入串行輸出移位寄存器

四、帶異步復位和置位、上升沿觸發的觸發器

五、模10計數器

六、停車位剩餘計數顯示牌的Verilog實現

七、銀行排號機系統電路

八、分頻器(2的偶數分頻、16分頻(佔空比爲2:14)、5分頻)

九、四選一數據選擇器——testbench仿真

十、ASK調製、FSK調製(正弦波)


一、4位半加法器的實現

  • 半加器: 加數和被加數爲輸入,sum與進位爲輸出。
  • 全加器: 加數、被加數與低位的進位數爲輸入,sum與進位爲輸出

四位半加器:輸入爲四位加數、四位被加數, 輸出爲四位和數、1位進位。

比如:

  • 1000+0000=1000, 輸出“和數爲1000、進位爲0
  • 1000+1000=0000, 輸出“和數爲0000、進位爲1

1、系統框圖

2、Verilog代碼

  • add4_half.v(源文件)
module add4_half(a,b,sum,cout);

	input [3:0] a,b;  //a、b<--輸入
	output [3:0] sum; //sum-->輸出變量
	output cout;  //cout-->輸出變量
	
	assign {cout,sum}=a+b; //a+b,進位保存至cout,和數保存至sum
	
endmodule
https://img-blog.csdnimg.cn/20200427161803873.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyNjA1MzAw,size_16,color_FFFFFF,t_70
RTL Viewer結果

 

  • tb_add4_half.v(testbench仿真文件)
`timescale 1us/1ps  //Time Delay Unit is 1us

module tb_add4_half();
  reg [3:0] A,B; //Two input registers 
 // wire sum;     //sum --> set as one wire ,for sum is operated by assign statement
 // wire cout;    //cout -->set as one wire ,for cout is operated by assign statement
  parameter delay = 5000; //delayTime's numbers, delayTime=5ms
  
  add4_half Instance(
    .a(A), 
    .b(B)
  );//Mappings and instantiation
 

/* Initializing Input Signals */    
  initial 
      begin
       /*Five sets of examples*/
               A=4'b0101; B=4'b1010;    // Group 1   its result should be "sum=1111=15,cout=0" >5+10=15     overflow bit = 0 
        #delay A=4'b0001; B=4'b0001;    // Group 2   its result should be "sum=0010=2,cout=0"  >1+1=2       overflow bit = 0 
        #delay A=4'b1000; B=4'b1000;    // Group 3   its result should be "sum=0000=0,cout=1"  >8+8=15+1    overflow bit = 1 
        #delay A=4'b1010; B=4'b1001;    // Group 4   its result should be "sum=0011=3,cout=1"  >10+9=15+4   overflow bit = 1         
        #delay A=4'b1111; B=4'b1111;    // Group 5   its result should be "sum=1110=14,cout=1" >15+14=15+14 overflow bit = 1
        #delay; //if u don't write down this delay statement, the last result will be invisible.
      end
  
endmodule

3、仿真結果

二、138譯碼器的Verilog實現

1、系統框圖

2、Verilog代碼

  • decode_138.v(源文件)
module decode_138(A, Y_n);
	input [2:0] A;
	output reg[7:0] Y_n;
	always @(A)
		begin
			case(A)
				3'b000: Y_n=8'b1111_1110 ; //0---Y_0
				3'b001: Y_n=8'b1111_1101 ; //1---Y_1
				3'b010: Y_n=8'b1111_1011 ; //2---Y_2
				3'b011: Y_n=8'b1111_0111 ; //3---Y_3
				3'b100: Y_n=8'b1110_1111 ; //4---Y_4
				3'b101: Y_n=8'b1101_1111 ; //5---Y_5
				3'b110: Y_n=8'b1011_1111 ; //6---Y_6
				3'b111: Y_n=8'b0111_1111 ; //7---Y_7
			endcase
		end
endmodule
RTL Viewer

 

  • tb_decode_138.v(testbench仿真文件)
`timescale 1us/1ps //延時單位爲1us,精度爲1ps

module tb_decode_138();
  reg [2:0] A;
  
  parameter delay=5; //每產生一個結果,延時5us
  
  //例化
  decode_138 instance1(
    .A(A)
  );
  
  //初始化賦值5組樣例
  initial 
    begin  
      A=3'd1; //1-->第2個燈亮(從右往左,低電平)
      #delay 
      A=3'd3; //3-->第4個燈亮(從右往左,低電平)
      #delay 
      A=3'd7; //7-->第8個燈亮(從右往左,低電平)
      #delay 
      A=3'd5; //5-->第6個燈亮(從右往左,低電平)
      #delay 
      A=3'd0; //0-->第1個燈亮(從右往左,低電平)
      #delay;
    end
endmodule

3、仿真結果

三、並行輸入串行輸出移位寄存器

1、系統框圖

2、Verilog代碼

  • shift_4t1.v(源文件)
/*移位寄存器--並行輸入串行輸出(4-->1)   同步加載、移位*/
module shift_4t1(clk, din, load, q);
	input clk, load;
	input [3:0] din;
	output reg q;
	
	reg [3:0] tmp;
	
	always@(posedge clk)
		begin 
			if(load==1'b1) //上升沿到來且滿足load=1時,將din值加載到tmp
				tmp <= din; 
			else //上升沿到來且滿足load=1時,將tmp向左移位
				//begin循環移位
				begin //tmp=1
					tmp <= tmp<<1;
					tmp[0] <= 1'b0;
					q <= tmp[3]; //此處q等於前一個上升沿的tmp[3],而不是tmp<<1後的tmp
				end
		end	
	
endmodule
  • tb_shift_4t1.v(testbench仿真文件)
`timescale 10ns/1ps  //Time Delay Unit is 10ns

module tb_shift_4t1();
  reg CLK, LOAD; //Three input registers 
  reg [3:0] DIN; 
  //wire Q;     //Q --> set Q as one wire
  
  parameter clkCircle = 10; //clkCircle's numbers, clkCircle=10ns
  parameter delay = 80; //delayTime's numbers, delayTime=0.8us
  
  shift_4t1 Instance(
    .clk(CLK), 
    .load(LOAD),
    .din(DIN)
  );//Mappings and instantiation
 
 /*CLK*/
  initial 
    begin 
      CLK=0;
      forever
        #(clkCircle/2) CLK = ~ CLK; //Flip the level state of CLK every half cycle
    end 

 /* Initializing Input Signals */    
  initial 
    begin
      
       DIN=4'b0001; 
       LOAD = 1; //Load the first DIN(tmp of DIN is updated)
       @(posedge CLK);  //Waiting for posedge clock "CLK" 
       LOAD = 0;  //tmp of DIN is beginning shifting left and ouput Q  
       #delay;    //Delay some time, awaiting before Next DIN's loading 
              
       DIN=4'b0111; 
       LOAD = 1;    //Load the first DIN(tmp of DIN is updated)
       @(posedge CLK);  //Waiting for posedge clock "CLK" 
       LOAD = 0; 	//tmp of DIN is beginning shifting left and ouput Q      
       #delay;    //Delay some time, awaiting before Next DIN's loading
       
      
       DIN=4'b1010; 
       LOAD = 1; //Load the first DIN(tmp of DIN is updated)
       @(posedge CLK);  //Waiting for posedge clock "CLK" 
       LOAD = 0; 	//tmp of DIN is beginning shifting left and ouput Q     
       #delay; //Delay some time, awaiting before Next DIN's loading
       
       DIN=4'b1101; 
       LOAD = 1;     //load the first DIN(tmp of DIN is updated)
       @(posedge CLK);  //waiting for posedge clock "CLK" 
       LOAD = 0; 	     
       #delay; //delay some time, awaiting before Next DIN's loading
       
       DIN=4'b1111; 
       LOAD = 1;
       @(posedge CLK);  //waiting for posedge clock "CLK" 
       LOAD = 0; 	     
       #delay; //Delay some time, awaiting before Next DIN's loading
       
       DIN=4'b0101;  
       LOAD = 1;
       @(posedge CLK);  //waiting for posedge clock "CLK" 
       LOAD = 0; 	     
       #delay; //delay some time, awaiting before Next DIN's loading
       
    end
  
endmodule

3、仿真結果

四、帶異步復位和置位、上升沿觸發的觸發器

1、系統框圖

2、Verilog代碼

  • dff_asynrst.v(源文件)
module dff_asynrst(data,rst,set,clk,q); 

	input data,rst,set,clk; 
	output reg q; 
	
	always@(posedge clk or posedge rst or posedge set) //三個異步時鐘信號
		begin 
			if(rst==1'b1) //如果復位信號來到,將q置0
				q <= 1'b0; 
			else if(set==1'b1)  //如果置位信號來到,將q置1
				q <= 1'b1; 
			else 
				q<=data;  //否則,將data值賦值給q
		end 
endmodule
  • tb_dff_asynrst.v(testbench仿真文件)
module

3、仿真結果

五、模10計數器

1、系統框圖

2、Verilog代碼

  • counter10.v(源文件)
//模10計數器的Verilog HDL設計
module counter10(clk, rst_n, en, dout, co);
 
	input clk, rst_n, en;
	output[3:0] dout;
	reg [3:0] dout;
	output co;
	 
	always@(posedge clk or negedge rst_n)
		begin
			if(!rst_n)
				dout <= 4'b0000;        //系統復位,計數器清零
			else if(en)
				if(dout == 4'b1001)     //計數值達到5時,計數器清零
					dout <= 4'b0000;
				else
					dout <= dout + 1'b1; //否則,計數器加1
			else
				dout <= dout;
		 
		end
	
	assign co = dout[0]&dout[3];  //當計數達到5(4'b1001)時,進位爲1,計數值爲其他,都沒有進位
 
endmodule
  • tb_counter10.v(testbench仿真文件)
module

3、仿真結果

六、停車場剩餘車位計數顯示牌的Verilog實現

1、系統框圖

2、Verilog代碼

  • parkinglot.v(源文件)
module parkinglot(in, out, remain,num_1,num_0,led_1,led_0);
	input in, out;
	
	output reg [4:0] remain;	
	output reg [3:0] num_1,num_0;
	output reg [6:0] led_1, led_0;
	
	integer i;
	
	initial  //初始化
		begin	
			remain = 5'b11000; //初始賦值爲24
		end
	
	
	always@(in or out)  //main_module,計數器處理
		begin 
			if(in == 1'b1 && remain>0)   
				begin
					remain <= remain - 1'b1; 
				end
			if(out == 1'b1 && remain<24) 
				begin
					remain <= remain + 1'b1;
				end
		end
	
	always@(remain) //將剩餘車位數量轉換成BCD碼,並將個位數、十位數保存至num_0、num_1
		begin 
			num_1=4'd0;
			num_0=4'd0;
			for(i=4;i>=0;i=i-1)
				begin	
					if(num_1>=5)
						num_1=num_1+3;
					if(num_0>=5)
						num_0=num_0+3;
					num_1 = num_1<<1;
					num_1[0] = num_0[3];
					num_0 = num_0<<1;
					num_0[0]= remain[i];
				end		
		end	
		
	
	always@(num_0) //將一條5位的remain總線轉換成2條7位的led總線(供顯示模塊調用以顯示)
		begin 
			case(num_0)
				5'd0: led_0<=7'b011_1111;
				5'd1: led_0<=7'b000_0110;
				5'd2: led_0<=7'b101_1011;
				5'd3: led_0<=7'b100_1111;
				5'd4: led_0<=7'b110_0110;
				5'd5: led_0<=7'b110_1101;
				5'd6: led_0<=7'b111_1100; 
				5'd7: led_0<=7'b000_0111;
				5'd8: led_0<=7'b111_1111;
				5'd9: led_0<=7'b110_0111;
				default: led_0<=7'b000_0000;
			endcase
			
			case(num_1)
				5'd0: led_1<=7'b011_1111;
				5'd1: led_1<=7'b000_0110;
				5'd2: led_1<=7'b101_1011;
				default: led_1<=7'b000_0000;
			endcase
		end	

endmodule

 參考二進制碼轉換爲BCD碼,Verilog代碼實現

  • tb_parkinglot.v(testbench仿真文件)
`timescale 1us/1ps  //Time Delay Unit is 1us
 
module tb_parkinglot();sim:/tb_parkinglot/OUT sim:/tb_parkinglot/IN sim:/tb_parkinglot/Instance
  reg  IN, OUT; //Two input registers 
  
  parkinglot Instance(
    .in(IN), 
    .out(OUT)
  );//Mappings and instantiation

 
 /* Initializing Input Signals */    
  initial 
    begin
      IN=0;
      OUT=0;
    end
  
  initial 
    begin
      #10  IN=1;OUT=0;
      #10 OUT=1;IN=0;
      #10  IN=1;OUT=0;
      #20  OUT=1;IN=0;
      #2  IN=1;OUT=0;
      #15 OUT=1;IN=0;
      #1  OUT=1;IN=0;
      #30 IN=1;OUT=0;
      #3  IN=1;
      #1  OUT=1;
      #3  IN=1;
      #1  OUT=1;
      #20 IN=1;
      #5  OUT=1;
      #20;
    end
  
endmodule    

3、仿真結果

七、銀行排號機系統電路

1、系統框圖

2、Verilog代碼

  • BankQueue.v(源文件)
module BankQueue(N, V, key1, key2, key3, led1, led2, led3); 
	input N, V, key1, key2, key3; 
	output led1, led2, led3; 
	reg [7:0] led1, led2, led3; 
	
	reg [7:0] vw=8'b0000_0000, nw=8'b0000_0000;
	reg [7:0] cntn=8'b0000_0000, cntv=8'b1100_1000; //排號機普通客戶計數器、VIP客戶計數器
	reg [7:0] cntnormal=8'b0000_0000, cntvip=8'b1100_1000; //櫃檯的普通客戶、VIP客戶計數器
	
	always@( N or V ) //異步時序,電平觸發
		begin 
			if(V == 1'b1 && cntv+cntn < 8'd500) 
				cntv = cntv + 8'd1; 
			if(N== 1'b1 && cntv+cntn < 8'd500)
				cntn = cntn+ 8'd1; 
		end
		
	always@ (cntv or cntvip or cntn or cntnormal) //VIP競爭機制
		begin 
			vw = cntv - cntvip;  //櫃檯VIP計數器的號數 - 排號機VIP計數器的號數纔可以接下一個客戶
			nw = cntn - cntnormal; 
		end
	
	
	
	always@ (key1 or key2 or key3) //異步時序,電平觸發
		begin 
					
			if(key1 == 1'b1) //當key1按下時
				if(vw > 0) //若VIP客戶搶得
					begin
						cntvip = cntvip + 1;
						led1 = cntvip; 	//顯示正在處理的號數
					end
				else if(nw > 0)
					begin
						cntnormal = cntnormal + 1;
						led1 = cntnormal;	//顯示正在處理的號數
					end
				
			if(key2 == 1'b1)
				if(vw > 0)
					begin
						cntvip = cntvip + 1;
						led2 = cntvip; 	//顯示正在處理的號數
					end
				else if(nw > 0)
					begin
						cntnormal = cntnormal + 1;
						led2 = cntnormal;	//顯示正在處理的號數
					end
			
			if(key3 == 1'b1)
				if(vw > 0)
					begin
						cntvip = cntvip + 1;
						led3 = cntvip; 	//顯示正在處理的號數
					end
				else if(nw > 0)
					begin
						cntnormal = cntnormal + 1;
						led3 = cntnormal;	//顯示正在處理的號數
					end
		end
		
endmodule
  • tb_BankQueue.v(testbench仿真文件)
`timescale 1ns/1ps 
 
module tb_BankQueue();
  reg N, V, Key1, Key2, Key3;
  BankQueue Test(.N(N),.V(V),.key1(Key1),.key2(Key2),.key3(Key3));
 
  initial //Initiating
    begin
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
    end
  
  initial //Process
    begin
      #1 
      N=1;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #3 
      N=1;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1  
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1  
      N=0;
      V=0;
      Key1=1;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #2 
      N=1;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=1;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=1;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=1;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=1;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #3  
      N=0;
      V=0;
      Key1=1;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=1;  //
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1
      N=0;
      V=0;
      Key1=1;  //
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=1;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=1;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=1;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=1;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=1;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=1;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=1;
      
      #1 
      N=0;
      V=0;
      Key1=0;
      Key2=0;
      Key3=0;
      
      #1 
      N=1;   //
      V=1;   //
      Key1=1; 
      Key2=0;
      Key3=0;
      
      #1; 
    end
endmodule      

3、仿真結果

八、分頻器(2的偶數分頻、16分頻(佔空比爲2:14)、5分頻)

① 2的整數次冪的偶數分頻器——2、4、8、16分頻器

  • 系統框圖

  • Verilog代碼

  1、freq_div.v(源文件)

/*2的整數次冪偶數分頻器:2、4、8、16分頻器*/
module freq_div(clk,rst,clk2,clk4,clk8,clk16);
    input    rst,clk;
    output    clk2,clk4,clk8,clk16;
    wire    clk2,clk4,clk8,clk16; //用"assign"語句賦值的變量,需定義爲wire型
    reg    [3:0]    cnt;
    
    always@(posedge clk or posedge rst) //上升沿觸發,只有復位纔會重置爲零的計數器
        begin    
            if(rst==1'b1)        
                cnt <= 4'b0000;    
            else    
                cnt <= cnt+1;
        end
    
    assign    clk2 = cnt[0]; //取出計數變量cnt的相應位的0、1狀態作爲本身的0、1狀態
    assign    clk4 = cnt[1];
    assign    clk8 = cnt[2];
    assign    clk16 = cnt[3];
    
endmodule 

2、 tb_freq_div.v(testbench仿真文件)

module

3、仿真結果

 佔空比爲2:14的16分頻器

  • 系統框圖

  • Verilog代碼

  1、freq_div.v(源文件)

/*佔空比不爲50%的分頻器————2:14佔空比16分頻器*/
module freq_div(clk,rst, clk2_14);
 
    input clk,rst;
    output reg clk2_14;
    reg [3:0] cnt;
    
    always@(posedge clk or posedge rst)   //上升沿觸發,只有復位纔會重置爲零的計數器
        begin
            if(rst == 1'b1)
                cnt <=4'b0000;        //重置計數變量cnt爲0
            else 
                cnt <= cnt + 1; 
        end
        
    always@(posedge clk or posedge rst)
        begin
            if(rst == 1'b1)
                clk2_14 <= 1'b0;     //rst重置clk2_14爲0(低電平)
            else if(cnt ==13 || cnt == 14) 
                clk2_14 <= 1'b1;     //當rst==0、上升沿到來,且cnt已經計數到13或14時,將clk2_14置爲1(高電平)
            else
                clk2_14=1'b0;     //當rst==0、上升沿到來,且cnt沒有計數到13、14,clk2_14置爲0(低電平)
        end    
 
endmodule 

2、 tb_freq_div.v(testbench仿真文件)

module

3、仿真結果

 奇數分頻器——5分頻器

  • 系統框圖

  • Verilog代碼

  1、freq_div.v(源文件)

/*奇數分頻器——5分頻器*/
module freq_div(clk, rst, clk_5);
    input clk, rst;
    output clk_5;
    wire clk_5;        //用"assign"語句賦值的變量,需定義爲wire型
    reg  [2:0]  cnt_pre, cnt_later;
    reg  clk_5_pre, clk_5_later;
 
    
    always@(posedge clk or posedge rst)    // 上升沿觸發,5進制計數器。範圍:000、001、010、011、100
        if(rst == 1)
            cnt_pre <= 3'b000;
        else if(cnt_pre == 3'b100)  //  000 001 010 011 100 --> 000 001 010 011 100 --> 001 010 011 100 --> ···
            cnt_pre <= 3'b000;
        else
            cnt_pre <= cnt_pre + 1;
    
    always@(posedge clk or posedge rst)    //上升沿觸發,佔空比爲2:3的分頻器
        if(rst == 1)
            clk_5_pre <= 0;
        else if(cnt_pre == 3'b000 || cnt_pre == 3'b100)  // 在上升沿到來時,計數到000或100之後這樣判斷爲1,纔會置爲1(高電平) 
            clk_5_pre <= 1;
        else
            clk_5_pre =0;
            
    always@(negedge clk or posedge rst)    // 下降沿觸發,5進制計數器。範圍:000、001、010、011、100
        if(rst == 1)
            cnt_later <= 3'b000;
        else if(cnt_later == 3'b100)  // 000 001 010 011 100 --> 000 001 010 011 100 --> 001 010 011 100 --> ···
            cnt_later <= 3'b000;
        else
            cnt_later <= cnt_later + 1;
    
    always@(negedge clk or posedge rst)    //下降沿觸發,佔空比爲2:3的分頻器
        if(rst == 1)
            clk_5_later <= 0;
        else if(cnt_later == 3'b000 || cnt_later == 3'b100)  // 在下降沿到來時,計數到000或100之後這樣判斷爲1,纔會置爲1(高電平) 
            clk_5_later <= 1;
        else
            clk_5_later =0;
    
    assign clk_5 = clk_5_pre | clk_5_later; 
    
endmodule

   tb_freq_div.v(testbench仿真文件)

module

3、仿真結果

九、四選一數據選擇器——testbench仿真

1、系統框圖

2、Verilog代碼

  • t1.v(源文件)
module t1(a,b,c,d,s1,s0,y);
	input a,b,c,d;
	input s0,s1;
	output y;
	reg y=0; //這裏要賦初值,不然仿真時就看不到y的輸出結果了
	always@(a,b,c,d,s1,s0)
		begin 
			case({s1,s0})
				2'b00: y<=a; // s1_s0 = 00時,y=a(這裏的下劃線指s1和s0間的拼接符)
				2'b01: y<=b; // s1_s0 = 01時,y=b
				2'b10: y<=c; // s1_s0 = 10時,y=c
				2'b11: y<=d; // s1_s0 = 11時,y=d
				default: y<=a; // 其他情況,y=a
			endcase
		end
endmodule
 
  • tb_t1.v(testbench仿真文件)
`timescale 1ns/1ps
 
module tb_t1();
  reg va,vb,vc,vd,s1,s0;
  t1 T1(.a(va),.b(vb),.c(vc),.d(vd),.s1(s1),.s0(s0));
 
  initial 
    begin
      va=0;
      vb=1;
      vc=0;
      vd=1;
    end
  
  initial 
    begin
      s1=0;
      #10 s1=1;
      #1 s1=0;
      #15 s1=1;
      #1 s1=0;
      #20 s1=1;
      #1 s1=0;
      #10 s1=1;
      #1 s1=0;
      #30 s1=1;
      #1 s1=0;
    end
  
  initial 
    begin
      s0=0;
      #18 s0=1;
      #1 s0=0;
      #8 s0=1;
      #1 s0=0;
      #30 s0=1;
      #1 s0=0;
      #40 s0=1;
      #1 s0=0;
    end
  
endmodule      

3、仿真結果

十、ASK調製、FSK調製(正弦波)

1)ASK調製(鍵控法)

① 系統框圖

② Verilog代碼

  • ASK_modulate.v(源文件)
module ASK_modulate(clk, start, x, y);
 
	input clk;
	input start; //開始調製的信號
	input x; //基帶信號(調製前的信號)
 
	output y; //調製後的信號
	wire y;
  
	reg [1:0] q; //分頻計數器
	reg f;       //載波信號
 
	always @(posedge clk) 
		begin 
			if(start == 0)
				q <= 0 ;
			else if(q <= 1) //
				begin 
					f <= 1;
					q <= q + 1;
				end
			else if(q==3) //
				begin 
					f <= 0;
					q <= 0;
				end 
			else          //
				begin 
					f <= 0;
					q <= q + 1;
				end
		end
 
	assign y = x && f;  //對基帶信號進行調製
 
endmodule
  • tb_ASK_modulate.v(testbench仿真文件)
`timescale 100ns/1ps  //延時間隔單位爲0.1us
 
module TB_ASK_Modulate();
  reg CLK, START, X;
  
  //parameter initTime = 30;
  parameter period = 2;
  
  ASK_modulate Obj(.clk(CLK), .start(START), .x(X));
  
  /*時鐘脈衝信號,佔空比爲50%,週期爲period=0.2us*/ 
  initial 
    begin 
      CLK = 0;
      //#initTime; 
      forever
        #(period/2) CLK = ~CLK; 
    end
 
 
    /*同步啓動信號,CLK的第一個下降沿到來後開始ASK調製*/   
    initial 
    begin 
      START=0; 
	    @(posedge CLK);        
	    START=1;
    end	 
 
    /*基帶信號*/    
    initial 
      begin
        X=0;
        #50   X=1;  // 1持續5us
        #50   X=0;  // 0持續5us
        #50   X=1;  // 1持續10us
        #100  X=0;  // 0持續10us
        #100  X=1;  // 1持續5us
        #50   X=0;  // 0持續10us
        #100  X=1;  // 1持續5us
        #50   X=0;  // 0持續不變
      end	
  
endmodule

③ 仿真結果

1)FSK調製(正弦波模擬)

① 系統框圖

② Verilog代碼

  • FSK_modulate_mini.v(源文件)
module FSK_modulate_mini(
	input clk,//時鐘信號
	output reg [7:0]sigOut,//輸出已調信號
	output reg [7:0]carryWave1,//1對應的載波幅度
	output reg [7:0]carryWave0,//0對應的載波幅度
	output wire codeSource,//數字基帶信號
	output reg codeClk=0,//用來控制數字基帶信號的時鐘
	output reg stClk=0//用來控制載波的時鐘,數字基帶時鐘週期應爲載波時鐘的n倍
);
 
//分頻器部分
reg [7:0]codeClkCount=0;//時鐘計數器
reg [3:0]carryClkCount=0;//載波時鐘計數器
always @(posedge clk)
	begin
		//codeClk
		if(codeClkCount==127)
			begin
				codeClk=~codeClk;
				codeClkCount=0;
			end
		else
			begin
				codeClkCount=codeClkCount+1;
			end
		
		//carryClk
		if(carryClkCount==1)
			begin
				stClk=~stClk;
				carryClkCount=0;
			end
		else
			begin
				carryClkCount=carryClkCount+1;
			end
	end
 
//數字基帶信號,m序列發生器
reg [5:0]outReg=6'b010101;//序列寄存器初始化
reg mAdded;//m序列移位的輔助變量
assign codeSource=outReg[5];//輸出變量爲寄存器序列的最高位
always @(negedge codeClk)
	begin
		//手動異或
		if(outReg[0]==outReg[5])
			begin
				mAdded=0;
			end
		else
			begin
				mAdded=1;
			end
		outReg=outReg<<1;//對寄存器左移
		outReg=outReg+mAdded;
	end
 
//載波的產生
reg [7:0]waveCount=0;//載波幅度查詢變量
always @(posedge stClk)
	begin
		if(waveCount==63)
			begin
				waveCount=0;
			end
		else
			begin
				waveCount=waveCount+1;
			end
		
		//根據查詢變量進行載波幅度查詢
		case(waveCount)
			0: begin carryWave0<=0;carryWave1<=0; end
			1: begin carryWave0<=12;carryWave1<=25; end
			2: begin carryWave0<=25;carryWave1<=49; end
			3: begin carryWave0<=37;carryWave1<=71; end
			4: begin carryWave0<=49;carryWave1<=90; end
			5: begin carryWave0<=60;carryWave1<=106; end
			6: begin carryWave0<=71;carryWave1<=117; end
			7: begin carryWave0<=81;carryWave1<=125; end
			8: begin carryWave0<=90;carryWave1<=127; end
			9: begin carryWave0<=98;carryWave1<=125; end
			10:begin carryWave0<=106;carryWave1<=117; end
			11:begin carryWave0<=112;carryWave1<=106; end
			12:begin carryWave0<=117;carryWave1<=90; end
			13:begin carryWave0<=122;carryWave1<=71; end
			14:begin carryWave0<=125;carryWave1<=49; end
			15:begin carryWave0<=126;carryWave1<=25; end
			16:begin carryWave0<=127;carryWave1<=0; end
			17:begin carryWave0<=126;carryWave1<=-25; end
			18:begin carryWave0<=125;carryWave1<=-49; end
			19:begin carryWave0<=122;carryWave1<=-71; end
			20:begin carryWave0<=117;carryWave1<=-90; end
			21:begin carryWave0<=112;carryWave1<=-106; end
			22:begin carryWave0<=106;carryWave1<=-117; end
			23:begin carryWave0<=98;carryWave1<=-125; end
			24:begin carryWave0<=90;carryWave1<=-127; end
			25:begin carryWave0<=81;carryWave1<=-125; end
			26:begin carryWave0<=71;carryWave1<=-117; end
			27:begin carryWave0<=60;carryWave1<=-106; end
			28:begin carryWave0<=49;carryWave1<=-90; end
			29:begin carryWave0<=37;carryWave1<=-71; end
			30:begin carryWave0<=25;carryWave1<=-49; end
			31:begin carryWave0<=12;carryWave1<=-25; end
			32:begin carryWave0<=0;carryWave1<=0; end
			33:begin carryWave0<=-12;carryWave1<=25; end
			34:begin carryWave0<=-25;carryWave1<=49; end
			35:begin carryWave0<=-37;carryWave1<=71; end
			36:begin carryWave0<=-49;carryWave1<=90; end
			37:begin carryWave0<=-60;carryWave1<=106; end
			38:begin carryWave0<=-71;carryWave1<=117; end
			39:begin carryWave0<=-81;carryWave1<=125; end
			40:begin carryWave0<=-90;carryWave1<=127; end
			41:begin carryWave0<=-98;carryWave1<=125; end
			42:begin carryWave0<=-106;carryWave1<=117; end
			43:begin carryWave0<=-112;carryWave1<=106; end
			44:begin carryWave0<=-117;carryWave1<=90; end
			45:begin carryWave0<=-122;carryWave1<=71; end
			46:begin carryWave0<=-125;carryWave1<=49; end
			47:begin carryWave0<=-126;carryWave1<=25; end
			48:begin carryWave0<=-127;carryWave1<=0; end
			49:begin carryWave0<=-126;carryWave1<=-25; end
			50:begin carryWave0<=-125;carryWave1<=-49; end
			51:begin carryWave0<=-122;carryWave1<=-71; end
			52:begin carryWave0<=-117;carryWave1<=-90; end
			53:begin carryWave0<=-112;carryWave1<=-106; end
			54:begin carryWave0<=-106;carryWave1<=-117; end
			55:begin carryWave0<=-98;carryWave1<=-125; end
			56:begin carryWave0<=-90;carryWave1<=-127; end
			57:begin carryWave0<=-81;carryWave1<=-125; end
			58:begin carryWave0<=-71;carryWave1<=-117; end
			59:begin carryWave0<=-60;carryWave1<=-106; end
			60:begin carryWave0<=-49;carryWave1<=-90; end
			61:begin carryWave0<=-37;carryWave1<=-71; end
			62:begin carryWave0<=-25;carryWave1<=-49; end
			63:begin carryWave0<=-12;carryWave1<=-25; end
		endcase
	end
 
//調製部分
always @(posedge stClk)
	begin
		if(codeSource)
			begin
				sigOut=carryWave1;
			end
		else
			begin
				sigOut=carryWave0;
			end
	end
 
endmodule
  • tb_TB_FSK_modulate_mini.v(testbench仿真文件)
`timescale 10ns/10ps
 
module TB_FSK_modulate_mini();
	reg clk;
	wire [7:0]sigOut;
	wire [7:0]carryWave0;
	wire [7:0]carryWave1;
	wire codeSource;
	wire codeClk;
	wire stClk;
 
	FSK_modulate_mini Obj(
		.clk (clk),
		.sigOut (sigOut),
		.carryWave0 (carryWave0),
		.carryWave1 (carryWave1),
		.codeSource (codeSource),
		.codeClk (codeClk),
		.stClk (stClk)
	);
	 
	parameter clkper=100;
	 
	initial 
		begin
			clk = 1'b0;
		end
	 
	always
	  begin
		 #(clkper / 2) clk=~clk;
	  end
 
endmodule

③ 仿真結果

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章