1、顶层思维
例子1:RS232的顶层模块
设计一个实验工程的时候,最首要的就是顶层模块,自上而下的进行设计。
比如从该RS232的顶层模块中可以得出,里面一个包含两个子功能模块,分别是uart_rx和uart_tx模块。这两个模块与顶层模块的关系由外部的线连出,而模块间的联系则是在内部进行相连。
在写代码的时候也可以直接先把顶层模块的代码写好如下:
module top_rs232(
input wire sys_clk ,
input wire sys_rst_n ,
input wire rx ,
output wire tx
);
parameter uart_bps = 14'd9600;
parameter clk_freq = 26'd50_000_000;
wire [7:0] po_data;
wire po_flag;
uart_rx
#(
.uart_bps(uart_bps),
.clk_freq(clk_freq)
)
uart_rx_inst
(
.sys_clk (sys_clk) ,
.sys_rst_n (sys_rst_n) ,
.rx (rx) ,
.po_data (po_data) ,
.po_flag (po_flag)
);
uart_tx
#(
.uart_bps(uart_bps),
.clk_freq(clk_freq)
)
uart_tx_inst1
(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.pi_data (po_data),
.pi_data_flag (po_flag),
.tx (tx)
);
endmodule
其它关于子功能模块的代码则可以进一步根据波形图进行编写,具体看链接http://t.csdn.cn/kVNGF
例子2:VGA显示的顶层模块
该模块包含了3个子功能模块,同样可以运用例子1中的方法,直接写出顶层模块的代码,然后再进一步细分,画出各个子功能模块的波形图,根据波形图编写代码。
如画出Vga_ctrl的波形图如下:
关于根据波形图编写代码的一些个人理解:
第一、首先画出输入输出变量,根据不同的颜色标明。
第二、输入与输出信号的关系,思考如何通过输入信号的数据,得出输出信号的数据?
第三、思考为了得到输出信号的波形,需要使用哪些中间变量达到?FPGA中最常见的中间变量就是计数器、寄存器以及标志信号了。思考该如何充分的利用他们以连接输入信号与输出信号。
2、算法思维
例子1:HDMI的显示
在HDMI的显示中,需要一个编码模块将一个8bit的数据,转化位10bit的数据。即这个模块的输入就是一个8bit的数据,输出就是一个10bit的数据,中间过程不能任由自己随便定义,中间过程是官方文档给出的一个流程图,既是一种协议、也是一种算法。
例子2:DDS信号发生器
就单纯的正弦波、三角波、锯齿波、方波的发生是非常简单的,只需要提前将输出存在ROM或者RAM中,然后输入顺序的地址到ROM或者RAM中,数据就会输出,然后以模拟信号的形式显示,就可以显示正弦波、三角波、锯齿波以及方波等。
但是如果想要实现这四种波形的选择,并且实现各个波形频率相位的调整就需要使用到FPGA内部的资源,定义很多变量,这些变量连接这输入以及输出之间的关系,其本质上也是一种算法,该算法用流程图表示如下:
图中所展示的四大结构中,相位累加器是整个 DDS 的核心,在这里完成相位累加,生成相位码。相位累加器的输入为频率字输入 K,表示相位增量,设其位宽为 N,满足等式K = 2^N * fOUT / fCLK 。其在输入相位累加器之前,在系统时钟同步下做数据寄存,数据改变时不会干扰相位累加器的正常工作。
通过改变频率字输入和相位字输入实现输出波形频率和相位的调节。
其它例子:如FIFO求和实验、Sobel算法等,也是利用的一种算法思维