FPGA实验二

实验一:四选一选择器

// module  test3, 选择器(mux)的代码,
module test3(
  IN0       ,   // input 1
  IN1       ,   // input 2
  IN2       ,   // input 3
  IN3       ,   // input 4
  SEL1      ,   // select 
  SEL2      ,
  OUT       );  // out data
parameter WL = 16;      // 输入输出数据信号位宽
input [WL-1:0] IN0, IN1, IN2, IN3;// 选择器的两个输入数据信号
input SEL1,SEL2;              // 通道选通的控制信号
output[WL-1:0] OUT;     // 选择器的输入数据信号

reg   [WL-1:0] OUT;
// 生成组合逻辑的代码
always @ (IN0 or IN1 or IN2 or IN3 or SEL1 or SEL2) begin
  if(SEL1==0 && SEL2==0) // SEL为1 选择输入1
    OUT = IN0;
  else if(SEL1==1 && SEL2==0)
	OUT = IN1;
  else if(SEL1==0 && SEL2==1)   // SEL为0 选择输入0
    OUT = IN2;
  else
	OUT = IN3;
end
endmodule
// endmodule top

时序图:

编码得出的二选一选择器结构:

二选一选择器消耗资源:

编码得出的四选一选择器结构

四选一选择器消耗资源:

实验二:4x4交叉选择器

代码:

// module  top, a 2x2 crossbar switch circuit

module test4(
  IN0       ,   // input 1
  IN1       ,   // input 2
  IN2       ,   // input 3
  IN3       ,   // input 4
  SEL0      ,   // select the output0 source 
  SEL1      ,   // select the output1 source 
  SEL2      ,   // select the output2 source 
  SEL3      ,   // select the output3 source 
  OUT0      ,   // output data 0
  OUT1      ,
  OUT2      ,
  OUT3      ,
  );  // output data 1
parameter WL = 16;
input [WL-1:0] IN0, IN1, IN2, IN3;
input SEL0, SEL1, SEL2, SEL3;
output[WL-1:0] OUT0, OUT1, OUT2, OUT3;

reg   [WL-1:0] OUT0, OUT1, OUT2, OUT3;
// get the OUT0
always @ (IN0 or IN1 or IN2 or IN3 or SEL0 or SEL1) begin
  if(SEL0==0 && SEL1==0)
    OUT0 = IN0;
  else if(SEL0==1 && SEL1==0)
    OUT0 = IN1;
  else if(SEL0==0 && SEL1==1)
	OUT0 = IN2;
  else
	OUT0 = IN3;
end
// get the OUT1
always @ (IN0 or IN1 or IN2 or IN3 or SEL1 or SEL2) begin
  if(SEL1==0 && SEL2==0)
    OUT1 = IN0;
  else if(SEL1==1 && SEL2==0)
    OUT1 = IN1;
  else if(SEL1==0 && SEL2==1)
	OUT1 = IN2;
  else
	OUT1 = IN3;
end
// get the OUT2
always @ (IN0 or IN1 or IN2 or IN3 or SEL2 or SEL3) begin
  if(SEL2==0 && SEL3==0)
    OUT2 = IN0;
  else if(SEL2==1 && SEL3==0)
    OUT2 = IN1;
  else if(SEL2==0 && SEL3==1)
	OUT2 = IN2;
  else
	OUT2 = IN3;
end
// get the OUT1
always @ (IN0 or IN1 or IN2 or IN3 or SEL0 or SEL3) begin
  if(SEL0==0 && SEL3==0)
    OUT3 = IN0;
  else if(SEL0==1 && SEL3==0)
    OUT3 = IN1;
  else if(SEL0==0 && SEL3==1)
	OUT3 = IN2;
  else
	OUT3 = IN3;
end

endmodule
// endmodule top

4x4选择器消耗资源

2X2选择器消耗资源

RTL结构图

实验三:8输入优先编码器

设计8输入优先编码器只需要对4输入优先编码器进行简单的修改,代码如下:

// module top, 4 input priority encoder with zero input check
module test5(
  IN        ,   // input  
  OUT       );  // output 
input [7:0] IN;
output[3:0] OUT;

reg   [2:0] OUT;
// get the OUT
always @ (IN) begin
   if(IN[7])       // 第一优先
     OUT = 4'b0111;
   else if(IN[6])  // 第二优先
     OUT = 4'b0110;
   else if(IN[5])  // 第三优先
     OUT = 4'b0101;
   else if(IN[4])  // 第四优先
     OUT = 4'b0100;
   else if(IN[3])  // 第四优先
     OUT = 4'b0011;
   else if(IN[2])  // 第四优先
     OUT = 4'b0010;
   else if(IN[1])  // 第四优先
     OUT = 4'b0001;
   else if(IN[0])  // 第四优先
     OUT = 4'b0000;
   else            // 什么都没有检测到
     OUT = 4'b1111; // 输出值可自定义,不和上面的输出值混淆即可
end
endmodule

时序图:

其RTL图如下:

实验四:4-16译码器、

代码:

// module top, 4 input priority encoder with zero input check
module test6(
  IN        ,   // input  
  OUT       );  // output 

input [3:0] IN;
output[15:0] OUT;

reg   [15:0] OUT;
// get the OUT
always @ (IN) begin
  case(IN)
    4'b0000: OUT = 16'b0000_0000_0000_0001;
    4'b0001: OUT = 16'b0000_0000_0000_0010;
    4'b0010: OUT = 16'b0000_0000_0000_0100;
    4'b0011: OUT = 16'b0000_0000_0000_1000;
    4'b0100: OUT = 16'b0000_0000_0001_0000;
    4'b0101: OUT = 16'b0000_0000_0010_0000;
    4'b0110: OUT = 16'b0000_0000_0100_0000;
    4'b0111: OUT = 16'b0000_0000_1000_0000;
    
    4'b1000: OUT = 16'b0000_0001_0000_0000;
    4'b1001: OUT = 16'b0000_0010_0000_0000;
    4'b1010: OUT = 16'b0000_0100_0000_0000;
    4'b1011: OUT = 16'b0000_1000_0000_0000;
    4'b1100: OUT = 16'b0001_0000_0000_0000;
    4'b1101: OUT = 16'b0010_0000_0000_0000;
    4'b1110: OUT = 16'b0100_0000_0000_0000;
    4'b1111: OUT = 16'b1000_0000_0000_0000;
    //  full case 不需要写default,否则一定要有default
  endcase
end
endmodule

3-8译码器的资源开销:

4-16译码器的资源开销:

RTL图:

实验五:加法器

代码如下:

module test7(
  IN1   ,
  IN2   ,
  OUT   );
input[3:0] IN1, IN2;
output[3:0] OUT;
reg[3:0] OUT;
always@(IN1 or IN2) begin // 生成组合逻辑的always 块
  OUT = IN1 + IN2;
end
endmodule

波形仿真图如下:

从波形仿真图中可以看出,从00变化到11并不能做到同时反转,存在过渡过程01。

00变成11与00变成10相比,后者的过渡过程偏多。

不难看出,如果输入输出信号宽度都为4比特,输出结果的大小会溢出导致结果错误。

如果将输入信号的位宽改为8比特,输出延迟会增大。例如当输入信号位宽为4比特时,输出延迟为1ns左右,改为8比特后卫2ns左右。

 

实验六:补码加法器

补码加法器代码与加法器相同。

可以看出当两数相加大于等于0时能够得到正确的数值结果。

增加位宽后延时加大。

实验七:带流水线的加法器

代码:

module test9(
  IN1   ,
  IN2   ,
  CLK   ,
  OUT   );
input  [3:0] IN1, IN2;
input CLK;
output  [4:0] OUT;
reg [3:0] in1_d1R, in2_d1R;
reg  [4:0] adder_out, OUT;
always@(posedge CLK) begin // 生成D触发器的always块
  in1_d1R <= IN1;
  in2_d1R <= IN2;
  OUT     <= adder_out;
  end
always@(in1_d1R or in2_d1R) begin // 生成组合逻辑的always 块
  adder_out = in1_d1R + in2_d1R;
end
endmodule 

一级流水线的延时低于无流水线的加法器。

实验八:双流水线加法器

代码:

module test11(
  IN1   ,
  IN2   ,
  CLK   ,
  OUT   ,
  SUM);
input  [7:0] IN1, IN2;
input CLK;
output OUT;
output [7:0] SUM;
reg [3:0] in1_d1R, in2_d1R,B;
reg A;
reg OUT;
reg [7:0]SUM;
always@(posedge CLK) begin // first line
  {A,B}=IN1[3:0] + IN2[3:0];
  in1_d1R = IN1[7:4];
  in2_d1R = IN2[7:4];
end

always@(posedge CLK) begin // second line
 {OUT,SUM[7:4]} =in1_d1R + in2_d1R + A;
 SUM[3:0]=B;
  
end
endmodule 

RTL图:

输出的时序图:

实验九:乘法器

输入位宽为8的乘法器输出时序图:

采用不包含硬件乘法器的FPGA芯片的资源开销,相应的8位加法器开销如下所示

 

实验十:计数器

多种信号控制计数器,其中同步清零CLR的优先级最高,使能EN次之,LOAD最低,代码如下:

 计数器代码  /

module test13(
  RST   , // 异步复位, 高有效
  CLK   , // 时钟,上升沿有效
  EN    , // 输入的计数使能,高有效
  CLR   , // 输入的清零信号,高有效
  LOAD  , // 输入的数据加载使能信号,高有效
  DATA  , // 输入的加载数据信号
  CNTVAL, // 输出的计数值信号
  OV    );// 计数溢出信号,计数值为最大值时该信号为1

input RST   , CLK   , EN    , CLR   , LOAD  ;
input [3:0] DATA ;
output [3:0] CNTVAL;
output OV;   

reg [3:0] CNTVAL, cnt_next;
reg OV;
// 电路编译参数,最大计数值
parameter CNT_MAX_VAL = 9;

// 组合逻辑,生成cnt_next
// 计数使能最优先,清零第二优先,加载第三优先
always @(EN or CLR or LOAD or DATA or CNTVAL) begin
  if(CLR) begin    //  清零有效
  cnt_next = 0;
  end
  else begin  //qingling wuxiao
    if(EN) begin //  使能有效  
         // 使能有效,清零和加载都无效,根据当前计数值计算下一值
        if(CNTVAL < CNT_MAX_VAL) begin // 未计数到最大值, 下一值加1
          cnt_next = CNTVAL + 1'b1;
        end
        else begin // 计数到最大值,下一计数值为0
          cnt_next = 0;
		end
	end
    else begin
          if(LOAD) begin // 加载有效
			cnt_next = DATA;
		  end
		  else begin     // 加载无效,正常计数
            cnt_next = CNTVAL;
          end
    end  // else EN
  
  
  end // if clr

end
// 时序逻辑 更新下一时钟周期的计数值
// CNTVAL 会被编译为D触发器
always @ (posedge CLK or posedge RST) begin
  if(RST) 
    CNTVAL <= 0;
  else
    CNTVAL <= cnt_next;
end

// 组合逻辑,生成OV
always @ (CNTVAL) begin
  if(CNTVAL == CNT_MAX_VAL) 
    OV = 1;
  else
    OV = 0;
end

endmodule
///

产生的波形图如下图所示:

实验十一:状态机

代码:

  三段式状态机代码  /
module test10(
  CLK       ,   // clock
  RST       ,   // reset
  CENT1IN   ,   // input 1 shuju
  TINOUT    ,
  EN);  // output 1 

input  CLK       ; 
input  RST       ; 
input  CENT1IN   ; 
input  EN        ;
output TINOUT    ;

parameter ST_0_CENT = 0;
parameter ST_1_CENT = 1;
parameter ST_2_CENT = 2;
parameter ST_3_CENT = 3;
parameter ST_4_CENT = 4;

reg [2:0]stateR       ;
reg [2:0]next_state   ;
reg        TINOUT       ;

// calc next state
always @ (CENT1IN or stateR or EN) begin

  case (stateR)
    ST_0_CENT :begin if(CENT1IN && EN) next_state = ST_1_CENT ; else next_state = ST_0_CENT; end
    ST_1_CENT :begin if(CENT1IN && EN) next_state = ST_0_CENT ; else next_state = ST_2_CENT; end
    ST_2_CENT :begin if(CENT1IN && EN) next_state = ST_3_CENT ; else next_state = ST_0_CENT; end
    ST_3_CENT :begin if(CENT1IN && EN) next_state = ST_4_CENT ; else next_state = ST_2_CENT; end
    ST_4_CENT :begin next_state = ST_0_CENT; end
  endcase

end

// calc output
always @ (stateR) begin
  if(stateR == ST_4_CENT) 
    TINOUT = 1'b1;
  else 
    TINOUT = 1'b0;
end

// state DFF
always @ (posedge CLK or posedge RST)begin
  if(RST)
    stateR <= ST_0_CENT;
  else
    stateR <= next_state;
end

endmodule
//

生成的状态图:

实验十二:并串转换器

代码:


module test30 (
	    pdin,
	    sdout,
	    en,
		 width_sw,
 
	    clk,
	    rstn
	    );
 
   input	[7:0]	pdin;		// 
   output		sdout;
   input		en;
	input		width_sw;
 
   input		clk;
   input		rstn;
 
   
 
   reg [6:0] 		tmp;		// 
   reg sdout;
 
   always @ ( posedge clk or negedge rstn )
     if ( !rstn )
       {tmp, sdout} <= 0;
     else 
		if ( en )		// start p2s
			{tmp, sdout} <= pdin;
		else	
			begin
				if( width_sw )
					{tmp, sdout} <= {1'b0, tmp};
				else
					{tmp[4:0], sdout} <= {1'b0, tmp[4:0]};
			end
         
   
 
endmodule 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

daijingxin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值