


乘法:将d进行移位相加
//4、移位运算与乘法
`timescale 1ns/1ns
module multi_sel(
input [7:0]d ,
input clk,//200MHZ,5ns
input rst,
output reg input_grant,
output reg [10:0]out
);
reg [1:0] cnt_3;
always@(posedge clk or negedge rst)begin
if(!rst)begin
cnt_3 <= 2'd0;
end
else if(cnt_3 == 2'd3)begin
cnt_3 <= 2'd0;
end
else
cnt_3 <= cnt_3 + 2'd1;
end
reg [7:0] d_reg;
always@(posedge clk or negedge rst)begin
if(!rst)begin
input_grant = 1'd0;
d_reg = 8'd0;
out = 8'd0;
end
else begin
case(cnt_3)
2'd0:begin
input_grant = 1'd1;
d_reg = d;//寄存数据
out = d;
end
2'd1:begin
input_grant = 1'd0;
out = d_reg + (d_reg<<1'd1);//3
end
2'd2:begin
input_grant = 1'd0;
out = d_reg + (d_reg<<1'd1) + (d_reg<<2'd2) ;//7
end
2'd3:begin
input_grant = 1'd0;
out = (d_reg<<3'd3);//8
end
default:;
endcase
end
end
endmodule

`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_reg;
always@(posedge clk or negedge rst)begin
if(!rst)begin
out <= 5'd0;
validout <= 1'd0;
d_reg <= 16'd0;
end
else
case(sel)
2'd0: begin
validout <= 1'd0;
d_reg <= d;//锁存数据
out <= 5'd0;
end
2'd1: begin
validout <= 1'd1;
out <= d_reg[3:0] + d_reg[7:4];
end
2'd2: begin
validout <= 1'd1;
out <= d_reg[3:0] + d_reg[11:8];
end
2'd3: begin
validout <= 1'd1;
out <= d_reg[3:0] + d_reg[15:12];
end
default:;
endcase
end
//*************code***********//
endmodule

根据指示信号select的不同,对输入信号a,b实现不同的运算。输入信号a、b为8bit有符号数,
当select[1;0] =0,输出a;
当select[1;0] =1,输出b;
当select[1;0] =2,输出a+b;
当select[1;0] =3,输出a-b。
因为输入输出都已经直接定义了signed有符号数类型,所以直接相加、相减也没有问题,不会出现运算错误。
有符号数+有符号数=有符号数,但是如果表达式中有一个无符号数,则所有的操作数都会被强行转换为无符号数
两种解决方法:
(1)涉及到有符号数运算时,和有符号相关的输入、输出、中间变量均定义成signed有符号数,这样全部遵循有符号数运算规则;
(2)用位拼接符补齐符号位;
// VL6 多功能数据处理器
// 1.有符号数的减法运算
// 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 )begin
c <= 9'd0;
end
case(select)
2'd0: c <= a;
2'd1: c <= b;
2'd2: c <= a + b;
2'd3: c <= a - b;
default:;
endcase
end
endmodule
作用上:
和for是一样的;
区别:
(1)generate for的循环变量必须用genvar声明,for的变量可以用reg、integer整数等多种类型声明;
(2)for只能用在always块里面,generate for可以做assign赋值,用always块话always写在generate for里;
(3)generate for后面必须给这个循环起一个名字,for不需要;
(4)generate for还可以用于例化模块
格式:
genvar i;
generate
for(i=0;表达式2;表达式3)
begin :起个名字
…;
end
endgenerate
// VL8 使用generate…for语句简化代码
`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: myloop
assign data_out[i] = data_in[7-i];
end
endgenerate
endmodule
等价于
因此for循环里的语句也是并行的
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

`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
);
wir [7:0] min_ab;
wir [7:0] min_ac;
wir [7:0] min_abc;
sub_mod sub_mod_inst_01(
.clk(clk),
.rst_n(rst_n),
.a(a),
.b(b),
.d(min_ab)
);
sub_mod sub_mod_inst_02(
.clk(clk),
.rst_n(rst_n),
.a(a),
.b(c),
.d(min_ac)
);
sub_mod sub_mod_inst_03(
.clk(clk),
.rst_n(rst_n),
.a(min_ab),
.b(min_ac),
.d(min_abc)
);
assign d = min_abc;
endmodule
//子模块
module sub_mod(
input clk,
input rst_n,
input [7:0]a,
input [7:0]b,
output reg[7:0]d
);
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
d <= 8'd0;
end
else if(a>b)begin
d <= b;
end
else if(a<b)
d <= a;
else
d <= d;
end
endmodule
function笔记
实现向量位转换
HDLBits类似题
`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 = rst_n ? change_bit(a) : 1'd0;
assign d = rst_n ? change_bit(b) : 1'd0;
function [3:0]change_bit;
input [3:0]data_in;
integer i;
for (i = 0; i < 4 ; i=i+1)
begin: myloop
change_bit[i] = data_in[3-i];
end
endfunction
endmodule
题目中规定了要用门级描述:参考答案

首先根据真值表写出表达式
然后画出对应的电路图

最后可以用Verilog描述出上面的电路

// VL11 4位数值比较器电路
`timescale 1ns/1ns
module comparator_4(
input [3:0] A ,
input [3:0] B ,
output wire Y2 , //A>B
output wire Y1 , //A=B
output wire Y0 //A
);
// 方法一:使用比较大小的方法,虽然能运行出来,但是题目要求是欧诺个门级描述
// 因此最好不适用比较大小的方法
/* assign Y2 = ((A[3]>B[3])||(A[2]>B[2])||((A[1]>B[1]) && (A[2]==B[2]) && (A[3]==B[3]))||((A[0]>B[0])&&(A[2]==B[2])&&(A[1]==B[1]) && (A[3]==B[3])))?1'd1:1'd0;
assign Y0 = ((A[3]
//方法二
not iv0(iv0_o, B[0]),
iv1(iv1_o, B[1]),
iv2(iv2_o, B[2]),
iv3(iv3_o, B[3]),
iv4(iv4_o, A[0]),
iv5(iv5_o, A[1]),
iv6(iv6_o, A[2]),
iv7(iv7_o, A[3]);
and ad0(
, iv0_o, A[0]),
ad1(ad1_o, iv1_o, A[1]),
ad2(ad2_o, iv2_o, A[2]),
ad3(ad3_o, iv3_o, A[3]),
ad4(ad4_o, ad0_o, xnr0_o, xnr1_o, xnr2_o),
ad5(ad5_o, ad1_o, xnr1_o, xnr2_o),
ad6(ad6_o, ad2_o, xnr2_o),
ad7(ad7_o, iv4_o, B[0]),
ad8(ad8_o, iv5_o, B[1]),
ad9(ad9_o, iv6_o, B[2]),
ad10(ad10_o, iv7_o, B[3]),
ad11(ad11_o, ad7_o, xnr0_o, xnr1_o, xnr2_o),
ad12(ad12_o, ad8_o, xnr1_o, xnr2_o),
ad13(ad13_o, ad9_o, xnr2_o),
ad14(Y1, xnr2_o, xnr1_o, xnr0_o, xnr3_o);
xnor xnr0(xnr0_o, A[1], B[1]),
xnr1(xnr1_o, A[2], B[2]),
xnr2(xnr2_o, A[3], B[3]),
xnr3(xnr3_o, A[0], B[0]);
or or0(Y2, ad3_o, ad6_o, ad5_o, ad4_o),
or1(Y0, ad10_o, ad13_o, ad12_o, ad11_o) ;
endmodule