Verilog学习脚印2-时序逻辑

Verilog学习脚印2-时序逻辑
附:verilog语法笔记(持续更新ing)


触发器基础

因为笔者对触发器知识有所遗忘,因此在这里做一个回顾

以下这篇文章对RS触发器(Reset Set flip-flop)、D触发器(data flip-flop或delay flip-flop)描述已经较为详细。
链接


bash命令

bash调用dve和vcs的命令:

dve & // 启用VDE
vcs *.v -R -timescale=1ns/10ps +v2k +define+RTL_SAIF // 编译

实例1:计数器

电路原理(来自B站-北交李金城老师的PPT,侵删)

在这里插入图片描述

代码实现与验证

完整代码:

`timescale 1ns/10ps

// ----- definition of counter -----
module counter(
                clk,
                res,
                y
);
input           clk;
input           res;
output[7:0]     y;

reg[7:0]        y;

wire[7:0]       sum; // result of +1
assign          sum=y+1; // logic

always@(posedge clk or negedge res)
if(~res) begin
    y<=0;
end
else begin
    y<=sum;
end

endmodule

// ----- testbench of counter -----
module counter_tb;

reg             clk,res;
wire[7:0]       y;

counter counter(
                .clk(clk),
                .res(res),
                .y(y)
);

initial begin
    $dumpfile("counter_tb.vcd"); // save wave file
    $dumpvars(0,counter);
end

initial begin
            clk<=0;res<=0; // nitice! initial of res and clk is must!
    #20     res<=1;
    #6000   $stop;
end
always #5 clk<=~clk;

endmodule

波形输出:
在这里插入图片描述


实例2:4级伪随机码发生器

电路原理(来自B站-北交李金城老师的PPT,侵删)

在这里插入图片描述

代码实现与验证

代码如下:

// Level 4 pseudo-random code generator
`timescale 1ns/1ps

// ----- definition -----
module p_random_code_generator(
                                clk,
                                res,
                                y
);

input                           clk;
input                           res;
output                          y;

reg[3:0]                        d;
assign                          y=d[0];

always@(posedge clk or negedge res)
if(~res) begin
    d<=4'b1111;
end
else begin
    d[2:0]<=d[3:1]; // notice! '>>' is not recommanded!
    d[3]<=d[3]+d[0]; // nitoce! module 2 addition!
end

endmodule

// ----- testbench -----
module p_random_code_generator_tb;
reg                             clk,res;
wire                            y;
p_random_code_generator p_random_code_generator(
                                .clk(clk),
                                .res(res),
                                .y(y)
);

initial begin
    $dumpfile("p_random_code_generator_tb.vcd"); // save wave file
    $dumpvars(0,p_random_code_generator);
end

initial begin
            clk<=0;res<=0; // nitice! initial of res and clk is must!
    #20     res<=1;
    #600   $stop;
end
always #5 clk<=~clk;


endmodule

验证结果如下:
在这里插入图片描述


实例3:秒计数器

电路原理(来自B站-北交李金城老师的PPT,侵删)

功能说明:对于24MHz系统时钟,实现能够循环0-9的秒计数器
实现思路:首先得到秒脉冲,再对秒脉冲进行计数

在这里插入图片描述

代码实现与验证

代码:

// s_counter from 0 to 9
`timescale 1ns/1ps

module s_counter(
                clk,
                res,
                s_sum
);
input           clk;
input           res;
output          s_sum;

reg[24:0]       con_t; // crossover count. notice! why 24!
reg             s_pulse; // seconds pulse peak
reg[3:0]        s_sum; // second counter

parameter       frequency_clk=24; // 24MHz: system clock frequency

always@(posedge clk or negedge res)
if(~res)begin // notice! reset of all registers is must!
    con_t<=0;s_pulse<=0;s_sum<=0;
end
else begin
    if(con_t==frequency_clk*1000000-1)begin
        con_t<=0;
    end
    else begin
        con_t<=con_t+1;
    end

    if(con_t==0)begin
        s_pulse<=1;
    end
    else begin
        s_pulse<=0;
    end

    if(s_pulse==1)begin
        if(s_sum==9)begin
            s_sum<=0;
        end
        else begin
            s_sum<=s_sum+1;
        end
    end
end

endmodule

// ----- testbench -----
module s_counter_tb;
reg             clk,res;
wire[3:0]       s_sum;
s_counter s_counter(
                .clk(clk),
                .res(res),
                .s_sum(s_sum)
);

initial begin
    $dumpfile("s_counter_tb.vcd"); // save wave file
    $dumpvars(0,s_counter);
end

initial begin
                clk<=0;res<=0;
        #17     res<=1;
        #10000   $stop;
end

always #5 clk=~clk;


endmodule

验证结果如下:
在这里插入图片描述


实例4:相邻16点相加输出

功能说明:从data_in中每读取16个数据,就输出它们的和。

在这里插入图片描述
在这里插入图片描述
代码如下:

// add 16 numbers from data_in flow
`timescale 1ns/1ps

// ----- definition -----
module add_16(
                clk,
                res,
                data_in,
                syn_in,
                data_out,
                syn_out
);

input           clk;
input           res;
input[7:0]      data_in; // sample signal
input           syn_in; // sample clock signal
output[11:0]    data_out; // output the add result
output          syn_out; // output the sync pulse of the add result

reg             syn_in_n1; // reverse time delay of 'syn_in'
wire            syn_pulse;
reg[3:0]        con_syn; // counter of sync clock

wire[7:0]       comp_8; // complement code
wire[11:0]      d_12;  // notice! raise the wide to prevent overflow!!!
reg[11:0]       sigma; // result of add
reg[11:0]       data_out; // output
reg             syn_out;
assign          comp_8=data_in[7]?{data_in[7],~data_in[6:0]+1}:data_in;
assign          d_12={comp_8[7],comp_8[7],comp_8[7],comp_8[7],comp_8};  // why?


assign          syn_pulse=syn_in&syn_in_n1;   

always@(posedge clk or negedge res)
if(~res)begin  // notice! all registr must be reset!
    syn_in_n1<=0;sigma<=0;data_out<=0;syn_out<=0;con_syn<=0;
end
else begin
    syn_in_n1<=~syn_in;
    if(syn_pulse)begin
        con_syn<=con_syn+1;
    end

    if(syn_pulse)begin
        if(con_syn==15)begin
            sigma<=d_12;
            data_out<=sigma;
            syn_out<=1;
        end
        else begin
            sigma<=sigma+d_12;
        end
    end
    else begin
        syn_out<=0;
    end
end
    
endmodule

// ----- testbench -----
module add_16_tb;

reg             clk,res;
reg[7:0]        data_in;
reg             syn_in;
wire[11:0]      data_out;
wire            syn_out;

add_16 add_16(
                .clk(clk),
                .res(res),
                .data_in(data_in),
                .syn_in(syn_in),
                .data_out(data_out),
                .syn_out(syn_out)
);

initial begin
    $dumpfile("add_16_tb.vcd"); // save wave file
    $dumpvars(0,add_16);
end

initial begin
            clk<=0;res<=0;data_in<=1;syn_in<=0; // if data_in=-1, then data_in=8'b1000_0001
    #17     res<=1; // why 17? Avoid coinciding clock edges and reset edges
    #6000   $stop;
end

always #5 clk<=~clk;

always #100 syn_in<=~syn_in;

endmodule

验证如下:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值