华中科技大学Verilog实验解析

Sukuna发布

实验二:基本的组合逻辑电路

这里只展示2.3的一部分代码

module decoder_3to8(in, out);
    input [2:0] in;
    output reg [7:0] out;
    
    always@(in)  
        case(in)  
            3'b000 : out[7:0] = 8'b11111110;
            3'b001 : out[7:0] = 8'b11111101;
            3'b010 : out[7:0] = 8'b11111011;
            3'b011 : out[7:0] = 8'b11110111;
            3'b100 : out[7:0] = 8'b11101111;
            3'b101 : out[7:0] = 8'b11011111;
            3'b110 : out[7:0] = 8'b10111111;
            default : out[7:0] = 8'b01111111;
        endcase
endmodule

这里我需要提一点,就是always语句或者initial语句里面是数据流的形式,数据流的形式和其他形式的区别有以下几点

  • 左边的元素一定是reg类型的
  • 不允许使用assign赋值
  • @(…..)表示…..里面的值发生变化的时候就进入语句块

这里可以使用case(…)来模仿C里面的switch语句来进行赋值(真值表)
用逻辑函数也可以(做运算或者申明逻辑门[逻辑门之间使用wire连接])

对于4-16的亦是如此

module decoder_4to16(in, out);
    input [3:0] in;
    output reg [7:0] out;

    always@(in)
        begin
            case(in)
                4'b0000 : out[7:0] = 8'b11000000;
                4'b0001 : out[7:0] = 8'b11111001;
                4'b0010 : out[7:0] = 8'b10100100;
                4'b0011 : out[7:0] = 8'b10110000;
                4'b0100 : out[7:0] = 8'b10011001;
                4'b0101 : out[7:0] = 8'b10010010;
                4'b0110 : out[7:0] = 8'b10000010;
                4'b0111 : out[7:0] = 8'b11111000;
                4'b1000 : out[7:0] = 8'b10000000;
                4'b1001 : out[7:0] = 8'b10011000;
                4'b1010 : out[7:0] = 8'b10001000;
                4'b1011 : out[7:0] = 8'b10000011;
                4'b1100 : out[7:0] = 8'b11000110;
                4'b1101 : out[7:0] = 8'b10100001;
                4'b1110 : out[7:0] = 8'b10000110;
                default : out[7:0] = 8'b10001110;
            endcase
        end
endmodule

最后使用结构声明来组装零件

module Last(SW, SEG, AN, LED);
    input [15:0] SW;       // 16位拨动开关
    output [7:0] SEG;      // 7段数码管驱动,低电平有效
    output [7:0] AN;       // 7段数码管片选信号,低电平有效
    output [15:0] LED;     // 16位LED显示

    decoder_3to8(.in(SW[15:13]), .out(AN[7:0]));
    decoder_4to16(.in(SW[3:0]), .out(SEG[7:0]));
    
    assign LED[15:0] = SW[15:0];
endmodule

说明一下.xxx(yyy)说明yyy这个值传进结构声明中xxx这个变量,.in(SW[15:13])表示SW[15:13]这个东西放到decoder_3to8里面的in

实验三:简单的同步时许逻辑电路

首先就是滤波器

module divider(clk, clk_N);
    input clk;                      // 系统时钟
    output reg clk_N;                   // 分频后的时钟
    parameter N = 100_000_000;     // 1Hz的时钟,N=fclk/fclk_N
    reg [31:0] counter;             /* 计数器变量,通过计数实现分频。当计数器从0计数到(N/2-1)时,输出时钟翻转,计数器清零 */

    initial
    begin                           // 赋初始值
        counter = 0;
        clk_N = 0;
    end
    always @(posedge clk)           // 时钟上升
    begin
        counter <= counter + 1;
        if (counter > N / 2)
            begin
                clk_N <= ~clk_N;
                counter <= 0;
            end
    end
endmodule

posedge代表上升的意思,这个就是clk(板子里面的E3)每一次上升就会触发,其实板子里面的E3会一直变化(速度非常快)这个就是板子里的E3变化了1亿次之后就会传输一个信号出去的意思

就是clk进.clk_N出clk变化100000000次,clk_N变化一次,这个就是分频的定义,所以说在always里面加上了一个if语句就是这个意思

module counter(clk, out);
    input clk;                    // 计数时钟
    output reg [2:0] out;         // 计数值

    always @(posedge clk)         // 在时钟上升沿计数器加1
    begin
        out <= out + 1;
    end
endmodule

计数器,就是每一次clk上升out就会加1,至于触发器怎么用,咱也不用管,就说明功能就完事了

第三个实验就是测试一下计数器和过滤器组合的原理

module divide_and_count(clk, out);
    input clk;
    output [2:0] out;
    wire clk_tmp;

    divider d1(.clk(clk), .clk_N(clk_tmp));
    counter c1(.clk(clk_tmp), .out(out[2:0]));
endmodule

这个是不是有点像Java里面的装饰器,对传进来的信号进行逐级装饰,传递来的信号经过计数器的转化进行输出

实验四:只读存储器:打个表就行了

module rom8x4(addr, data);
    input [2:0] addr;               // 地址
    output [3:0] data;              // 地址addr处存储的数据 
    reg [3: 0] mem [7: 0];          //  8个4位的存储器

    initial                         // 初始化存储器
        begin
            mem[0]=4'b0000;
            mem[1]=4'b0010;
            mem[2]=4'b0100;
            mem[3]=4'b0110;
            mem[4]=4'b1000;
            mem[5]=4'b1010;
            mem[6]=4'b1100;
            mem[7]=4'b1110;
        end

    assign data[3:0] = mem[addr];   // 读取addr单元的值输出

endmodule

下面就是把信号分解成七位表示器了.上面提到过

最后把这些东西组在一块,又用到组织模块

module dynamic_scan(clk, SEG, AN);
    input clk;              // 系统时钟
    output [7:0] SEG;  		// 分别对应CA、CB、CC、CD、CE、CF、CG和DP
    output [7:0] AN;        // 8位数码管片选信
    wire clk_tmp;
    wire [2:0] num;
    wire [3:0] code;

    divider d1(.clk(clk), .clk_N(clk_tmp));
    counter c1(.clk(clk_tmp), .out(num[2:0]));
    decoder_3to8(.in(num[2:0]), .out(AN[7:0]));
    rom8x4(.addr(num[2:0]), .data(code[3:0]));
    decoder_4to16(.in(code[3:0]), .out(SEG[7:0]));

endmodule

可以使用wire连接,也可以直接你的输出就是我的输入


0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用*标注

隐藏

总访问量:521786    今日访问量:3644    您是今天第:3644 位访问者