牛客网verilog题解(快速入门—基础语法)

VL1 四选一多路器
入门题,但要注意波形图的才是正确的对应关系

`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_1;
always@(*)  begin
    case(sel)
        2'b00 : mux_out_1 = d3;
        2'b01 : mux_out_1 = d2;
        2'b10 : mux_out_1 = d1;
        2'b11 : mux_out_1 = d0;
    endcase
end
assign mux_out = mux_out_1;

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

VL2 异步复位的串联T触发器
t触发器:输入为1信号反转,输入为0信号不变
异步复位:always @ (posedge clk or negedge rst_n) begin在复位信号rst_n的下降沿有效

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

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

VL3 奇偶校验
奇校验:数据和校验位中“1”的个数总和位奇数个
^a[x:y]:相当于a[x] ^ a[x-1] ^ a[x-2] ^ … ^ a[y],得到的值用于奇效验

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

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

题解看到一个小天才是这么做的

assign check = sel?(bus[0]+bus[1]+bus[2]+bus[3]+bus[4]+bus[5]+bus[6]+bus[7]+bus[8]+bus[9]+
                        bus[10]+bus[11]+bus[12]+bus[13]+bus[14]+bus[15]+bus[16]+bus[17]+bus[18]+
                        bus[19]+bus[20]+bus[21]+bus[22]+bus[23]+bus[24]+bus[25]+bus[26]+bus[27]+
                        bus[28]+bus[29]+bus[30]+bus[31]):(bus[0]+bus[1]+bus[2]+bus[3]+bus[4]+bus[5]+bus[6]+bus[7]+bus[8]+bus[9]+
                        bus[10]+bus[11]+bus[12]+bus[13]+bus[14]+bus[15]+bus[16]+bus[17]+bus[18]+
                        bus[19]+bus[20]+bus[21]+bus[22]+bus[23]+bus[24]+bus[25]+bus[26]+bus[27]+
                                                          bus[28]+bus[29]+bus[30]+bus[31]+1'b1);

大哥抽华子
VL4 移位运算与乘法
一个整数每次执行移位运算中的左运算n次(a << n),相当于这个整数乘以2的n次方;
一个整数每次执行移位运算中的右运算n次(a >> n),相当于这个整数除以2的n次方;

`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] cnt;
    reg [7:0] d_1;
    always@(posedge clk or negedge rst) begin
        if(!rst) begin
            cnt <= 0;
            out <= 0;
            input_grant <= 0;
            d_1 <= 0;
        end
        else begin
            cnt <= cnt+1;
            case(cnt)
                0 : begin
                    d_1 <= d;
                    input_grant <= 1;
                    out <= d;
                    end
                1 : begin
                    input_grant <=0;
                    out <= (d_1<<2)-d_1;
                    end
                2 : begin
                    input_grant <=0;
                    out <= (d_1<<3)-d_1;
                    end
                3 : begin
                    input_grant <=0;
                    out <= (d_1<<3);
                    end
            endcase
        end
    end

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

VL5 位拆分与运算
状态机,前面一道题的低配版,这道题教会了我原来//✳✳code✳✳//以外的部分原来是可以改的(把out和sel改为reg可以省很多事ovo)

`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
);
//*************code***********//
    reg [15:0] d_1;  
    always@(posedge clk or negedge rst) begin
        if(!rst)  begin
            validout <= 0;
            out <= 0;
        end
        else begin
            case(sel)
                0 : begin
                    validout <= 0;
                    d_1 <= d;
                    out <= 0;
                end
                1 : begin
                    validout <= 1;
                    out <= d_1[3:0] + d_1[7:4];
                end
                2 : begin
                    validout <= 1;
                    out <= d_1[3:0] + d_1[11:8];
                end
                3 : begin
                    validout <= 1;
                    out <= d_1[3:0] + d_1[15:12];
                end
            endcase
        end
    end
//*************code***********//
endmodule

VL6 多功能数据处理器
不能一遍过的可以自裁了罢(无慈悲

`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)
        c <= 0;
    else begin
        case(select)
            0 : c <= a;
            1 : c <= b;
            2 : c <= (a+b);
            3 : c <= (a-b);
        endcase
    end
end
endmodule

我自裁罢(悲
牛客网verilog题解(快速入门—基础语法)_第1张图片

VL7 求两个数的差值

`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)
            c <= 0;
        else c = (a>b) ? (a-b) : (b-a);
    end
endmodule

VL8 使用generate…for语句简化代码
generate讲解
格式:genvar定义for中变量,generate接for,注意for里的begin,end不能省

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

VL9 使用子模块实现三输入数的大小比较
为什么要用三个子模块而非两个
如果报错信息是

cannot be driven by primitives or continuous assignment.

那是因为reg不应连接到模块输出,改成wire就好

`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] c_1; //a,b中最小
    wire [7:0] c_2; //a,c中最小
    
    min_ab U1(
        .clk(clk),
        .rst_n(rst_n),
        .aa(a),
        .bb(b),
        .cc(c_1)
    );
    
    min_ab U2(
        .clk(clk),
        .rst_n(rst_n),
        .aa(a),
        .bb(c),
        .cc(c_2)
    );
    
    min_ab U3(
        .clk(clk),
        .rst_n(rst_n),
        .aa(c_1),
        .bb(c_2),
        .cc(d)
    );
endmodule
    
module min_ab(
    input clk,
    input rst_n,
    input [7:0] aa,
    input [7:0] bb,
        
    output reg [7:0] cc   
    );
        always@(posedge clk or negedge rst_n) begin
            if(!rst_n)
                cc <= 0;
            else if(aa > bb)
                cc <= bb;
            else 
                cc <= aa;
        end
endmodule

VL10 使用函数实现数据大小端转换
大小端转换就是把正着写的数字倒过来写
函数function声明模板如下

function [range-1] function_name;
   input_declaration
   other_declarations
   procedural_statement
endfunction

一边没过大概率是因为声明没写clk和rst_n,也不知道为啥要写,牛客命题者出来挨打

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

    assign c = dinzheng(a);
    assign d = dinzheng(b);
    
    function [3:0] dinzheng;
        input  [3:0] yiyan;
        begin
            dinzheng[0] = yiyan[3];
            dinzheng[1] = yiyan[2];
            dinzheng[2] = yiyan[1];
            dinzheng[3] = yiyan[0];
        end
    endfunction

endmodule

你可能感兴趣的:(fpga开发)