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
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