刚开始学习FPGA和verilog语言,从单片机过来,看着并行操作的语言确实很不习惯,翻了小段时间,看到本书《FPGA那些事》,讲的还好。
verilog语言本质是并行操作的,因为有时钟节拍的驱动和模块之间的同步信号的驱动和控制,所以可以仿C的顺序操作,其实就是一个个状态机实现步奏控制,然后上层的大的状态机嵌套底层小的状态机,模块之间通过信号量(功能模块的启动信号与功能模块的完成信号进行同步)。建模的重点在于划分模块的功能与层次。
比起写成一团的单一文件方式,这种防顺序操作建模类似于写单片机程序的模块划分与软件分层思想,便于模块的维护/理解/移植。
稍作下总结,留做自己的框架。
1.1 自顶向下划分模块和接口:
模块分为:功能模块/控制模块/组织模块
1.2 仿顺序操作:
功能模块接口:clk/rst_n/start_sig(启动信号)/done_sig(完成信号)/以及其他的控制接口(数据data的输入输出接口)。
1.3.1 防顺序操作的格式:
//输入输出变量的说明
input …
output…
inout…
//参数定义
parameter T1MS = …;
//时钟发生模块
reg[15:0] count1;
always @ (posedge clk or negedge rst_n)
if(!rst_n) count1<=16’d0;
else if(count1 == T1MS)
count1<=16’d0;
else if(isCount)
count1<=count1+1’b1;
else if(!isCount)
count1<=16’d0;
//在一个时钟的基础上产生其他时钟
reg[9:0] count2;
always @ (posedge clk or negedge rst_n)
if(!rst_n) count2<=10’d0;
else if(count2 == T1S)
count2<=10’d0;
else if(count1==T1MS)
count2<=count2+1’b1;
//通过时钟产生相应的同步信号
assign SS_sig=(count==T1MS)? 1’b1:1’b0;…
//----------------------------------------------
//定义需要的中间寄存器reg或者wire变量
reg[width:0] i;//用于作为顺序操作的控制变量
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
//信号初始化操作
i<=4’d0;
isCount<=1’b0;
isDone<=1’b0;
end
else if(start_sig) //如果接收到启动信号
case(i)
4’d0:… i<=i+1;…
//每个时间点下面的变量输出变化
if(count1== ??) …
4’d1:…
…
//产生结束信号
4’d9: begin isDone<=1’b1;i<=i+1;end
4’d10:begin isDone<=1’b0;i<=4’d0;end
endcase
end
end
//如果有组合逻辑。。。
always @ (*) begin
end
//中间定义的寄存器变量赋值输出
assign Data=rData;…
assign Done_sig=isDone;
1.3.2 控制模块的建模
上层控制模块完成对下层功能模块的调度,实现起来仍然是采用防顺序操作的模式。所以这种建模有点自底而上的样子。
可以通过命令的方式对下层模块进行调度。命令可以放在FIFO里面进行顺序执行。
1.3.3 顶层模块的连接
1.3.4 模块接口
leawise_816723039 2014-5-8 13:20
用户450531 2014-5-4 11:38
用户1754706 2014-5-2 00:54
小梅哥 2014-4-30 20:28