Verilog 基础语法(题目)
**本内容来自 牛客网Verilog基础语法**
1、四选一多路器
制作一个四选一的多路选择器,要求输出定义上为线网类型
状态转换:
d0 11
d1 10
d2 01
d3 00
信号示意图:
波形示意图:
输入描述:
输入信号 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@(*) begincase(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;endcaseendassign mux_out = mux_out_tmp;//*************code***********//
endmodule
2、异步复位的串联T触发器
用verilog实现两个串联的异步复位的T触发器的逻辑,结构如图:
信号示意图:
波形示意图:
输入描述:
输入信号 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) beginif(~rst)tmp <= 0;else if(data)tmp <= ~tmp;elsetmp <= tmp;endalways@(posedge clk or negedge rst) beginif(~rst)q <= 0;else if(tmp)q <= ~q;elseq <= q;end//*************code***********//
endmodule
3、奇偶校验
现在需要对输入的32位数据进行奇偶校验,根据sel输出校验结果(1输出奇校验,0输出偶校验)
信号示意图:
波形示意图:
输入描述:
输入: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给出信号的上升沿表示写入有效)
信号示意图:
波形示意图:
输入描述:
输入信号:d、clk、rst
类型:wire
在testbench中,clk为周期5ns的时钟,rst为低电平复位
输出描述:
输出信号:input_grant、out
类型:reg
分析:
题意整理:
- 在硬件中进行乘除法运算是比较消耗资源的一种方法,想要在不影响延迟并尽量减少资源消耗,必须从硬件的特点上进行设计。
- 根据寄存器的原理,由于是二进制,所以进位和退位为x2或者/2,同样除7可以使用进位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) beginif(!rst) begincnt <= 0;out <= 0;input_grant <= 0;din <= 0;endelse begincnt <= cnt + 1;case (cnt)0: begindin <= d;input_grant <= 1;out <= d;end1: begininput_grant <= 0;out <= (din<<2)-din;end2: begininput_grant <= 0;out <= (din<<3)-din;end3: begininput_grant <= 0;out <= (din<<3);endendcaseendend
//*************code***********//
endmodule