1.LV1 四选一多路器
1.题目:制作一个四选一的多路选择器,要求输出定义上为线网类型
2.解题代码:
module mux4_1( //建立一个模块 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; //首先建立一个2 位寄存器,存储数据
always@(*) //对下面等式右边的信号 做出应激反应,就是右边的数值发生改变,就会激发这个模块
begin
case (sel) //条件语句
2'b00: mux_out_tmp = d3; //堵塞赋值
2'b01: mux_out_tmp = d2; //堵塞赋值
2'b10: mux_out_tmp = d1; //堵塞赋值
default: mux_out_tmp =d0; //堵塞赋值
endcase
end
assign mux_out = mux_out_tmp; //持续赋值语句
//*************code***********//
endmodule
2.VL2 异步复位的串联T触发器
1.题目描述:
用verilog实现两个串联的异步复位的T触发器的逻辑,结构如图:
2.解题知识:
1. rst 低电平复位 代表 输出的信号值为 0
2.T触发器 在时钟 上升沿的时候输出信号, 假如输入信号的地方有小圈 就是下降沿。
3.因为时钟 和复位信号都是在一条线 所以我们不要管先后顺序.
4.在输出描述的 里面说了, 输出信号为 reg 类型
3.解题代码:
module Tff_2 ( //模块名字
input wire data, clk, rst, //输入信号
output reg q //输出信号
);
//*************code***********//
reg line; //输出信号类型 reg
always@(posedge clk or negedge rst) //第一个T触发器 ,时钟上升沿触发, 复位信号下降沿触发,因为此时rst 是低电平
if(rst == 1'b0) //复位信号是低电平
line <=1'b0;
else if(data == 1'b0) //在时钟上升沿 的时候 输入信号为0
line <=line;
else 在时钟上升沿 的时候 输入信号为1
line <=~line;
always@(posedge clk or negedge rst)//第二个触发器
if(rst == 1'b0) //复位信号是低电平
q<= 1'b0;
else if(line ==1'b0) //在时钟上升沿 的时候 输入信号为0
q<=q;
else //在时钟上升沿 的时候 输入信号为1
q<=~q;
//*************code***********//
endmodule
3.VL3 奇偶校验
1.题目:现在需要对输入的32位数据进行奇偶校验,根据sel输出校验结果(1输出奇校验,0输出偶校验)
2.解题思路
一,奇偶校验:在数据位后添加一个校验位,使得所有数位中1的个数为奇数或者偶数。
偶校验:添加校验位后,数位中的1总数是偶数。
比如:0110,偶校验位为0,变为01100。
二,32位数据中1 的个数, 我们可以使用 ^按位异或
tmp = ^bus[31:0] 等价于 tmp = bus[31]^bus[30]^...^bus[0]。
//如果bus有奇数个1,tmp=1;反之,tmp=0。
3.解题代码:
`timescale 1ns/1ns
module odd_sel(
input [31:0] bus,
input sel,
output check
);
//*************code***********//
integer i; //循环变量
wire tmp; //线网型数据
assign tmp =^bus[31:0]; //持续赋值语句
assign check = sel?tmp:~tmp;//持续赋值语句
//*************code***********//
endmodule
4.VL4 移位运算与乘法
1.题目:已知d为一个8位数,请在每个时钟周期分别输出该数乘1/3/7/8,并输出一个信号通知此时刻输入的d有效(d给出的信号的上升沿表示写入有效)
2.解题思路:
一, 可以注意输入信号只有 在经历了4次输出信息,才会使用.
二,他可以变成一个 两个组合, 激励信号为 时钟信号上升沿.
三,注意 他需我们发出一个上升沿的信号,来代表 输出信号的 开始输出.
3.解题代码:
`timescale 1ns/1ns
module multi_sel(
input [7:0]d ,
input clk,
input rst,
output reg input_grant,
output reg [10:0]out
);
//*************code***********//
reg[1:0] state;//设置状态位
reg[10:0] data;// 设置数据位
always @(posedge clk or negedge rst)// 把握 时钟周期 5次 设计一个时序组合
if(rst == 1'b0)
begin
state <=2'b00; //复位信号,开始信号为0
end
else if(state == 2'b11) //当一个上升沿的信号来到,我们的信号等于最大, 此时是下一个数据的输入时候,我们要转化为第一个数据的输出时刻
begin
state <=2'b00;
end
else
begin
state <=state+2'b01;
end
always @(posedge clk or negedge rst ) //逻辑输出组合
if(rst == 1'b0) //复位信号 , 全部初始信号
fork
out <= 10'b0;
input_grant <=1'b0;
join
else
case (state) //状态位
2'b00: //此时输出一倍的 信号 ,,并且输出一个 上升沿的信号
begin
input_grant<=1'b1; //上升沿信号 0->1
out <= d; //输出一倍的输入信号
data <= d;//记录这次 输入的信号
end
2'b01:
begin
input_grant <=1'b0; //归0 就是提前变成 0 之后我们就好在
out <=3*data;
end
2'b10:
begin
input_grant <=1'b0;
out <=7*data;
end
2'b11:
begin
input_grant<=1'b0;
out<=8*data;
end
default:
begin
out<= 10'b0;
input_grant <=1'b0;
end
endcase
//*************code***********//
endmodule
5.VL5 位拆分与运算
1.题目:
现在输入了一个压缩的16位数据,其实际上包含了四个数据[3:0][7:4][11:8][15:12],
现在请按照sel选择输出四个数据的相加结果,并输出valid_out信号(在不输出时候拉低)
0: 不输出且只有此时的输入有效
1:输出[3:0]+[7:4]
2:输出[3:0]+[11:8]
3:输出[3:0]+[15:12]
2.解题思路:两个组合
3.解题代码:
`timescale 1ns/1ns
module data_cal(
input clk,
input rst,
input [15:0]d,
input [1:0]sel,
output reg[4:0]out,
output reg validout
);
reg [15:0]data_lock;
always@(posedge clk or negedge rst) begin
if (!rst)
data_lock <= 0;
else if(!sel)
data_lock <= d;
end
always@(posedge clk or negedge rst) begin
if (!rst) begin
out <= 'b0;
validout <=0;
end
else begin
case(sel)
0:begin
out <= 'b0;
validout <=0;
end
1:begin
out <= data_lock[3:0]+data_lock[7:4];
validout <=1;
end
2:begin
out <= data_lock[3:0]+data_lock[11:8];
validout <=1;
end
3:begin
out <= data_lock[3:0]+data_lock[15:12];
validout <=1;
end
endcase
end
end
endmodule
6.VL6 多功能数据处理器
1.题目:根据指示信号select的不同,对输入信号a,b实现不同的运算。输入信号a,b为8bit有符号数,当select信号为0,输出a;当select信号为1,输出b;当select信号为2,输出a+b;当select信号为3,输出a-b.
2.解题思路:位数需要自己解决!!
3.解题代码:
`timescale 1ns/1ns
module data_select(
input clk,
input rst_n,
input signed[7:0]a,
input signed[7:0]b,
input [1:0]select,
output reg signed [8:0]c
);
always @(posedge clk or negedge rst_n )
begin
if(rst_n == 1'b0)
c <= 9'b0;
else
begin
case(select)
2'b00:
c <={a[7],a};
2'b01:
c <={b[7],b};
2'b10:
c <={a[7],a} + {b[7],b};
2'b11:
c <={a[7],a} - {b[7],b};
default:
begin
c <=9'b0;
end
endcase
end
end
endmodule
7.VL7 求两个数的差值
1.题目:根据输入信号a,b的大小关系,求解两个数的差值:输入信号a,b为8bit位宽的无符号数。如果a>b,则输出a-b,如果a≤b,则输出b-a。
2.解题思路:三目运算符
3.解题代码:
`timescale 1ns/1ns
module data_minus(
input clk,
input rst_n,
input [7:0]a,
input [7:0]b,
output reg [8:0]c
);
always@ (posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
c<= 9'b0;
end
else
begin
c <= a>b? (a-b) : (b-a);
end
end
endmodule
8.VL8 使用generate…for语句简化代码
1.题目:在某个module中包含了很多相似的连续赋值语句,请使用generata…for语句编写代码,替代该语句,要求不能改变原module的功能。
使用Verilog HDL实现以上功能并编写testbench验证。
2.解题思路 :for 循环语句的使用 这个方式 (generate 方法比那个安全一点)
3.解题代码:
`timescale 1ns/1ns
module gen_for_module(
input [7:0] data_in,
output [7:0] data_out
);
genvar i;
generate
for(i=0;i<8;i=i+1)
begin
assign data_out[i] = data_in[7-i];
end
endgenerate
endmodule
9.VL9 使用子模块实现三输入数的大小比较
1.题目:
在数字芯片设计中,通常把完成特定功能且相对独立的代码编写成子模块,在需要的时候再在主模块中例化使用,以提高代码的可复用性和设计的层次性,方便后续的修改。
请编写一个子模块,将输入两个8bit位宽的变量data_a,data_b,并输出data_a,data_b之中较小的数。并在主模块中例化,实现输出三个8bit输入信号的最小值的功能。
2.解题思路: 模板的使用
3.解题代码:
`timescale 1ns/1ns
module main_mod(
input clk,
input rst_n,
input [7:0]a,
input [7:0]b,
input [7:0]c,
output [7:0]d
);
wire [7:0] min_ab;
wire [7:0] min_ac;
wire [7:0] min_bc;
sub_mod sub_mod_Uo(
.clk (clk),
.rst_n (rst_n),
.a (a),
.b (b),
.c (min_ab)
);
sub_mod sub_mod_U1(
.clk (clk),
.rst_n (rst_n),
.a (a),
.b (c),
.c (min_ac)
);
sub_mod sub_mod_U2(
.clk (clk),
.rst_n (rst_n),
.a (min_ab),
.b (min_ac),
.c (min_bc)
);
assign d =min_bc;
endmodule
module sub_mod(
input clk,
input rst_n,
input [7:0]a,
input [7:0]b,
output reg[7:0]c
);
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
c <= 8'b0;
else
begin
c <= (a>b)? b:a;
end
end
endmodule
10.VL10 使用函数实现数据大小端转换
1.题目:
在数字芯片设计中,经常把实现特定功能的模块编写成函数,在需要的时候再在主模块中调用,以提高代码的复用性和提高设计的层次,分别后续的修改。
请用函数实现一个4bit数据大小端转换的功能。实现对两个不同的输入分别转换并输出。
2.解题思路: 暴力赋值 与 循环赋值
3.解题代码:
`timescale 1ns/1ns
module function_mod(
input [3:0]a,
input [3:0]b,
output [3:0]c,
output [3:0]d
);
assign c = revrs(a);
assign d = revrs(b);//使用写在 函数的前面
integer i;
function[3:0] revrs; //模块
input [3:0] datain;
begin //这里要起名字, 不然会出问题。 要不把 interger i 放外面去
for(i=0;i<4;i=i+1)
begin
revrs[i] = datain[3-i];
end
end
endfunction
endmodule