当前位置:   article > 正文

FPGA开发中SRL16E的使用_srl16e使用

srl16e使用

FPGA开发过程中是免不了要用到移位寄存器的,传统的移位寄存器是通过寄存器(或者叫触发器FF)实现的,占用的是FPGA内部的逻辑资源,当要移位的次数过多时,自然会耗费更多FF资源。

但是如果用LUT(look up table)查找表实现的话就很轻松了,LUT是通过提前存储下一张真值表来实现逻辑运算的,所以非常节省逻辑资源。常用的移位寄存器SRL种类很多,这里以16bit的SRL16E为例,说一说怎么使用它。

Xilinx SRL16E的源码如下,这个代码在安装vivado之后,都会默认自带,我的代码路径如下C:\Xilinx\Vivado\2018.3\data\verilog\src\unisims。此处推荐一个全盘快速搜索工具everything,谁用谁知道。

 

  1. ///
  2. // Copyright (c) 1995/2016 Xilinx, Inc.
  3. // All Right Reserved.
  4. ///
  5. // ____ ____
  6. // / /\/ /
  7. // /___/ \ / Vendor : Xilinx
  8. // \ \ \/ Version : 2017.1
  9. // \ \ Description : Xilinx Unified Simulation Library Component
  10. // / / 16-Bit Shift Register Look-Up-Table with Clock Enable
  11. // /___/ /\ Filename : SRL16E.v
  12. // \ \ / \
  13. // \___\/\___\
  14. //
  15. ///
  16. // Revision
  17. // 03/23/04 - Initial version.
  18. // 03/11/05 - Add LOC paramter;
  19. // 05/07/08 - 468872 - Add negative setup/hold support
  20. // 12/13/11 - 524859 - Added `celldefine and `endcelldefine
  21. // 04/16/13 - 683925 - add invertible pin support.
  22. // End Revision
  23. ///
  24. `timescale 1 ps/1 ps
  25. `celldefine
  26. module SRL16E #(
  27. `ifdef XIL_TIMING
  28. parameter LOC = "UNPLACED",
  29. `endif
  30. parameter [15:0] INIT = 16'h0000,
  31. parameter [0:0] IS_CLK_INVERTED = 1'b0
  32. )(
  33. output Q,
  34. input A0,
  35. input A1,
  36. input A2,
  37. input A3,
  38. input CE,
  39. input CLK,
  40. input D
  41. );
  42. `ifdef XIL_TIMING
  43. wire CE_dly;
  44. wire CLK_dly;
  45. wire D_dly;
  46. `endif
  47. reg [15:0] data = INIT;
  48. reg first_time = 1'b1;
  49. initial
  50. begin
  51. assign data = INIT;
  52. first_time <= #100000 1'b0;
  53. `ifdef XIL_TIMING
  54. while ((((CLK_dly !== 1'b0) && (IS_CLK_INVERTED == 1'b0)) ||
  55. ((CLK_dly !== 1'b1) && (IS_CLK_INVERTED == 1'b1))) &&
  56. (first_time == 1'b1)) #1000;
  57. `else
  58. while ((((CLK !== 1'b0) && (IS_CLK_INVERTED == 1'b0)) ||
  59. ((CLK !== 1'b1) && (IS_CLK_INVERTED == 1'b1))) &&
  60. (first_time == 1'b1)) #1000;
  61. `endif
  62. deassign data;
  63. end
  64. `ifdef XIL_TIMING
  65. generate
  66. if (IS_CLK_INVERTED == 1'b0) begin : generate_block1
  67. always @(posedge CLK_dly) begin
  68. if (CE_dly == 1'b1) begin
  69. data[15:0] <= {data[14:0], D_dly};
  70. end
  71. end
  72. end else begin : generate_block1
  73. always @(negedge CLK_dly) begin
  74. if (CE_dly == 1'b1) begin
  75. data[15:0] <= {data[14:0], D_dly};
  76. end
  77. end
  78. end
  79. endgenerate
  80. `else
  81. generate
  82. if (IS_CLK_INVERTED == 1'b0) begin : generate_block1
  83. always @(posedge CLK) begin
  84. if (CE == 1'b1) begin
  85. data[15:0] <= {data[14:0], D};
  86. end
  87. end
  88. end else begin : generate_block1
  89. always @(negedge CLK) begin
  90. if (CE == 1'b1) begin
  91. data[15:0] <= {data[14:0], D};
  92. end
  93. end
  94. end
  95. endgenerate
  96. `endif
  97. assign Q = data[{A3, A2, A1, A0}];
  98. `ifdef XIL_TIMING
  99. reg notifier;
  100. wire sh_clk_en_p;
  101. wire sh_clk_en_n;
  102. wire sh_ce_clk_en_p;
  103. wire sh_ce_clk_en_n;
  104. always @(notifier)
  105. data[0] = 1'bx;
  106. assign sh_clk_en_p = ~IS_CLK_INVERTED;
  107. assign sh_clk_en_n = IS_CLK_INVERTED;
  108. assign sh_ce_clk_en_p = CE && ~IS_CLK_INVERTED;
  109. assign sh_ce_clk_en_n = CE && IS_CLK_INVERTED;
  110. `endif
  111. specify
  112. (A0 => Q) = (0:0:0, 0:0:0);
  113. (A1 => Q) = (0:0:0, 0:0:0);
  114. (A2 => Q) = (0:0:0, 0:0:0);
  115. (A3 => Q) = (0:0:0, 0:0:0);
  116. (CLK => Q) = (100:100:100, 100:100:100);
  117. `ifdef XIL_TIMING
  118. $period (negedge CLK, 0:0:0, notifier);
  119. $period (posedge CLK, 0:0:0, notifier);
  120. $setuphold (negedge CLK, negedge CE, 0:0:0, 0:0:0, notifier,sh_clk_en_n,sh_clk_en_n,CLK_dly,CE_dly);
  121. $setuphold (negedge CLK, negedge D, 0:0:0, 0:0:0, notifier,sh_ce_clk_en_n,sh_ce_clk_en_n,CLK_dly,D_dly);
  122. $setuphold (negedge CLK, posedge CE, 0:0:0, 0:0:0, notifier,sh_clk_en_n,sh_clk_en_n,CLK_dly,CE_dly);
  123. $setuphold (negedge CLK, posedge D, 0:0:0, 0:0:0, notifier,sh_ce_clk_en_n,sh_ce_clk_en_n,CLK_dly,D_dly);
  124. $setuphold (posedge CLK, negedge CE, 0:0:0, 0:0:0, notifier,sh_clk_en_p,sh_clk_en_p,CLK_dly,CE_dly);
  125. $setuphold (posedge CLK, negedge D, 0:0:0, 0:0:0, notifier,sh_ce_clk_en_p,sh_ce_clk_en_p,CLK_dly,D_dly);
  126. $setuphold (posedge CLK, posedge CE, 0:0:0, 0:0:0, notifier,sh_clk_en_p,sh_clk_en_p,CLK_dly,CE_dly);
  127. $setuphold (posedge CLK, posedge D, 0:0:0, 0:0:0, notifier,sh_ce_clk_en_p,sh_ce_clk_en_p,CLK_dly,D_dly);
  128. $width (negedge CLK, 0:0:0, 0, notifier);
  129. $width (posedge CLK, 0:0:0, 0, notifier);
  130. `endif
  131. specparam PATHPULSE$ = 0;
  132. endspecify
  133. endmodule
  134. `endcelldefine

SRL16E例化原语如下,输入是时钟CLK,使能CE,D,和四位输出位选择控制地址A3A2A1A0,输出是Q。首先要给出一个16bit的初始值,后面的移位就是按照时钟节拍对初始进行操作的,以代码为例,输入是D(0),意味着这16个周期内每个周期给序列最右边增加一个0,相应的每个周期对应的序列最左边的值也会被挤走。第0次移位得到0000000000001111,第二位是1,输出Q就是1,第一次移位得到0000000000011110,第二位是1,输出Q就是1,第二次移位得到0000000000111100,第二位是0,输出Q就是0,以此类推,输出依次是1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,输出第几位由A3A2A1A0做地址控制(第二位输出对应0001).

modelsim仿真示意图如下:

 

  1. SRL16E #(
  2. .INIT (16'h0000 ), // Initial contents of shift register
  3. .IS_CLK_INVERTED(1'b0 ) // Optional inversion for CLK
  4. )
  5. u_ca_gain(
  6. .Q (o_ca_out ), // 1-bit output: SRL Data
  7. .CE (1'b1 ), // 1-bit input: Clock enable
  8. .CLK (i_clk ), // 1-bit input: Clock
  9. .D (i_ca_in ), // 1-bit input: SRL Data
  10. // Depth Selection inputs: A0-A3 select SRL depth
  11. .A0 (1'b1 ),
  12. .A1 (1'b1 ),
  13. .A2 (1'b0 ),
  14. .A3 (1'b1 )
  15. );

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/896857
推荐阅读
相关标签
  

闽ICP备14008679号