牛客网verilog快速入门_ 基础语法

目录

VL1:4选1多路选择器

(1)描述

(2)代码

VL2:异步复位的串联T触发器

(1)描述     

(2)代码

VL3:奇偶校验

(1)描述

(2)代码

VL4:移位运算与乘法

(1)描述

(2)代码

VL5:位拆分与运算

(1)描述

(2)代码

VL6:多功能数据处理器

(1)描述

(2)代码

VL7:求两个数的差值

(1)描述

(2)代码

VL8:使用generate...for语句简化代码

(1)描述

(2)代码

VL9:使用子模块实现三输入数的大小比较

(1)描述

(2)代码

VL10:使用函数实现数据大小端转换

(1)描述

(2)代码​​​​​​​


VL1:4选1多路选择器

(1)描述

制作一个四选一的多路选择器,要求输出定义上为线网类型

状态转换:
        d0    11
        d1    10
        d2    01
        d3    00

信号示意图:

 波形示意图:

 输入描述:

        输入信号   d1,d2,d3,d4 sel
        类型 wire

输出描述:

        输出信号 mux_out
        类型  wire

(2)代码

`timescale 1ns/1ns
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_ff   ;
wire [1:0] mux_out      ;
always @(*) begin
    case(sel[1:0])
        2'b00   : mux_out_ff = d3 ;
        2'b01   : mux_out_ff = d2 ;
        2'b10   : mux_out_ff = d1 ;
        default : mux_out_ff = d0 ;
    endcase
end

assign mux_out = mux_out_ff ;

//*************code***********//
endmodule

VL2:异步复位的串联T触发器

(1)描述     

用verilog实现两个串联的异步复位的T触发器的逻辑,结构如图:

信号示意图:

 波形示意图:


 输入描述:  

      输入信号   data, clk, rst
        类型 wire
        在testbench中,clk为周期5ns的时钟,rst为低电平复位

 输出描述:

        输出信号 q 
        类型  reg 

(2)代码

`timescale 1ns/1ns
module Tff_2 (
input wire data, clk, rst,
output reg q  
);
//*************code***********//
reg q_0 ;
always @(posedge clk or negedge rst) begin
    if(!rst)
        q_0 <= 1'b0 ;
    else begin
        if(data == 1'b0)
            q_0 <=  q_0 ;
        else
            q_0 <= ~q_0 ;
    end
end

always @(posedge clk or negedge rst) begin
    if(!rst)
        q <= 1'b0 ;
    else begin
        if(q_0 == 1'b0)
            q <=  q ;
        else
            q <= ~q ;
    end
end
//*************code***********//
endmodule

VL3:奇偶校验

(1)描述

题目描述:

        现在需要对输入的32位数据进行奇偶校验,根据sel输出校验结果(1输出奇校验,0输出偶校验)

信号示意图:

 波形示意图:

 输入描述:

        输入信号   bus sel
        类型 wire

输出描述

        输出信号   check        
        类型  wire

(2)代码

`timescale 1ns/1ns
module odd_sel(
input [31:0] bus,
input sel,
output check
);
//*************code***********//
wire check      ;
wire check_odd  ;
wire check_even ;
assign check_odd  = ^bus        ;
assign check_even = ~check_odd  ;
assign check = sel ? check_odd : check_even ;
//*************code***********//
endmodule

VL4:移位运算与乘法

(1)描述

题目描述:

      已知d为一个8位数,请在每个时钟周期分别输出该数乘1/3/7/8,并输出一个信号通知此时刻输入的d有效(d给出的信号的上升沿表示写入有效)

信号示意图:

 波形示意图:

 输入描述:

        输入信号   d, clk, rst
        类型 wire
        在testbench中,clk为周期5ns的时钟,rst为低电平复位

输出描述

        输出信号 input_grant    out
        类型  reg 

(2)代码

`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 [43 : 0] shift_register   ;
reg [2  : 0] cnt              ;
always @(posedge clk or negedge rst) begin
    if(!rst)
        shift_register <= 44'h0 ;
    else begin
        shift_register[10:0]  <= {3'h0, d[7:0]}                         ; // d*1
        shift_register[21:11] <= shift_register[10:0] * 2'd3            ; // d*3
        shift_register[32:22] <= (shift_register[21:11] / 2'd3) * 3'd7  ; // d*7
        shift_register[43:33] <= (shift_register[32:22] / 3'd7) * 4'd8  ; // d*8
    end
end
always @(posedge clk or negedge rst) begin
    if(!rst)
        cnt <= 3'h0 ;
    else begin
        if(cnt == 3'd4)
            cnt <= 3'h1 ;
        else
            cnt <= cnt + 1'b1 ;
    end
end

always @(*) begin
    if(cnt == 3'd1)
        input_grant = 1'b1 ;
    else
        input_grant = 1'b0 ;
end

always @(*) begin
    case(cnt)
        3'b00   : out = 11'h0                 ;
        3'b01   : out = shift_register[10:0]  ;
        3'b10   : out = shift_register[21:11] ;
        3'b11   : out = shift_register[32:22] ;
        default : out = shift_register[43:33] ;
    endcase
end
//*************code***********//
endmodule

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]

信号示意图:

波形示意图:

输入描述:

        输入信号   d, clk, rst
        类型 wire
        在testbench中,clk为周期5ns的时钟,rst为低电平复位

输出描述

        输出信号 validout    out
        类型  reg 

(2)代码

`timescale 1ns/1ns

module data_cal(
input clk,
input rst,
input [15:0]d,
input [1:0]sel,

output [4:0]out,
output validout
);
//*************code***********//
reg [15 : 0] d_real         ;
reg [4  : 0] out_ff         ;

always @(posedge clk or negedge rst) begin
    if(!rst)
        d_real <= 16'd0 ;
    else if(sel == 2'd0)
        d_real <= d ;
end

always @(*) begin
    case(sel)
        2'd0    : out_ff = 5'h0 ;
        2'd1    : out_ff = {1'b0, d_real[3:0]} + {1'b0, d_real[7 : 4]} ;
        2'd2    : out_ff = {1'b0, d_real[3:0]} + {1'b0, d_real[11: 8]} ;
        default : out_ff = {1'b0, d_real[3:0]} + {1'b0, d_real[15:12]} ;
    endcase
end

assign out = out_ff ;
assign validout = (sel == 2'd0) ? 1'b0 : 1'b1;
//*************code***********//
endmodule

VL6:多功能数据处理器

(1)描述

题目描述:

        根据指示信号select的不同,对输入信号a,b实现不同的运算。输入信号a,b为8bit有符号数,当select信号为0,输出a;当select信号为1,输出b;当select信号为2,输出a+b;当select信号为3,输出a-b.

信号示意图:

​​​​​​​

 输入描述:

        clk:系统时钟

        rst_n:复位信号,低电平有效

        a,b:8bit位宽的有符号数

        select:2bit位宽的无符号数

输出描述

        c:9bit位宽的有符号数

(2)代码

`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
);

wire [8:0] a_ext ;
wire [8:0] b_ext ;

assign a_ext = {a[7], a[7:0]} ;
assign b_ext = {b[7], b[7:0]} ;

always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		c <= 9'h0 ;
	else begin
		case(select)
			2'd0    : c <= a_ext 	 	 ;
			2'd1    : c <= b_ext 		 ;
			2'd2    : c <= a_ext + b_ext ;
			default : c <= a_ext - b_ext ;
		endcase
	end
end

endmodule

VL7:求两个数的差值

(1)描述

题目描述:

        根据输入信号a,b的大小关系,求解两个数的差值:输入信号a,b为8bit位宽的无符号数。如果a>b,则输出a-b,如果a≤b,则输出b-a。

信号示意图:

​​​​​​​

 输入描述:

        clk:系统时钟

        rst_n:复位信号,低电平有效

        a,b:8bit位宽的无符号数

输出描述

        c:8bit位宽的无符号数

(2)代码

`timescale 1ns/1ns
module data_minus(
	input clk,
	input rst_n,
	input [7:0]a,
	input [7:0]b,

	output  reg [8:0]c
);

wire [8:0] a_ext ;
wire [8:0] b_ext ;

assign a_ext = { 1'b0, a[7:0] } ;
assign b_ext = { 1'b0, b[7:0] } ;

always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		c <= 9'h0 ;
	else begin
		if(a_ext > b_ext)
			c <= a_ext - b_ext ;
		else
			c <= b_ext - a_ext ;
	end
end

endmodule

VL8:使用generate...for语句简化代码

(1)描述

题目描述:

        在某个module中包含了很多相似的连续赋值语句,请使用generata…for语句编写代码,替代该语句,要求不能改变原module的功能。
使用Verilog HDL实现以上功能并编写testbench验证。

        module template_module( 
            input [7:0] data_in,
            output [7:0] data_out
        );
            assign data_out [0] = data_in [7];
            assign data_out [1] = data_in [6];
            assign data_out [2] = data_in [5];
            assign data_out [3] = data_in [4];
            assign data_out [4] = data_in [3];
            assign data_out [5] = data_in [2];
            assign data_out [6] = data_in [1];
            assign data_out [7] = data_in [0];
    
        endmodule

输入描述:

        data_in:8bit位宽的无符号数

输出描述

        data_out:8bit位宽的无符号数

(2)代码

`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 : gen_data
        assign data_out[i] = data_in[7-i];
    end
endgenerate

endmodule

VL9:使用子模块实现三输入数的大小比较

(1)描述

题目描述:

        在数字芯片设计中,通常把完成特定功能且相对独立的代码编写成子模块,在需要的时候再在主模块中例化使用,以提高代码的可复用性和设计的层次性,方便后续的修改。

        请编写一个子模块,将输入两个8bit位宽的变量data_a,data_b,并输出data_a,data_b之中较小的数。并在主模块中例化,实现输出三个8bit输入信号的最小值的功能。

子模块的信号接口图如下:

 主模块的信号接口图如下:

 

输入描述:

        clk:系统时钟

        rst_n:异步复位信号,低电平有效

        a,b,c:8bit位宽的无符号数

输出描述

        d:8bit位宽的无符号数,表示a,b,c中的最小值

(2)代码

`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 ;
reg  [7:0] c_d1   ;

always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		c_d1 <= 8'h0 ;
	else
		c_d1 <= c    ;
end

sub_mod u_sub_mod0(
	//Input
	.clk	(clk   ) ,
	.rst_n	(rst_n ) ,
	.a		(a	   ) ,
	.b		(b 	   ) ,
	//Output
	.c		(min_ab)
);


sub_mod u_sub_mod1(
	//Input
	.clk	(clk   ) ,
	.rst_n	(rst_n ) ,
	.a		(min_ab) ,
	.b		(c_d1  ) ,
	//Output
	.c		(d     )
);

endmodule

module sub_mod(
	input clk,
	input rst_n,
	input [7:0]a,
	input [7:0]b,

	output [7:0]c
);

reg [7:0] c_ff ;

always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		c_ff <= 8'h0 ;
	else begin
		if(a <= b)
			c_ff <= a ;
		else
			c_ff <= b ;
	end
end

assign c = c_ff ;

endmodule

VL10:使用函数实现数据大小端转换

(1)描述

题目描述:

        在数字芯片设计中,经常把实现特定功能的模块编写成函数,在需要的时候再在主模块中调用,以提高代码的复用性和提高设计的层次,分别后续的修改。

        请用函数实现一个4bit数据大小端转换的功能。实现对两个不同的输入分别转换并输出。

信号示意图:

​​​​​​​

 输入描述:

        clk:系统时钟

        rst_n:异步复位信号,低电平有效

        a,b:4bit位宽的无符号数

输出描述

        c,d:8bit位宽的无符号数

(2)代码

`timescale 1ns/1ns
module function_mod(
	input [3:0]a,
	input [3:0]b,
	
	output [3:0]c,
	output [3:0]d
);

function [3:0] little_big_endian_converter;
	input [3:0] in ;

	begin
		little_big_endian_converter[0] = in[3] ;
		little_big_endian_converter[1] = in[2] ;
		little_big_endian_converter[2] = in[1] ;
		little_big_endian_converter[3] = in[0] ;
	end
endfunction

assign c = little_big_endian_converter(a) ;
assign d = little_big_endian_converter(b) ;

endmodule

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值