RTL可拓展设计:VerilogHDL实现数据深度与位宽可配置的余弦函数发生器

RTL可拓展设计:VerilogHDL实现数据深度与位宽可配置的余弦函数发生器

参考资料

Github代码仓库

使用方法

文件构成

  • trigonometric_function/cos_function/cos_function_x1.v:ROM空间优化的余弦函数发生器
  • trigonometric_function/cos_function/cos_function_x4.v:LUT规模优化的余弦函数发生器
  • trigonometric_function/cos_function/Makefile:用于测试的make脚本文件
  • trigonometric_function/cos_function/testbench.sv:测试激励文件
  • trigonometric_function/cos_function/python/gen_cos_data.py:用于生成余弦函数数据的python脚本

主模块信号及其参数配置

虽然两种优化方向的余弦函数发生器的模块名稍有区别,但是参数配置、信号和信号的时序都是一样的。

// trigonometric_function/cos_function/cos_function_x1.v
module cos_function_x1 #(
    parameter DEPTH_BITWIDTH = 8,
    parameter DATA_BITWIDTH  = 8
) (
    input clk,
    input rstn,

    input      [DEPTH_BITWIDTH-1:0] pword,
    output reg [ DATA_BITWIDTH-1:0] cos
);

// trigonometric_function/cos_function/cos_function_x4.v
module cos_function_x4 #(
    parameter DEPTH_BITWIDTH = 8,
    parameter DATA_BITWIDTH  = 8
) (
    input clk,
    input rstn,

    input      [DEPTH_BITWIDTH-1:0] pword,
    output reg [ DATA_BITWIDTH-1:0] cos
);

以下是参数的相关解释:

参数备注
DEPTH_BITWIDTH余弦函数发生器地址深度
DATA_BITWIDTH输出的数据位宽

需要注意的是,这里建议DEPTH_BITWIDTHDATA_BITWIDTH相等,因为这样在经验上可以获得精度和空间利用的最高性价比。

以下是信号的相关解释:

方向位宽信号备注
输入1clk系统时钟信号
输入1rstn同步复位信号,低有效
输入DEPTH_BITWIDTHpword余弦函数相位
输入DATA_BITWIDTHcos余弦函数输出

信号时序

请添加图片描述

这个的时序很简单,pwordcos同周期。

余弦函数数据生成

利用trigonometric_function/cos_function/python/gen_cos_data.py可以生成余弦函数数据,具体用法如下:

python gen_cos_data.py 深度位宽 数据位宽

这样就会在本目录下生成cos_data_x1.datcos_data_x4.dat两个数据文件,分别对应ROM空间优化版本和LUIT资源优化版本。

设计原理

本设计主要利用了查表的原理。

LUT优化的实现(cos_function_x4)如下:

// trigonometric_function/cos_function/cos_function_x4.v
module cos_function_x4 #(
    parameter DEPTH_BITWIDTH = 8,
    parameter DATA_BITWIDTH  = 8
) (
    input clk,
    input rstn,

    input      [DEPTH_BITWIDTH-1:0] pword,
    output reg [ DATA_BITWIDTH-1:0] cos
);

  reg [DATA_BITWIDTH-1:0] cos_rom[0:2**DEPTH_BITWIDTH-1];
  initial $readmemh("./python/cos_data_x4.dat", cos_rom);

  always @(posedge clk) begin
    if (!rstn) begin
      cos <= {DATA_BITWIDTH{1'b0}};
    end else begin
      cos <= cos_rom[pword];
    end
  end

endmodule  //cos_function_x4

很简单,就是用pword为地址读取cos_rom中的数据,然后直接输出。

以下为ROM优化版本(cos_function_x1)的实现:

// trigonometric_function/cos_function/cos_function_x1.v
module cos_function_x1 #(
    parameter DEPTH_BITWIDTH = 8,
    parameter DATA_BITWIDTH  = 8
) (
    input clk,
    input rstn,

    input      [DEPTH_BITWIDTH-1:0] pword,
    output reg [ DATA_BITWIDTH-1:0] cos
);
  localparam DEPTH = 2 ** (DEPTH_BITWIDTH - 2);
  localparam DATA_MAX_VALUE = 2 ** DATA_BITWIDTH;

  reg [DATA_BITWIDTH-1:0] cos_rom[0:DEPTH-1];
  initial $readmemh("./python/cos_data_x1.dat", cos_rom);

  always @(posedge clk) begin
    if (!rstn) begin
      cos <= {DATA_BITWIDTH{1'b0}};
    end else begin
      if (pword < DEPTH) begin
        cos <= cos_rom[pword];
      end else if ((pword >= DEPTH) && (pword < 2 * DEPTH)) begin
        cos <= DATA_MAX_VALUE - cos_rom[2*DEPTH-pword-1];
      end else if ((pword >= 2 * DEPTH) && (pword < 3 * DEPTH)) begin
        cos <= DATA_MAX_VALUE - cos_rom[pword-2*DEPTH];
      end else begin
        cos <= cos_rom[4*DEPTH-pword-1];
      end

    end
  end

endmodule  //cos_function_x1

在这个实现中,利用了余弦函数单周期内的特性求解,节省了 3 4 \frac{3}{4} 43的ROM资源。

cos ⁡ \cos cos函数的一个周期为 2 π 2\pi 2π,但是在这一个周期中可以将其分解为4段(暂不考虑边界情况): ( 0 , 0.5 π ) (0,0.5\pi) (0,0.5π) ( 0.5 π , π ) (0.5\pi,\pi) (0.5π,π) ( π , 1.5 π ) (\pi,1.5\pi) (π,1.5π) ( 1.5 π , 2 π ) (1.5\pi,2\pi) (1.5π,2π),这四个区间其实都可以用同一段区间的数据生成。假设 a ∈ ( 0 , 0.5 π ) a\in(0,0.5\pi) a(0,0.5π) b ∈ ( 0.5 π , π ) b\in(0.5\pi,\pi) b(0.5π,π) c ∈ ( π , 1.5 π ) c\in(\pi,1.5\pi) c(π,1.5π) d ∈ ( 1.5 π , 2 π ) d\in(1.5\pi,2\pi) d(1.5π,2π),储存区 R R R长度为 0.5 π 0.5\pi 0.5π,输出数据 D [ a ] = R [ a ] D[a]=R[a] D[a]=R[a],则易得以下式子:

D [ b ] = 0 − R [ π − b ] D[b]=0-R[\pi-b] D[b]=0R[πb]

D [ c ] = R [ c − π ] D[c]=R[c-\pi] D[c]=R[cπ]

D [ d ] = R [ 2 π − d ] D[d]=R[2\pi-d] D[d]=R[2πd]

然后看边界情况,如果下溢出(寻址到小于0的空间)就+1,如果上溢出(寻址到大于 a a a的空间)就-1,就可以得到代码中的转换式了。

补充说明

cos_ram在具体用在某一块FPGA上的时候最好用IP进行替代,实测安路TD没有办法将这个储存区综合为ROM。使用ROM时时序基本跟用储存区是一样的,具体可以参考具体器件开发环境(如Vivado、Pango)相关IP的数据手册。

  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值