Verilog 基础语法(题目)
**本内容来自 牛客网Verilog基础语法**
1、四选一多路器
制作一个四选一的多路选择器,要求输出定义上为线网类型
状态转换:
d0 11
d1 10
d2 01
d3 00
信号示意图:
波形示意图:
输入描述:
输入信号 d1,d2,d3,d4 sel
类型 wire
输出描述:
输出信号 mux_out
类型 wire
c
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触发器的逻辑,结构如图:
信号示意图:
波形示意图:
输入描述:
输入信号 data, clk, rst
类型 wire
在testbench中,clk为周期5ns的时钟,rst为低电平复位
输出描述:
输出信号 q
类型 reg
c
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输出偶校验)
信号示意图:
波形示意图:
输入描述:
输入:bus、sel
类型:wire
输出描述:
输出信号:check
类型:wire
c
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代码描述如下: |
c
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