硬件语言 Verilog HDL 牛客刷题day01 基础语法部分

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

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值