我来抛块砖引个玉~
说说我的理解~
FPGA和C语言什么的是不一样的,他的程序是HDL语言,即VHDL或者Verilog HDL,这些语言有个名字:硬件描述语言。既然是硬件描述,那就是说只是描述某种状态,要注意描述状态这些词汇,就是说他是搭建一个硬件的固定的系统,一旦用语言描述好了以后,这个系统就固定了。
首先FPGA有两种逻辑:组合逻辑和时序逻辑。
组合逻辑:描述一个状态,比如c:=a+b ,d:=c+‘1’那么在硬件电路上,这就是个固定的通道,c在任何时刻都等于a+b,而d在任何时刻都等于c+‘1’,也就是说,d在任何时刻都等于a+b+‘1’(如果不考虑门级延时的话),a、b值改变时,c、d的值会同时改变,而C语言里就不一样,如果是以上两个语句的话,在第一句之间和第二句之间若设断点,则a、b改变时,d不会立刻发生变化,只有在执行完第二句后,d才会发生变化。
时序逻辑:这个是写在进程process(对VHDL)或者always(对verilog)里面的,会一级一级的靠时钟来触发,在进程中的if-else分支语句,其实就是出发的条件
楼主追问的那个问题,调用模块,其实也是在程序中并行的,就是说模块被调用了,就相当于写在这个程序里的并行语句,调用它的模块是一起一直在运作,之所以用运作就是想说明这些模块没有先后顺序,他们都是用来描述你要实现的功能的,只是对硬件的描述,映射到硬件上就是一堆寄存器和与非门和线而已。用FPGA的时候要经常联想下硬件怎么实现的,这样就会明白所谓的“执行顺序”。其实严格来说,FPGA应该没有“执行顺序”这个词,他只是对硬件的一个描述而已。
举个例子,就像你设置一个物理的陷阱,你要实现的功能是,人推门,夹在门上的水桶掉落,然后再砸到跷跷板上,这个过程,你的设置就相当于硬件语言描述,人推门可以理解为时序逻辑,相当于需要触发条件的并行逻辑,你检测门是否被推开,和是否有重物砸向跷跷板是一直在进行的,只是在某一刻这些条件才被触发,所以在你看来好像是顺序执行的,但实际上是一直并行的。
说了这些,仅供参考。。
always(@posedge sclk)
begin
if(rst)
begin
pulse_cnt<=1'b0; //用于记输出的脉冲数
pulse_out<=1'b0; //通过管脚输出脉冲
end
else if(pulse_cnt[N-1:0] == {rec_data[N : 1],1'b0})//rec_data是用串口接收到的需要输出的脉冲数
begin
pulse_cnt<=pulse_cnt+1'b1;
pulse_out<=!pulse_out;
end
else
begin
pulse_cnt<=1'b0;
pulse_out<=1'b0;
end
end
N是rec_data的位数+1
(1)先做一个消抖,存到文件debouncevhd
library IEEE;
use IEEEstd_logic_1164all;
use IEEEstd_logic_arithall;
use IEEEstd_logic_unsignedall;
entity debounce is
generic (
CLK_FREQ_MHz : integer := 20; --in MHz
BUTTON_PRESS_STATUS : std_logic := '0'
);
port (
reset_n : in std_logic;
clk : in std_logic;
btnIn : in std_logic;
btnPressed : out std_logic
);
end debounce;
architecture debounce_arch of debounce is
constant MAX_MS_CNT : integer := CLK_FREQ_MHz 1000 - 1;
signal msCnt : integer range 0 to MAX_MS_CNT;
signal msClk : std_logic; --做一个毫秒脉冲,每1毫秒对按钮采样一次
signal btnIn_q : std_logic_vector(9 downto 0); --记住最后10次采样
signal btn : std_logic;
signal btn_q : std_logic;
begin
--产生毫秒脉冲
process(reset_n, clk)
begin
if reset_n = '0' then
msCnt <= 0;
msClk <= '0';
elsif rising_edge(clk) then
if msCnt >= MAX_MS_CNT then
msCnt <= 0;
msClk <= '1';
else
msCnt <= msCnt + 1;
msClk <= '0';
end if;
end if;
end process;
--记住最后10次采样
process(reset_n, clk)
begin
if reset_n = '0' then
btnIn_q <= (others => not BUTTON_PRESS_STATUS);
elsif rising_edge(clk) then
if msClk = '1' then
btnIn_q <= btnIn_q(btnIn_q'left-1 downto 0) & btnIn;
else
btnIn_q <= btnIn_q;
end if;
end if;
end process;
process(reset_n, clk)
variable all_samples_are_pressed : std_logic_vector(btnIn_q'left downto 0) := (others => BUTTON_PRESS_STATUS);
begin
if reset_n = '0' then
btn <= '0';
btn_q <= '0';
elsif rising_edge(clk) then
if btnIn_q = all_samples_are_pressed then
btn <= '1'; --最后10次采样都是按下状态,就确认按钮按下(10ms消抖)
elsif btnIn_q = not all_samples_are_pressed then
btn <= '0'; --最后10次采样都是抬起状态,就确认按钮抬起(10ms消抖)
else
btn <= btn; --否则保持不变
end if;
btn_q <= btn;
end if;
end process;
btnPressed <= '1' when btn = '1' and btn_q = '0' else '0'; --按钮按下上升沿检测
end debounce_arch;
(2)做一个加法器,存到文件addervhd
library IEEE;
use IEEEstd_logic_1164all;
use IEEEstd_logic_arithall;
use IEEEstd_logic_unsignedall;
entity adder is
port (
reset_n : in std_logic;
clk : in std_logic;
adderEn : in std_logic;
data : out std_logic_vector(3 downto 0);
dataValid : out std_logic
);
end adder;
architecture adder_arch of adder is
signal cnt : std_logic_vector(3 downto 0);
begin
process(reset_n, clk)
begin
if reset_n = '0' then
cnt <= x"0";
dataValid <= '0';
elsif rising_edge(clk) then
if adderEn = '1' then --将被替换成,按钮按下时,计数+1
if cnt >= x"9" then
cnt <= x"0";
else
cnt <= cnt + 1;
end if;
dataValid <= '1';
else
cnt <= cnt;
dataValid <= '0';
end if;
end if;
end process;
data <= cnt;
end adder_arch;
(3)做7段数码管显示,存到文件SevenSegmentvhd
library IEEE;
use IEEEstd_logic_1164all;
use IEEEstd_logic_arithall;
use IEEEstd_logic_unsignedall;
entity SevenSegment is
generic (
LED_ON : std_logic := '0'
);
port (
reset_n : in std_logic;
clk : in std_logic;
data : in std_logic_vector(3 downto 0);
dataValid : in std_logic;
ledOut : out std_logic_vector(6 downto 0)
);
end SevenSegment;
architecture SevenSegment_arch of SevenSegment is
constant LED_OFF : std_logic := not LED_ON;
signal led : std_logic_vector(6 downto 0);
begin
-- --a--
-- |f |b
-- --g--
-- |e |c
-- --d--
process(reset_n, clk)
begin
if reset_n = '0' then
led <= LED_ON & LED_ON & LED_ON & LED_ON & LED_ON & LED_ON &LED_OFF; --display 0
elsif rising_edge(clk) then
if dataValid = '1' then
case data is --a b c d e f g
when x"0" =>
led <= LED_ON & LED_ON & LED_ON & LED_ON & LED_ON & LED_ON & LED_OFF; --display 0
when x"1" =>
led <= LED_OFF & LED_ON & LED_ON & LED_OFF & LED_OFF & LED_OFF & LED_OFF; --display 1
when x"2" =>
led <= LED_ON & LED_ON & LED_OFF & LED_ON & LED_ON & LED_OFF & LED_ON ; --display 2
when x"3" =>
led <= LED_ON & LED_ON & LED_ON & LED_ON & LED_OFF & LED_OFF & LED_ON ; --display 3
when x"4" =>
led <= LED_OFF & LED_ON & LED_ON & LED_OFF & LED_OFF & LED_ON & LED_ON ; --display 4
when x"5" =>
led <= LED_ON & LED_OFF & LED_ON & LED_ON & LED_OFF & LED_ON & LED_ON ; --display 5
when x"6" =>
led <= LED_ON & LED_OFF & LED_ON & LED_ON & LED_ON & LED_ON & LED_ON ; --display 6
when x"7" =>
led <= LED_ON & LED_ON & LED_ON & LED_OFF & LED_OFF & LED_OFF & LED_OFF; --display 7
when x"8" =>
led <= LED_ON & LED_ON & LED_ON & LED_ON & LED_ON & LED_ON & LED_ON ; --display 8
when x"9" =>
led <= LED_ON & LED_ON & LED_ON & LED_ON & LED_OFF & LED_ON & LED_ON ; --display 9
when others =>
led <= (others => LED_OFF);
end case;
else
led <= led;
end if;
end if;
end process;
ledOut <= led;
end SevenSegment_arch;
(4)最后,综合到一起,存到文件topvhd
library IEEE;
use IEEEstd_logic_1164all;
use IEEEstd_logic_arithall;
use IEEEstd_logic_unsignedall;
entity top is
generic (
CLK_FREQ_MHz : integer := 20; --可以修改成你的系统时钟频率,以MHz为单位
BUTTON_PRESS_STATUS : std_logic := '0'; --指定按钮按下时,是逻辑0还是1
LED_ON : std_logic := '0' --指定数码管点亮需要输出0还是1
);
port (
reset_n : in std_logic;
clk : in std_logic;
btnIn : in std_logic;
ledOut : out std_logic_vector(6 downto 0)
);
end top;
architecture top_arch of top is
component debounce
generic (
CLK_FREQ_MHz : integer := 20; --in MHz
BUTTON_PRESS_STATUS : std_logic := '0'
);
port (
reset_n : in std_logic;
clk : in std_logic;
btnIn : in std_logic;
btnPressed : out std_logic
);
end component;
component adder
port (
reset_n : in std_logic;
clk : in std_logic;
adderEn : in std_logic;
data : out std_logic_vector(3 downto 0);
dataValid : out std_logic
);
end component;
component SevenSegment
generic (
LED_ON : std_logic := '0'
);
port (
reset_n : in std_logic;
clk : in std_logic;
data : in std_logic_vector(3 downto 0);
dataValid : in std_logic;
ledOut : out std_logic_vector(6 downto 0)
);
end component;
signal btnPressed : std_logic;
signal data : std_logic_vector(3 downto 0);
signal dataValid : std_logic;
begin
debounce_inst : debounce
generic map (
CLK_FREQ_MHz => CLK_FREQ_MHz, --in MHz
BUTTON_PRESS_STATUS => BUTTON_PRESS_STATUS
)
port map(
reset_n => reset_n,
clk => clk,
btnIn => btnIn,
btnPressed => btnPressed
);
addr_inst : adder
port map (
reset_n => reset_n,
clk => clk,
adderEn => btnPressed,
data => data,
dataValid => dataValid
);
SevenSegment_inst : SevenSegment
generic map (
LED_ON => LED_ON
)
port map (
reset_n => reset_n,
clk => clk,
data => data,
dataValid => dataValid,
ledOut => ledOut
);
end top_arch;
(5)你只要修改topvhd里generic的定义,设定时钟频率、按钮按下状态和数码管点亮状态即可
以上就是关于FPGA程序执行问题全部的内容,包括:FPGA程序执行问题、FPGA编程请教: 编程语言用的VerilogHDL 功能流程描述:用FPGA编的串口,串口接收到数据后,转成脉冲输出、急!vhdl编写fpga程序!10小时内需要!等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)