【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

③ 仿真结果

 

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