(FPGA编程)仿C的硬件描述语言----verilog基本语法

学习FPGA编程,学习语法是编程的第一步的,今天就侃侃硬件仿C的硬件描述语言---verilog基本语法!

1.模块化编写输入输出接口:

module cmd_ctr (//module 模块名

                         clk,rst_n,enable,

                          h2l,data_in,end_cmd);

注意: 模块名与保存文件名cmd_ctr .v必须一致,编程编一个模块除了有你需要输出管脚,输入端通常还需要添加异步复位信号rst_n,同步时钟信号clk,以及开启触发模块工作的enable信号,输出端还有模块工作完成信号end_cmd。

2.各信号类型定义:

input clk;
input rst_n;
input enable;
input h2l;
input[7:0] data_in;
output dataout;
parameter t1ms=20'd49_999;//1000000ns/20ns=50000=1024*1024
reg[19:0] count;
reg iscount;

wire clock;

input与output定义输入输出信号,parameter用于定于参数类型为常数,wire用于信号或者模块之间的连线,reg为寄存器信号,用于暂存数据,区别reg有时是不能替代wire类型的,比如用作下个模块的时钟信号。

3.简单的always编写:

always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
 rdata<=4'b0001;
end
else if(dataend)
begin
 case(datain)
  8'h1d:rdata<={rdata[2:0],rdata[3]};
  8'h22:rdata<={rdata[0],rdata[3:1]};
  8'h14:rdata<={rdata[0],rdata[1],rdata[2],rdata[3]};
  endcase
end

跟VHDL一样,verilog也是由一个一个的进程构成,只是构成的方式不同,VHDL由多个process组成,而verilog由多个always组成,而且编写的形式还是比较固定的,当然在编写时一定要有编写C语言的思维,因此一定要会用if,case语句。而且要养成每个case或者if后面一定要紧跟一个begin...........end语句,养成良好的编写习惯。

4.verilog编程两大利器之一:计数器

always @(posedge clk or negedge rst_n)
if(!rst_n)
begin 
 count<=13'd0;
end
else if(count==13'd4999)
begin
 count<=13'd0;
end
else
begin
 count<=count+1'b1;
end

assign clock=(count==13'd2499)?1'b1:1'b0;

别看着计数器是一个简单的东西,其实,这是做fpga项目人最常用到的利器,比如很多器件(如sdram)开启时启动时间需要200us的开启时间,那么这是时间怎么来,当然是计数器完成,所以计数必定是fpga编程的利器。

5.verilog编程两大利器之二:状态机

//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器

always @ (posedge clk or negedge rst_n) //异步复位

if(!rst_n)

current_state <= IDLE;

else

current_state <= next_state; 

//第二个进程,组合逻辑always模块,描述状态转移条件判断

always @ (current_state)  begin //电平触发

next_state = x; //要初始化,使得系统复位后能进入正确的状态

case(current_state)

S1 : if(...)

next_state = S2; 

default : next_state = IDLE;  //默认是初始化状态

endcase

end 

//第三个进程,同步时序always模块,格式化描述次态寄存器输出

always @ (posedge clk or negedge rst_n)

case(next_state)

S1:

out1 <= 1'b1

S2:

out2 <= 1'b1;

default:... //default的作用是免除综合工具综合出锁存器

endcase

end

状态机在我常写的代码中非常常用,但是由于常常写的很长,所以就贴了贴网上常用的三段式状态机模板,我一向是支持三段式状态机,因为这样很符合思维逻辑性的进程。

6.顶层模块编写:

module topallkey(clk,rst_n,keyin,clock,dataout);
input clk;
input rst_n;
input wire keyin;
output clock;
wire dataend;
output dataout;
wire[7:0] ps2_data; 
top_ps2keyboard u3(.clk(clk),
                   .rst_n(rst_n),
   .ps2_keyin(keyin),
                   .ps2_data(ps2_data),
   .ps2_end(dataend),
   .clock(clock));
ctr u2(.clk(clk),
       .rst_n(rst_n),
.datain(ps2_data),
.dataend(dataend),
.dataout(dataout));
 

endmodule

以上是将ctr.v模块和top_ps2keyboard.v模块例化成u1和u2模块,.rst_n和.ps2_keyin为模块的引脚,其后面括号里面的信号就是例化模块的引脚,用于连接到整个模块的输出,两个例化模块的连接用wire信号相连。

7.常规问题:

“<=”与“=”的区别,好多书上都说阻塞与不阻塞,其实不必要讲的那么高深,其实就是“<=”需要时钟clk控制,“=”则不需要clk控制,直接可赋值。

clk与rst_n要着有何用,clk是编程fpga心脏跳动的源泉,rst_n是异步复位阻止程序乱拍的信号。

wire与reg区别,wire只是用于连线,reg用于寄存数据,当用于连线时只能用wire,当需要寄存数据时只能用reg。





你可能感兴趣的:((FPGA编程)仿C的硬件描述语言----verilog基本语法)