FPGA之道(63)“万能”的查表法
前言
又好几天没更新了,这就是又停止了读书的节奏,终于在毕业论文可以稍微舒缓下来的时候更新了博客,完成一个系列,读完一本书等等都是有印记的,这是很有成就感的事情。
最重要的声明来了,本文摘自于《FPGA之道》。
“万能”的查表法
查表法的应用范围非常之广,利用查表法,我们可以实现任意的组合逻辑功能,甚至可以实现任意的时序逻辑功能(详见【知己知彼篇->FPGA内部资源介绍->逻辑资源块】中关于查找表的介绍,以及【本篇->编程思路->状态机,FPGA的灵魂->状态机的实现方式->基于RAM的实现方式浅析】章节),因此,只要系统提供的存储空间(可以是FPGA内部的或外部的)足够大,查表法可以帮助我们实现任何想实现的逻辑功能,这也是为什么我们说查表法是“万能的”了。
当然了,对于FPGA设计者来说,通常我们使用查表法,都是为了解决组合逻辑方面的问题,例如,实现任意波形发生器,或者实现任意函数求解器,等等。采用查表法来实现组合逻辑的优点是——逻辑功能实现起来相对较为简单(核心技术就是数据的存储与读取而已),且整个组合逻辑的延迟也相对较小且固定(无论功能复杂还是简单,基于查找表的逻辑延迟仅取决于存储器的地址总线到数据输出总线之间的延迟);不过其缺点就是会消耗过多的系统存储空间(存储空间大小与组合逻辑的输入端口数呈二的整数次幂关系)。因此,虽然查表法是“万能”的,但是在进行FPGA项目开发时,我们不能把它当成万能膏药,到处乱贴,只有对于那些适合的情况,才应该予以考虑,从而达到出其不意的绝妙效果。那么,本章节接下来以几个示例来为大家简单的介绍一下查表法的使用。
正弦波发生器示例
现假设FPGA外部有一块DA芯片,我们要利用这块DA芯片向外界发送一路频率为1MHz的模拟正弦波。
已知FPGA内部主时钟频率为10MHz,外部DA芯片接收8bits并行数字信号并将其转换为电压值,其中数字信号取值范围为整数0255,而DA芯片会将其均匀转换到对应的模拟电压-1.51.5V之间。
在不倍频的前提下,10MHz的时钟信号就代表发送给DA芯片的数字序列采样率最高为10MHz,因此采样间隔为100ns。而1MHz的正弦波的周期为1000ns,正好1个正弦波周期可以被10MHz的采样率均匀的采上10个点。综上所述,我们可以从正弦波的一个周期中均匀的取出10个样点的值(初始相位不同,结果也会有不同,本例以0弧度作为起始相位),如下图所示:
然后对其进行放大、直流偏移、整数近似等操作,进而得出10个介于0~255之间的正弦波采样点。最后,以10MHz的频率循环发送这10个采样点给DA芯片,便可实现发送1路1MHz模拟正弦波的需求。
下述即为正弦波发生器的HDL示例:
-- VHDL example
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity SinWave is
port (
clk : in std_logic;
rst : in std_logic;
toDAClk : out std_logic;
toDAData : out std_logic_vector(7 downto 0)
);
end SinWave;
architecture Behavioral of SinWave is
type rom_type is array (9 downto 0) of std_logic_vector (7 downto 0);
signal ROM: rom_type:= (X"35", X"07", X"07", X"35", X"80",
X"CB", X"F9", X"F9", X"CB", X"80");
begin
process(clk)
begin if(clk'event and clk = '1')then if(rst = '1')then addr <= "0000"; else if(addr = "1001")then addr <= "0000"; else addr <= addr + 1; end if; end if; end if;
end process;
end Behavioral;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
// Verilog example
module SinWave(
input clk,
input rst,
output toDAClk,
output [7:0] toDAData
); reg [7:0] ROM [9:0];
reg [3:0] addr; initial begin
ROM[0] = 8'd128; ROM[1] = 8'd203; ROM[2] = 8'd249; ROM[3] = 8'd249;
ROM[4] = 8'd203; ROM[5] = 8'd128; ROM[6] = 8'd53; ROM[7] = 8'd7;
ROM[8] = 8'd7; ROM[9] = 8'd53;
end always@(posedge clk)
begin
if(rst == 1'b1)
begin addr <= 4'd0;
end
else
begin if(addr == 4'd9) begin addr <= 4'd0; end else begin addr <= addr + 1'b1; end
end
end assign toDAClk = ~ clk;
assign toDAData = ROM[addr]; endmodule
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
上例的仿真结果如下图所示:
由于实际硬件系统的带宽都是有限的,如果在DA芯片的输出端再配合使用适当的模拟滤波器,那么该系统实际所发出的模拟正弦波将会比上图更加的圆润。
文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。
原文链接:reborn.blog.csdn.net/article/details/104955374
- 点赞
- 收藏
- 关注作者
评论(0)