Verilog数字系统设计学习笔记01

第一到五章

–二选一多路选择器


always@(sl or a or b)
    if(! sl) out = a;

其中always表示,sl或a或b其中有一个变化时就执行下面的语句。


–定义参数

parameter 
	wordsize=16,
	memsize=256;
reg[wordsize-1:0]
mem[mensize-1:0],
writereg, reading;
//同时定义存储类类型和reg数据类型
reg [n-1:0] rega;
//一个n位的寄存器,n位寄存器可以直接赋值
rega = 0;
---
reg mema[n-1:0]
//一个有n个1位寄存器构成的存储器组,存储器不能直接赋值
mema[3]=0;

–运算符表达式

位运算符

~   //取反
&	//按位与
|	//按位或
^	//按位异或
^~	//按位同或(异或非)

与门:有0则0,同1为1

或门:有1则1,同0为0

异或门:相异为1(助记:把那个“或”的一撇堪称是1)

同或门:相同为1,也可理解为异或门加上非门

位移运算
module shift;
    reg[3:0] start, //四位reg
    reg[3:0] result;
    	initial;
    	begin;
            start=1;
            //设定start的初始值为0001
            reault=(start<<2);
            //移位后,start的值0100,然后赋值给result
        end
endmodule
位拼接运算
{a, b[3:0], w, 3'b101}

{a, b[3], b[2], b[1], b[0], w, 1'b1, 1'b0, 1'b1}

{4{w}} //{w, w, w, w}

{b,3{a, b}} //{b, a, b, a, b, a, b}

–赋值语句和块语句

1、非阻塞赋值(Non_Blocking)赋值方式(b<=a)

​ 1)在语句块当中,上面语句所赋的变量值不能立即就为下面的语句所用;

​ 2)块结束后才能完成这次的赋值操作,而所赋的变量值是上一次赋值得到的;

​ 3)在编写可综合的时序逻辑模块时,这是最常用的赋值方法。

2、阻塞(Blocking)赋值(b=a)

​ 1)赋值语句完成执行后块才结束;

​ 2)b的赋值在语句执行完成后就立刻改变;

​ 3)在时序逻辑中使用可能会产生意想不到的结果;

–循环语句

1)forever,连续执行语句

forever
    begin
        xxx
    end

2)repeat,连续执行一条语句n次

3)while,执行一条语句知道某个条件不满足。

4)for,循环语句

–顺序块和并行块

module top;
    initial
        begin:block1
            integer i; //整形变量时静态本地变量
        end
    //可以通过top.block1.i被他模块访问
    initial 
        fork:block2l
            reg i;
        join
    可以通过top.block2.i被他模块访问

–部分简单的案例

//四选一多路选择器
moudule mux4_to_1(
	input i0,
    input i1,
    input i2,
    input i3,
    input s1,
    input s2,
    output out
);

always @(s1 or s0 or i0 or i1 or i2 or i3)
    begin
        case({s1, s0})
            2'b00:out=i0;
            2'b01:out=i1;
            2'b10:out=i2;
            2'b01:out=i3;
            default:out=1'bx;
        endcase
    end
endmodule

//四位计数器
module counter(
	input clock,
    input clear,
    output reg[3:0] Q
);
    always @(posedge clear or negedge clock)
        begin
            if(clear)
                Q<=4'd0; //为了实现注入触发器一类的时序逻辑,使用非阻塞赋值
            else
                Q<=Q+1; //Q是一个四位寄存器,计数超过15之后会归零,因为模16没有必要
        end
endmodule

第六章

–Task & Function

//红绿灯举例
//红绿灯举例
module traffic_lights
    reg clock;
    reg red;
    reg amber;
    reg green;
    parameter on =1, off=0, red_tics=350, 
    		amber_tics=30,green_tics=200;
    initial red=off;
    initial amber=off;
    initial green=off;
    
//交通灯控制程序
    always
        begin
            red=on;
            light(red, red_tics);
            green=on;
            light(green, green_tics);
            amber=on;
            light(amber, amber_tics);
        end
    
    task light;
        output color;
        input[31:0] tics;
        
        begin
            repeat(tics)
                //这个是 Verilog 的一个关键字,表示重复执行接下来的语句 tics 次。在这个例子中,就是让 @(posedge clock) 这个语句重复执行 tics 次
                @(posedge clock);
            color=off;
        end
    endtask
    
    //产生时钟脉冲的always模块
    always
        begin 
            #100 clock=0;
            #100 clock=1;
        end
    
endmodule
    
//偶校验位的函数(cal_parity)
//定义一个模块,其中包含能计算偶校验位的函数(cal_parity)
module parity
    reg[31:0] addr;
    reg parity;
    
    initial 
        begin
            addr=32'h3456_789a;
            #10 addr=32'hc4c6_78ff;
            #10 addr=32'hff56_ff9a;
            #10 addr=32'h3faa_aaaa;
        end
    
    //每当地址值发生变化,计算新的偶校验位
    always @(addr)
        begin
            parity=cal_parity(addr);  //第一次启动校验位计算函数
            $display("Parity calculated =%b", calc_parity(addr))
            //第二次去启动校验位计算函数
            
        end
    
    //定义偶校验计算函数
    function calc_parity
        input[31:0] address;
        begin
            //适当地设置输出值,使用隐含的内部寄存器calc_parity
            calc_parity = ^address;  //返回所有地址位的异或值
            
        end
    endfunction
endmodule

	//C语言风格声明
    function calc_parity(input[31:0] address);
        begin
            calc_parity= ^address;
        end
    endfunction


//左/右移位寄存器
//定义一个左/右移位寄存器
module shifter;
    `define LEFT_SHIFT 1'b0;
    `define RIGHT_SHIFT 1'b1;
    
    reg[31:0] addr;
    reg[31:0] left_addr;
    reg[31:0] right_addr;
    
    reg control;
    
    //每当新地址出现的时候就计算右移位和左移位的值
    always @(addr)
        begin
            //调用下面的定义的具有左右移位功能的函数
            left_addr=shift(addr, `LEFT_SHIFT);
            right_addr=shift(addr, `RIGHT_SHIFT);
        end
    
    function[31:0] shift;
        input[31:0] address;
        input control;
        
        begin 
            //根据控制信号适当地设置输出值
            shift=(control==`LEFT_SHIFT)?(address<<1):(address>>1);
        end
    endfunction
endmodule

//自动(递归)函数
module top;
    //定义自动(递归)函数
    function automatic integer factorial;
        input[31:0] oper;
        integer i;
        begin
            if(operand>=2)
                factorial=factorial(oper-1)*oper; //递归调用
            else
                factorial = 1;
        end
    endfunction
    
    //调用该函数
    integer result;
    initial
        begin
            result=factorial(4); //调用4的阶乘
            $display("Factorial of 4 is %0d", result); //显示24
        end
endmodule

//计算地址总线的宽度
module ram(......);
    parameter RAM_DEPTH=256;
    input [clog2(RAM_DEPTH)-1:0] addr_bus;
    
    function integer clogb2(input integer depth)
        begin
            for(clogb2=0; depth>0; clogb2=clogb2+1)
                depth=depth>>1;
        end
    endfunction
    
endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值