Verilog 基础语法(题目)

Verilog 基础语法(题目)

**本内容来自 牛客网Verilog基础语法**

1、四选一多路器

制作一个四选一的多路选择器,要求输出定义上为线网类型
状态转换:
d0 11
d1 10
d2 01
d3 00
信号示意图:
Verilog 基础语法(题目)_第1张图片
波形示意图:
Verilog 基础语法(题目)_第2张图片
输入描述:
输入信号 d1,d2,d3,d4 sel
类型 wire

输出描述:
输出信号 mux_out
类型 wire

module mux4_1(
    input [1:0]d1,d2,d3,d0,
    input [1:0]sel,
    output[1:0]mux_out
    );
    //*************code***********//
    reg [1:0] mux_out_tmp;
    always@(*) begin
        case(sel)
            2'b00:  mux_out_tmp = d3;
            2'b01:  mux_out_tmp = d2;
            2'b10:  mux_out_tmp = d1;
            2'd11:  mux_out_tmp = d0;
            default:    mux_out_tmp = d3;
        endcase
    end
    assign mux_out = mux_out_tmp;
    //*************code***********//
endmodule

2、异步复位的串联T触发器

用verilog实现两个串联的异步复位的T触发器的逻辑,结构如图:
信号示意图:
Verilog 基础语法(题目)_第3张图片
波形示意图:
Verilog 基础语法(题目)_第4张图片
输入描述:
输入信号 data, clk, rst
类型 wire
在testbench中,clk为周期5ns的时钟,rst为低电平复位

输出描述:
输出信号 q
类型 reg

module Tff_2 (
    input wire data, clk, rst,
    output reg q  
);
    //*************code***********//
    // 做题之前首先需要知道T触发器的特点:输入为1时,输出进行翻转。
    // 另外需要注意异步复位
    reg tmp;
    always@(posedge clk or negedge rst) begin
        if(~rst)
            tmp <= 0;
        else if(data)
            tmp <= ~tmp;
        else
            tmp <= tmp;
    end

    always@(posedge clk or negedge rst) begin
        if(~rst)
            q <= 0;
        else if(tmp)
            q <= ~q;
        else
            q <= q;
    end
    //*************code***********//
endmodule

3、奇偶校验

现在需要对输入的32位数据进行奇偶校验,根据sel输出校验结果(1输出奇校验,0输出偶校验)
信号示意图:
Verilog 基础语法(题目)_第5张图片
波形示意图:
Verilog 基础语法(题目)_第6张图片
输入描述:
输入:bus、sel
类型:wire

输出描述:
输出信号:check
类型:wire

module odd_sel(
    input [31:0] bus,
    input sel,
    output check
);
//*************code***********//
// 奇偶校验根据被传输的一组二进制代码的数位中“1”的个数是奇数或偶数来进行校验。
// 采用奇数的称为奇校验,反之,称为偶校验。
// bus=0,二进制数 0000,偶数个1 按位异或为0;
// bus=2,二进制数 0010,奇数个1 按位异或为1;
// bus=3,二进制数 0011,偶数个1 按位异或为0;
// bus=8,二进制数 1000,奇数个1 按位异或为1;

// 在Verilog中,^运算符作为单目运算符时的功能是"按位异或",作为双目运算符时的功能是"异或"。
// 当data_in是一个4 bit,的数据时,^data_in = data_in[0] ^ data_in[1] ^ data_in[2] ^ data_in[3],简言之,就是^bus,
// 就是检查bus中1的个数是否是成对的,如果成队,那就是为0,也就是偶校验,所以奇校验刚好取反
    assign check = sel ? ^bus : !(^bus);
//*************code***********//
endmodule

4、移位运算与乘法

已知d为一个8位数,请在每个时钟周期分别输出该数乘1/3/7/8,并输出一个信号通知此时刻输入的d有效(d给出信号的上升沿表示写入有效)
信号示意图:
Verilog 基础语法(题目)_第7张图片
波形示意图:
Verilog 基础语法(题目)_第8张图片
输入描述:
输入信号:d、clk、rst
类型:wire
在testbench中,clk为周期5ns的时钟,rst为低电平复位

输出描述:
输出信号:input_grant、out
类型:reg

分析:
题意整理:

  1. 在硬件中进行乘除法运算是比较消耗资源的一种方法,想要在不影响延迟并尽量减少资源消耗,必须从硬件的特点上进行设计。
  2. 根据寄存器的原理,由于是二进制,所以进位和退位为x2或者/2,同样除7可以使用进位3然后减去本身的做法,这样就将乘除法运算转化为位运算,这是一种比较简单的整数运算处理。
  3. 需要给出一个计数器的状态机,注意d输入不是随时有效的,只有在cnt计数为0的那个时钟沿,d输入有效,因此需要设计一个寄存器din,在cnt为0时候锁存d的值

解体主体:
根据题意分析,可以得到状态转换:
设输入为d,计数器为cnt
移位运算逻辑:

乘数 位运算
1 d
3 (din<<2)-din
7 (din<<3)-din
8 (din<<3)

状态机逻辑:

cnt out input_grant
0 直接输出d,并寄存d的值为din 1
1 (din<<2)-din 0
2 (din<<3)-din 0
3 (din<<3) 0
将电路转换成Verilog代码描述如下:
module multi_sel(
    input [7:0]d,
    input clk,
    input rst,
    output reg input_grant,
    output reg [10:0]out
);
//*************code***********//
    reg [1:0] cnt;
    reg [7:0] din;

    always @(posedge clk or negedge rst) begin
        if(!rst) begin
            cnt <= 0;
            out <= 0;
            input_grant <= 0;
            din <= 0;
        end
        else begin
            cnt <= cnt + 1;
            case (cnt)
                0:  begin
                    din <= d;
                    input_grant <= 1;
                    out <= d;
                end
                1:  begin
                    input_grant <= 0;
                    out <= (din<<2)-din;
                end
                2:  begin
                    input_grant <= 0;
                    out <= (din<<3)-din;
                end
                3:  begin
                    input_grant <= 0;
                    out <= (din<<3);
                end
            endcase
        end
    end
//*************code***********//
endmodule

你可能感兴趣的:(Verilog,FPGA,fpga开发)