FPGA入门实验

实验一 用一个拨码开关控制所有的LED灯亮灭

这里写图片描述

这里写图片描述

这里写图片描述

实验二

2—1 放置2个2-4译码器模块,则总共有2组SW, 每组2个,2组LED,每组4个,每组SW分别控 制其对应的LED组。

module dec_2to4(
IN  ,
OUT);
input  [2-1:0] IN  ;
output [4-1:0] OUT ;

reg [4-1:0] OUT ;

always @ (IN) begin
  case(IN)
    2'b00: OUT = 4'b 0001;
    2'b01: OUT = 4'b 0010;
    2'b10: OUT = 4'b 0100;
    2'b11: OUT = 4'b 1000;
  endcase
end

endmodule // module dec_2to4;

这里写图片描述

这里写图片描述

2-2 设计一个3-8译码器

module dec_3to8;
   output [8-1:0] out;
   input [3-1:0] in;
   reg [8-1:0] out;
   always @(in)
   begin
     case(in)
     3'd0:  out=8'b00000001;
     3'd1:  out=8'b00000010;
     3'd2:  out=8'b00000100;
     3'd3:  out=8'b00001000;
     3'd4:  out=8'b00010000;
     3'd5:  out=8'b00100000;
     3'd6:  out=8'b01000000;
     3'd7:  out=8'b10000000;
     endcase
   end
 endmodule

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

2-3 用4个拨码开关控制一个7段译码器的数字,从 0-9-A-F,共16个数字和字母

module yimaqi(out,in);
   output [16-1:0] out;
   input [4-1:0] in;
   reg [16-1:0] out;
   always @(in)
   begin
     case(in)
     4'd0:  out=16'b1111111111000000;
     4'd1:  out=16'b1111111111111001;
     4'd2:  out=16'b1111111110100100;
     4'd3:  out=16'b1111111110110000;
     4'd4:  out=16'b1111111110011001;
     4'd5:  out=16'b1111111110010010;
     4'd6:  out=16'b1111111110000010;
     4'd7:  out=16'b1111111111111000;
     4'd8:  out=16'b1111111110000000;
     4'd9:  out=16'b1111111110010000;
     4'd10: out=16'b1111111110001000;
     4'd11: out=16'b1111111110000011;
     4'd12: out=16'b1111111111000110;
     4'd13: out=16'b1111111110100001;
     4'd14: out=16'b1111111110000110;
     4'd15: out=16'b1111111110001110;
     endcase
   end
 endmodule

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

实验三

3-1设计一个0-17的计数器,当计数值为17的时,OV输出1,其他输出0

module cnt_0to17(
  CLK   ,   // clock
  CNTVAL,   // counter value
  OV    );  // overflow 
input CLK;
output [6-1:0] CNTVAL;
output OV;

reg [6-1:0] CNTVAL;
reg OV;

always @ (posedge CLK) begin
  if(CNTVAL >= 17)
    CNTVAL <= 0;
  else
    CNTVAL <= CNTVAL + 1'b1;
end

always @ (CNTVAL) begin
  if(CNTVAL == 17)
    OV = 1'b1;
  else
    OV = 1'b0;
end

endmodule   // module cnt_0to17

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

3-2 设计一个0-17的计数器,当计数值为0-8时,OV输出0;当计数值为9-17时,OV输出1

module cnt_0to17(
  CLK   ,   // clock
  CNTVAL,   // counter value
  OV    );  // overflow 
input CLK;
output [6-1:0] CNTVAL;
output OV;

reg [6-1:0] CNTVAL;
reg OV;

always @ (posedge CLK) begin
  if(CNTVAL >= 17)
    CNTVAL <= 0;
  else
    CNTVAL <= CNTVAL + 1'b1;
end

always @ (CNTVAL) begin
  if(CNTVAL > 8)
    OV = 1'b1;
  else
    OV = 1'b0;
end

endmodule   // module cnt_0to17

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

实验四 时间基准电路 和 带使能的多周期计数器

本质上是一个两级计数器级联的的电路结构 – 第一级计数器生成时间基准信号 – 第二级计数器用时间基准信号作为计数使能
4-1 将后级计数器的计数范围改为0-15

module cnt_sync(
  CLK   ,   // clock
  CNTVAL,   // counter value
  OV    );  // overflow
input CLK;
output [32-1:0] CNTVAL;
output OV;
parameter MAX_VAL = 25_000_000;
reg [32-1:0] CNTVAL;
reg OV;

always @ (posedge CLK) begin
  if(CNTVAL >= MAX_VAL)
    CNTVAL <= 0;
  else
    CNTVAL <= CNTVAL + 1'b1;
end

always @ (CNTVAL) begin
  if(CNTVAL == MAX_VAL)
    OV = 1'b1;
  else
    OV = 1'b0;
end

endmodule   // module cnt_en_0to9


module cnt_en_0to15(
  CLK   ,   // clock
  CNTVAL,   // counter value
  EN    ,
  OV    );  // overflow
input CLK;
input EN;
output [4-1:0] CNTVAL;
output OV;

reg [4-1:0] CNTVAL;
reg OV;

always @ (posedge CLK) begin
  if(EN) begin  // work enable
    if(CNTVAL >= 15)
      CNTVAL <= 0;
    else
      CNTVAL <= CNTVAL + 1'b1;
  end
  else
    CNTVAL <= CNTVAL ;  // hold same value
end

always @ (CNTVAL) begin
  if(CNTVAL == 15)
    OV = 1'b1;
  else
    OV = 1'b0;
end

endmodule   // module cnt_en_0to15

这里写图片描述

这里写图片描述

4-2 后级计数器的计数范围为0-15,然后经过译码,在DE0 的HEXLED上显示成0-9-A-F的十六进制数

module cnt_sync(
  CLK   ,   // clock
  CNTVAL,   // counter value
  OV    );  // overflow
input CLK;
output [32-1:0] CNTVAL;
output OV;
parameter MAX_VAL = 25_000_000;
reg [32-1:0] CNTVAL;
reg OV;

always @ (posedge CLK) begin
  if(CNTVAL >= MAX_VAL)
    CNTVAL <= 0;
  else
    CNTVAL <= CNTVAL + 1'b1;
end

always @ (CNTVAL) begin
  if(CNTVAL == MAX_VAL)
    OV = 1'b1;
  else
    OV = 1'b0;
end

endmodule   // module cnt_en_0to9


module cnt_en_0to15(
  CLK   ,   // clock
  CNTVAL,   // counter value
  EN    ,
  OV    );  // overflow
input CLK;
input EN;
output [4-1:0] CNTVAL;
output OV;

reg [4-1:0] CNTVAL;
reg OV;

always @ (posedge CLK) begin
  if(EN) begin  // work enable
    if(CNTVAL >= 15)
      CNTVAL <= 0;
    else
      CNTVAL <= CNTVAL + 1'b1;
  end
  else
    CNTVAL <= CNTVAL ;  // hold same value
end

always @ (CNTVAL) begin
  if(CNTVAL == 15)
    OV = 1'b1;
  else
    OV = 1'b0;
end

endmodule   // module cnt_en_0to15

module dec4_16(out,in);
   output [16-1:0] out;
   input [4-1:0] in;
   reg [16-1:0] out;
   always @(in)
   begin
     case(in)
     4'd0:  out=16'b1111111111000000;
     4'd1:  out=16'b1111111111111001;
     4'd2:  out=16'b1111111110100100;
     4'd3:  out=16'b1111111110110000;
     4'd4:  out=16'b1111111110011001;
     4'd5:  out=16'b1111111110010010;
     4'd6:  out=16'b1111111110000010;
     4'd7:  out=16'b1111111111111000;
     4'd8:  out=16'b1111111110000000;
     4'd9:  out=16'b1111111110010000;
     4'd10: out=16'b1111111110001000;
     4'd11: out=16'b1111111110000011;
     4'd12: out=16'b1111111111000110;
     4'd13: out=16'b1111111110100001;
     4'd14: out=16'b1111111110000110;
     4'd15: out=16'b1111111110001110;
     endcase
   end
 endmodule

这里写图片描述

这里写图片描述

这里写图片描述

4-3 修改时间基准发生器,设计一个使用2个HEX LED,精度为0.1秒,范围为0-9.9秒的计时秒表

module cnt_sync(
  CLK   ,   // clock
  CNTVAL,   // counter value
  OV    );  // overflow
input CLK;
output [32-1:0] CNTVAL;
output OV;
parameter MAX_VAL = 5_000_000;
reg [32-1:0] CNTVAL;
reg OV;

always @ (posedge CLK) begin
  if(CNTVAL >= MAX_VAL)
    CNTVAL <= 0;
  else
    CNTVAL <= CNTVAL + 1'b1;
end

always @ (CNTVAL) begin
  if(CNTVAL == MAX_VAL)
    OV = 1'b1;
  else
    OV = 1'b0;
end

endmodule   


module cnt_en_0to99(
  CLK   ,   // clock
  CNTVAL,   // counter value
  EN    ,
  OV    );  // overflow
input CLK;
input EN;
output [8-1:0] CNTVAL;
output OV;

reg [8-1:0] CNTVAL;
reg OV;

always @ (posedge CLK) begin
  if(EN) begin  // work enable
    if(CNTVAL >= 99)
      CNTVAL <= 0;
    else
      CNTVAL <= CNTVAL + 1'b1;
  end
  else
    CNTVAL <= CNTVAL ;  // hold same value
end

always @ (CNTVAL) begin
  if(CNTVAL == 99)
    OV = 1'b1;
  else
    OV = 1'b0;
end

endmodule   // module cnt_en_0to99


module dec4_16(out,in);
   output [8-1:0] out;
   input [8-1:0] in;
   reg [8-1:0] out;
   always @(in)
   begin
     case(in / 10)
     4'd0:  out=8'b01000000;
     4'd1:  out=8'b01111001;
     4'd2:  out=8'b00100100;
     4'd3:  out=8'b00110000;
     4'd4:  out=8'b00011001;
     4'd5:  out=8'b00010010;
     4'd6:  out=8'b00000010;
     4'd7:  out=8'b01111000;
     4'd8:  out=8'b00000000;
     4'd9:  out=8'b00010000;
     endcase
   end
 endmodule

module dec4_16L(outl,in);
   output [8-1:0] outl;
   input [8-1:0] in;
   reg [8-1:0] outl;
   always @(in)
   begin
     case(in % 10)
     4'd0:  outl=8'b11000000;
     4'd1:  outl=8'b11111001;
     4'd2:  outl=8'b10100100;
     4'd3:  outl=8'b10110000;
     4'd4:  outl=8'b10011001;
     4'd5:  outl=8'b10010010;
     4'd6:  outl=8'b10000010;
     4'd7:  outl=8'b11111000;
     4'd8:  outl=8'b10000000;
     4'd9:  outl=8'b10010000;
     endcase
   end
 endmodule

这里写图片描述

这里写图片描述

FPGA实验5:多周期移位寄存器

设计时间基准电路和带使能的多周期移位寄存器,
要求电路工作在50MHz,在每个时间基准信号有效的时钟周期,
–把一个拨码开关的状态值移位输入到寄存器的最低位
–顺序移动移位寄存器的值
–寄存器的每个比特送至一个LED灯上显示
–SW0仍然是移位寄存器组的输入
–使用SW1开关,控制移位寄存的方向

// 串入并出移位寄存器  
module shift_reg_SIPO(
  RST   ,   // 异步复位, 高有效
  CLK   ,   // 时钟,上升沿有效
  EN    ,   // 输入数据串行移位使能
  IN    ,   // 输入串行数据
  OUT   ,   // 并行输出数据
  CHOSS );  // 选择移位方向(左移or右移)
parameter SHLEN = 6;
input RST, CLK, EN,CHOSS;
input IN;
output[SHLEN-1:0] OUT;
reg [SHLEN-1:0] shift_R;

assign OUT[SHLEN-1:0] = shift_R[SHLEN-1:0];
// 时序逻辑 根据输入使能进行串行移位
// shift_R 会被编译为D触发器
always @ (posedge CLK or posedge RST) begin
  if(RST) 
    shift_R[SHLEN-1:0] <= 0;
  else
    if(EN&CHOSS) begin // 串行移位的使能有效(左移)
      shift_R[SHLEN-1:1] <= shift_R[SHLEN-2:0];
      shift_R[0]   <= IN;
    end

    else if(EN&CHOSS==0) begin // 串行移位的使能有效(右移)
      shift_R[SHLEN-2:0] <= shift_R[SHLEN-1:1];
      shift_R[SHLEN-1]   <= IN;
    end

    else begin // 使能无效保持不动
      shift_R[SHLEN-1:0] <= shift_R[SHLEN-1:0];
    end
end // always
endmodule

// 时间基准计数器  
module cnt_sync(
  CLK   ,   // clock
  CNTVAL,   // counter value
  OV    );  // overflow
input CLK;
output [32-1:0] CNTVAL;
output OV;
parameter MAX_VAL = 25_000_000;
reg [32-1:0] CNTVAL;
reg OV;

always @ (posedge CLK) begin
  if(CNTVAL >= MAX_VAL)
    CNTVAL <= 0;
  else
    CNTVAL <= CNTVAL + 1'b1;
end

always @ (CNTVAL) begin
  if(CNTVAL == MAX_VAL)
    OV = 1'b1;
  else
    OV = 1'b0;
end

endmodule

这里写图片描述

这里写图片描述

FPGA实验6:计数器、ROM和DDS

设计直接数字频率合成(DDS)
要求:
–用计数器生成地址、读取ROM数据
–理解二进制补码和无符号数
–修改计数增量值,观察波形变化,思考输出频率和计数器增量值的关系。

1、代码片段

这里写图片描述

这里写图片描述

2、原理图

这里写图片描述

3、RTL图

这里写图片描述

计数器模块内部电路结构:

这里写图片描述

ROM内部电路结构:

这里写图片描述

【思考】:如果加法器溢出了,输出结果会怎样?
【答】:当相位累加器的溢出时,—个完整的阶梯正弦信号就从ROM查询表的输出端输出。因此,相位累加器的溢出率就是正弦波信号的输出频率。

4、不同的计数增量值对应的波形

(1)计数增量为1时,正弦波频率约0.39 MHZ
这里写图片描述

(2)计数增量为2时,正弦波频率约0.78 MHZ
这里写图片描述

(3)计数增量为4时,正弦波频率1.5625 MHZ
这里写图片描述

【问题一】拨动开关,观察不同频率的正弦波, 电路的工作时钟是50MHz
(1) 请回答,你能得到的正弦波频率和计数器增量值的对应关系是什么?
(2)请回答,你能得到的最低频率的正弦波是多少?设该频率为f1
(3)请思考,能否有什么方法能够得到比f1频率还低的正弦波
【答】:
(1)正弦波频率和计数器增量值成 线性关系。
(2)正弦波的最低频率f1约0.39 MHZ。
(3)增加计数器增量或减小计数器数据位宽。

【问题二】输出信号频率 和 电路工作时钟频率,计数器增量值,以及计数器数据位宽之间的表达式关系?
【答】:
这里写图片描述

学生实验:

设计直接数字频率合成(DDS)
要求:
–把计数增量输入信号分配到10个拨码开关上
–把计数值信号的高7位分配为ROM的地址,低3位悬空不使用。
–编译、下载电路,拨动拨码开关,观察最低频率有什么变化。

1、代码改动部分
这里写图片描述

2、原理图
这里写图片描述

3、不同的计数增量值对应的波形

(1)计数增量为1时,正弦波频率约0.0488 MHZ
这里写图片描述

(2)计数增量为2时,正弦波频率约0.0976 MHZ
这里写图片描述

(3)计数增量为4时,正弦波频率约0.1953 MHZ
这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值