Verilog基础模块

参数parameter:

        parameter可以用标识符定义常量,运用时只使用标识符即可,提高可读性及维护性。

        参数的传递:在一个模块中如果有定义参数,在其他模块调用此模块时可以传递参数,并可以修改参数,如下所示,在module后用#()表示。

//定义的模块
module rom #(
 parameter depth =16, 
 parameter width = 8 
) 
( 
input [depth-1:0] addr , 
input [width-1:0] data , 
output result
);
endmodule

//调用模块
module top() ;
wire [31:0] addr ; 
wire [15:0] data ; 
wire result ;

rom 
#( 
.depth(32), 
.width(16)
)

rom rom_inst
( 
.addr(addr) , 
.data(data) , 
.result(result) 
); 
endmodule

        Parameter可以用于模块间的参数传递,而localparam仅用于本模块内使用,不能用于参数传递,而Localparam多用于状态机状态的定义。

变量

wire型

        Wire类型变量,也叫网络类型变量,用于结构实体之间的物理连接,,用连续赋值语句assign赋值。

Reg型

        Reg 类型变量,也称为寄存器变量,可用来储存值,必须在always语句里使用。也可以生成组合逻辑,,敏感信号没有时钟。

Memory型

        可以用memory类型来定义RAM,ROM等存储器,其结构为reg [n-1:0] 存储器名[m-1:0],意义为m个n位宽度的寄存器,m为存储器的深度,n为数据宽度。

赋值运算符

        “=”阻塞赋值,”<=”非阻塞赋值。阻塞赋值为执行完一条赋值语句,再执行下一条,可理解为顺序执行,而且赋值是立即执行;非阻塞赋值可理解为并行执行,不考虑顺序,在always块语句执行完成后,才进行赋值。

        一般情况下,在时序逻辑电路中使用非阻塞赋值,可避免仿真时出现竞争冒险现象;在组合逻辑中使用阻塞赋值,执行赋值语句后立即改变;在assign语句中必须用阻塞赋值。

        if (!a)表示条件为a的值不为1,也就是0。

拼接运算符

        “{ }”拼接运算符,将多个信号按位拼接,如{a[3:0], b[2:0]},将a的低4位,b的低3位拼接成7位数据。另外,{n{a[2:0]}}表示将n个a[2:0]拼接,{n{1’b0}}表示n位的0拼接。如{8{1’b0}}表示为8’b0000_0000。

带异步复位的D触发器

        异步复位是指独立于时钟,一旦异步复位信号有效,就触发复位操作,用于给信号复位,初始化。

always @(posedge clk or negedge rst) 
begin 
    if (rst == 1'b0) 
        q <= 0 ; 
    else 
        q <= d;
end

带异步复位同步清零的D触发器

        异步复位独立于时钟操作,而同步清零则是同步于时钟信号下操作的。不同于异步复位,同步操作不能把信号放到敏感列表里。

always @(posedge clk or negedge rst)
 begin 
    if (rst == 1'b0) 
        q <= 0 ; 
    else if (clr == 1'b1) 
        q <= 0 ; 
    else 
        q <= d ; 
end

移位寄存器

always @(posedge clk or negedge rst) begin 
    if (rst == 1'b0) 
        q <= 0 ; 
    else 
        q <= {q[6:0], d} ;  //向左移位 
       //q <= {d, q[7:1]} ; //向右移位 
end

单口RAM

单口RAM的写地址与读地址共用一个地址。

伪双口RAM

伪双口RAM的读写地址是独立的,可以随机选择写或读地址,同时进行读写操作。

真双口RAM

真双口RAM有两套控制线,数据线,允许两个系统对其进行读写操作。

单口ROM

ROM是用来存储数据的,可以按照代码形式初始化ROM,但这种方法处理大容量的ROM就比较麻烦,建议用FPGA自带的ROM IP核实现,并添加初始化文件。

有限状态机

        在verilog里经常会用到有限状态机,处理相对复杂的逻辑,设定好不同的状态,根据触发条件跳转到对应的状态,在不同的状态下做相应的处理。有限状态机主要用到always及case语句。

        Mealy有限状态机,输出不仅与当前状态有关,也与输入信号有关,在RTL中会与输入信号有连接。Moore有限状态机,输出只与当前状态有关,与输入信号无关,输入信号只影响状态的改变,不影响输出。

        采用一段式状态机的写法,只用一个always语句,所有的状态转移,判断状态转移条件,数据输出都在一个always语句里,缺点是如果状态太多,会使整段程序显的冗长。采用三段式状态机的写法,状态转移用一个always语句,判断状态转移条件是组合逻辑,采用一个always语句,数据输出也是单独的 always语句,这样写起来比较直观清晰,状态很多时也不会显得繁琐。

        采用Moore状态机三段式的写法设计一个8位的移位寄存器:

module top(
input shift_start,
input shift_stop ,
input rst ,
input clk,
input d,
output reg [ 7:0] q
);

parameter Idle  = 2'd0 ;  // Idle state
parameter Start = 2'dl ;  // start state
parameter Run   = 2'd2 ;  // Run state
parameter Stop  = 2'd3 ;  // stop state

reg [1:0] current_state ; // statement
reg [1:0] next_state ;
reg [4:0] delay_cnt ;     // delay counter

//First part: statement transition
always @(posedge clk or negedge rst)begin
    if(!rst)
        current_state <= Idle ;
    else
        current_state <= next_state ;
end

//Second part: combination logic, judge statement transition condition
always @(*)
begin
    case (current _state)
        Idle: begin
                if(shift_start)
                    next_state <=start ;
                else
                    next_state <=Idle ;
                end
        start : begin
                if(delay cnt == 5'd99)
                    next_state <=Run ;
                else
                    next_state <=start ;
                end
        Run: begin
                if(shift_stop)
                    next_state <=stop ;
                else
                    next_state <=Run ;
               end
        stop:
                next_state <=Idle ;
        default:
                next_state <=Idle ;
endcase
end

//Last part : output data
always @ (posedge clk or negedge rst) begin
    if( !rst)
        delay_cnt <= 0 ;
    else if (current_state == Start)
        delay cnt <=delay cnt +1 'b1 ;
    else
        delay cnt <=0 ;
end

always @(posedge clk or negedge rst) begin
    if(!rst)
        q <= 0 ;
    else if( current_state == Run)
        q <={q[6:0], d};
    else
        q <=0;
end
endmodule


激励文件:

`timescale 1 ns/1 ns
module top_tb ();
reg shift_start ;
reg shift_stop ;
reg rst ;
reg clk:
reg d ;
wire [7:0]a ;

initial
begin
    rst = 0 :
    clk = 0 ;
    d = 0   ;
    #200 rst = 1 ;
    forever
    begin
        #( { $random} %100)//产生0~99的随机数
        d = ~d ;
    end
end

initial
begin
    shift_start = 0 ;
    shift_stop  = 0 ;
    #300 shift_start   = 1 ;
    #1000 shift_start  =0  ;
          shift_stop   =1  ;
    #50 shift_stop = 0 ;
end

always #10 clk = ~clk ;

top t0
(
.shift_start (shift_start) ,
.shift_stop  (shift_stop)  ,
.rst         (rst)         , 
.clk         (clk)         ,
.d           (d)           ,
.q           (q)
) ;
endmodule


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A u g

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值