牛客刷题1——verilog

1. 一个16位信号in包含四个四位数[3:0]a[3:0]b[3:0]c[3:0]d,将它们顺序倒置为dcba输出,输出out

module top_module(
    input    in,
    output   out
);

assign out = {in[3:0],in[7:4],in[11:8],in[15:12]};

endmodule
module top_module(
    input    in,
    output    out
);

wire [3:0]a,b,c,d;

assign {a,b,c,d}=in;
assign out = {d,c,b,a};

endmodule

以 上写法适用于in位数较少的时候,当in位数较多时需要考虑用到generate...for语句。

当同一模块需要多次例化,或同一赋值语句需要多次执行时使用。

genvar i;

generater
    for(i=0;i<10;i=i+1)begin
        out[15-i]=in[i];
    end
endgenerate

(A)generate-for循环必须使用genvar关键字定义循环变量;
(B)generate-for循环中的内容必须使用begin-end包括起来,哪怕只有一句;
(C)generate-for循环begin后的名字不可以省略;
(D)generate-for循环同一个模块内的begin-end块名字不能一样。

module top_module(
    input   [15:0]  in,
    output  [15:0]  out
);

genvar i;
generate
    for(i=0;i<4;i=i+1)begin
        assign out[4*(3-i)+3:4*(3-i)]=in[4*i+3:4*i];
    end
endgenerate

向量的部分选择:

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

T ff:输入是1  输出取反(在上一个ff时); 输入是0,输出保持

图中是两个T FF,可以一级一级写。

module tolp_module(
    input clk,
    input rst,
    input data,

    output q
);

reg q1;

always@(posedge clk or negedge rst)
    if(!rst)
        q1 <= 1'b0;
    else 
        if(data)
            q1<=~q1;
        else 
            q1<=q1;

always@(posedge clk or negedge rst)
    if(!rst)
        q <= 1'b0;
    else 
        if(q1)
            q<=~q;
        else 
            q<=q;

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

单目运算符:

假设d=3'b100;

①e=&d   检测全为1(是否含0)

②f=^d     奇偶校验 (检测1的个数是奇数还是偶数,奇数个1 结果为1  偶数个1 结果为0)

③g=|d    检测全为0(是否含1)

使用异或就可以完成奇偶校验

module top_module(
    input [31:0] bus,
    input sel,
    input clk,
    output check
);

wire bus_tmp;
assign bus_tmp = ^bus;

assign check = sel ? bus_tmp: ~bus_tmp;

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

输入在6的时候很特殊,只持续了一个时钟周期,但是out 给6乘1、3、7、8需要四个时钟周期,说明不能利用d的实时变化去算out的实时变化,所以在第一个input_grant的时候把d寄存起来。就可以利用计数器 作为FSM,cnt=0 d*1;...cnt=1 d*3...

module top_module(
    input clk,
    input rst,
    input [7:0] d,

    output input_grant,
    output [10:0] out
);

reg [1:0] count;
always@(posedge clk or negedge rst)
    if(~rst)
        count <= 2'b0;
    else 
        count <= count;

always@(posedge clk or negedge rst)
    if(~rst)begin
        input_grant <= 1'b0;
        out<= 'd0;
        d_reg <= 'd0;
    end
    else begin
        case(count)
            2'b00:begin
                input_grant <= 1'b1;
                d_reg <= d;
                out <= d;
            end
            2'b01:begin
                input_grant <= 1'b0;
             
                out <= d_reg + {d_reg,1'b0};
            end
            2'b00:begin
                input_grant <= 1'b=;
        
                out <= d_reg + {d_reg,1'b0} + {d_reg,2'b0};
            end
            2'b00:begin
                input_grant <= 1'b0;
              
                out <= {d_reg,3'b0};
            end



    end

移位运算与乘法

移位运算符<< >>  移位可以实现乘法,和 无符号数的除法,有符号数的除法就不行了!!

<<低位补零 乘法   

>> 无符号数除法

假设d=4'b1110;(-6)

f=d>>1 = 3'b0111(6) (高位补零 错 负数成了正数)

可以使用位拼接!!!

对于乘法来说,都是在低位补零,不需要考虑符号位;

如果是有符号除法,需要在最前面补符号位

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

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

`timescale 1ns/1ns
module function_mod(
    input clk,
    input rst_n,
    
	input [3:0]a,
	input [3:0]b,
	
	output [3:0]c,
	output [3:0]d
);
    
    function [3:0] begin_end;  //输出
        input [3:0] data_in;

        begin
            begin_end[0] = data_in[3];
            begin_end[1] = data_in[2];
            begin_end[2] = data_in[1];
            begin_end[3] = data_in[0];
        end 
    
    endfunction

    assign c = begin_end(a);  //函数调用
    assign d = begin_end(b);

endmodule

在Verilog HDL中,函数的声明由关键字function开始,endfunction结束。对于函数中的语句需要用begin…end包含,即使只有一句。函数的声明模板如下:

       function [range-1:0] function_name ;

             input_declaration ;

             other_declaration ;

        begin

            procedural_statement ;
        end


        endfunction

函数只能描述组合逻辑,函数必须有一个返回值

  • 15
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值