2、关于4X4交叉开关
在已有代码的基础上进行了修改
module mux44(in0,in1,in2,in3,out0,out1,out2,out3,sl0,sl1,sl2,sl3);
parameter WL = 16;
input [WL-1:0] in0,in1,in2,in3;
input sl0,sl1,sl2,sl3;
output[WL-1:0] out0,out1,out2,out3;
reg [WL-1:0] out0,out1,out2,out3;
always @ (in0 or in1 or in2 or in3 or out0 or sl0 or sl1) begin
if((sl0)&&(sl1))
out0=in3;
else
if((!sl0)&&(sl1))
out0=in2;
else
if((sl0)&&(!sl1))
out0=in1;
else
out0=in0;
end
always @ (in0 or in1 or in2 or in3 or out1 or sl1 or sl2) begin
if((sl1)&&(sl2))
out1=in3;
else
if((!sl1)&&(sl2))
out1=in2;
else
if((sl1)&&(!sl2))
out1=in1;
else
out1=in0;
end
always @ (in0 or in1 or in2 or in3 or out2 or sl2 or sl3) begin
if((sl2)&&(sl3))
out2=in3;
else
if((!sl2)&&(sl3))
out2=in2;
else
if((sl2)&&(!sl3))
out2=in1;
else
out2=in0;
end
always @ (in0 or in1 or in2 or in3 or out3 or sl0 or sl3) begin
if((sl0)&&(sl3))
out3=in3;
else
if((!sl0)&&(sl3))
out3=in2;
else
if((sl0)&&(!sl3))
out3=in1;
else
out3=in0;
end
endmodule
下面是进行编译之后的资源消耗的显示。上图为4X4,下图是2X2的显示:
编译之后,RTL view如下图所示:
3、这题为做一个8位优先选择器,代码相对简单,如下面展示:
module YX(
IN ,
OUT );
input [7:0] IN;
output[3:0] OUT;
reg [3:0] OUT;
always @ (IN) begin
if(IN[7])
OUT = 3'b0111;
else if(IN[6])
OUT = 3'b0110;
else if(IN[5])
OUT = 3'b0101;
else if(IN[4])
OUT = 3'b0100;
else if(IN[3])
OUT = 3'b0011;
else if(IN[2])
OUT = 3'b0010;
else if(IN[1])
OUT = 3'b0001;
else if(IN[0])
OUT = 3'b0000;
else
OUT = 3'b1111;
end
endmodule
4、关于38译码器和416译码器
关于416译码器的代码的编写,也是在38译码器的基础上进行修改。
module yiima416(
IN ,
OUT );
input [3:0] IN;
output[15:0] OUT;
reg [15:0] OUT;
always @ (IN) begin
case(IN)
4'b0000: OUT = 16'b0000_0000_0000_0001;
4'b0001: OUT = 16'b0000_0000_0000_0010;
4'b0010: OUT = 16'b0000_0000_0000_0100;
4'b0011: OUT = 16'b0000_0000_0000_1000;
4'b0100: OUT = 16'b0000_0000_0001_0000;
4'b0101: OUT = 16'b0000_0000_0010_0000;
4'b0110: OUT = 16'b0000_0000_0100_0000;
4'b0111: OUT = 16'b0000_0000_1000_0000;
4'b1000: OUT = 16'b0000_0001_0000_0000;
4'b1001: OUT = 16'b0000_0010_0000_0000;
4'b1010: OUT = 16'b0000_0100_0000_0000;
4'b1011: OUT = 16'b0000_1000_0000_0000;
4'b1100: OUT = 16'b0001_0000_0000_0000;
4'b1101: OUT = 16'b0010_0000_0000_0000;
4'b1110: OUT = 16'b0100_0000_0000_0000;
4'b1111: OUT = 16'b1000_0000_0000_0000;
endcase
end
endmodule
然后进行编译,可以看到38和416的资源消耗是差一倍的。
38译码的资源消耗
416译码的资源消耗
然后可以看一下416的RTL View:
5、无符号加法器
只放一下8输入的加法器的代码图
module addunsign(
IN1 ,
IN2 ,
OUT );
input[7:0] IN1, IN2;
output[4:0] OUT;
reg[4:0] OUT;
always@(IN1 or IN2) begin
OUT = IN1 + IN2;
end
endmodule
加法器中输出改为4比特的仿真图
可以看到当输出的结果超出了输出所能表示的时候,会出现结果和想象的不一样.
输入为8位的时候的仿真图
可以 看到输出的结果的延迟是是比4输入的时候的延迟要大一些的 。
后面是有符号的加法器和流水线加法器
有符号的加法器
代码实现:
module signadd(
IN1 ,
IN2 ,
OUT );
input signed [3:0] IN1, IN2;
output signed [3:0] OUT;
reg signed [3:0] OUT;
always@(IN1 or IN2) begin
OUT = IN1 + IN2;
end
endmodule
编译完之后,进行仿真。仿真时对于数据的负数的实现,要在数据的属性里进行改变,在Radix里面改选为signed decimal,如下图所示:
然后就可以进行负数的编辑了,下面是4位输出的仿真图:
当输入改为8位的时候,再进行编译和仿真,仿真结果如下图:
再然后就是带流水线的加法器
将输入信号改为8比特位宽的,其代码实现如下
module lsxadd(
IN1 ,
IN2 ,
CLK ,
OUT );
input [7:0] IN1, IN2;
input CLK;
output [4:0] OUT;
reg [7:0] in1_d1R, in2_d1R;
reg [4:0] adder_out, OUT;
always@(posedge CLK) begin
in1_d1R <= IN1;
in2_d1R <= IN2;
OUT <= adder_out;
end
always@(in1_d1R or in2_d1R) begin
adder_out = in1_d1R + in2_d1R;
end
endmodule
然后仿真:
再添加一级流水线的情况,
代码也是在基础上改动一些:
module lsxadd(
IN1 ,
IN2 ,
CLK ,
OUT );
input [7:0] IN1, IN2;
input CLK;
output [4:0] OUT;
reg [7:0] in1_d1R, in2_d1R,in1_d2R,in2_d2R;
reg [4:0] adder_out, OUT;
always@(posedge CLK) begin
in1_d1R <= IN1;
in2_d1R <= IN2;
in1_d2R <= in1_d1R;
in2_d2R <= in2_d1R;
OUT <= adder_out;
end
always@(in1_d2R or in2_d2R) begin
adder_out = in1_d2R + in2_d2R;
end
endmodule
看RTL Viewer的情况
再之后就是仿真:
5.2 乘法器的实现
乘法器的基本实现是在加法器的基础上,将加号更换为乘号即可。
8输入输出的无流水线的乘法器的代码实现和仿真
module mul(
IN1 ,
IN2 ,
OUT );
input [7:0] IN1, IN2;
output [7:0] OUT;
reg [7:0] OUT;
always@(IN1 or IN2) begin // 生成组合逻辑的always 块
OUT = IN1 * IN2;
end
endmodule
module mul(
IN1 ,
IN2 ,
CLK ,
OUT );
input [7:0] IN1, IN2;
input CLK;
output [7:0] OUT;
reg [7:0] in1_d1R, in2_d1R;
reg [7:0] muler_out, OUT;
always@(posedge CLK) begin
in1_d1R <= IN1;
in2_d1R <= IN2;
OUT <= muler_out;
end
always@(in1_d1R or in2_d1R) begin
muler_out = in1_d1R * in2_d1R;
end
endmodule
编译之后的RTL Viewer如下图:
然后进行仿真
6、计数器
只有clk输入和OV输出的计数器,其代码如下:
module count1( clk, ov);
input clk;
output ov;
reg [3:0] cnt_next;
reg ov;
parameter CNT_MAX_VAL = 9;
always @ (posedge clk) begin
if(cnt_next < CNT_MAX_VAL) begin
ov=0;
cnt_next = cnt_next + 1'b1;
end
else begin
ov=1;
cnt_next = 0;
end
end
endmodule
仿真结果如下:
可以看到当计数到10的时候就会计1,然后接着计数
然后是相对复杂的一个计数器
module cntcom(
RST ,
CLK ,
EN ,
CLR ,
LOAD ,
DATA ,
CNTVAL,
OV );
input RST , CLK , EN , CLR , LOAD ;
input [3:0] DATA ;
output [3:0] CNTVAL;
output OV;
reg [3:0] CNTVAL, cnt_next;
reg OV;
parameter CNT_MAX_VAL = 9;
always @(EN or CLR or LOAD or DATA or CNTVAL) begin
if(CLR) begin
cnt_next = 0;
end
else begin
if(EN) begin
if(LOAD) begin
cnt_next = DATA;
end
else begin
if(CNTVAL < CNT_MAX_VAL) begin
cnt_next = CNTVAL + 1'b1;
end
else begin
cnt_next = 0;
end
end
end
else begin
cnt_next = CNTVAL;
end
end
end
always @ (posedge CLK or posedge RST) begin
if(RST)
CNTVAL <= 0;
else
CNTVAL <= cnt_next;
end
always @ (CNTVAL) begin
if(CNTVAL == CNT_MAX_VAL)
OV = 1;
else
OV = 0;
end
endmodule
7、状态机
代码如下
module yiwei(
CLK ,
EN ,
RST ,
CENT1IN ,
TINOUT );
input CLK ;
input RST ;
input CENT1IN ;
input EN ;
output TINOUT ;
parameter ST_0_CENT = 0;
parameter ST_1_CENT = 1;
parameter ST_2_CENT = 2;
parameter ST_3_CENT = 3;
parameter ST_4_CENT = 4;
reg [4-2:0]stateR ;
reg [4-2:0]next_state ;
reg TINOUT ;
always @ (CENT1IN or stateR) begin
case (stateR)
ST_0_CENT :begin if(CENT1IN) next_state = ST_1_CENT ; else next_state = ST_0_CENT; end
ST_1_CENT :begin if(CENT1IN) next_state = ST_2_CENT ; else next_state = ST_0_CENT; end
ST_2_CENT :begin if(!CENT1IN) next_state = ST_3_CENT ; else next_state = ST_0_CENT; end
ST_3_CENT :begin if(CENT1IN) next_state = ST_4_CENT ; else next_state = ST_0_CENT; end
ST_4_CENT :begin next_state = ST_0_CENT ;end
endcase
end
always @ (stateR) begin
if(EN) begin
if(stateR == ST_4_CENT)
TINOUT = 1'b1;
else
TINOUT = 1'b0;
end
end
// state DFF
always @ (posedge CLK or posedge RST)begin
if(RST)
stateR <= ST_0_CENT;
else
stateR <= next_state;
end
endmodule
上面的代码是一个带有EN使能的状态机,当遇到1011时,输出为1,否则输出就为0.
状态转移图也可以通过Tools-Netlist Viewers-State Machine Viewer 看到,如下图:
仿真结果如下:
当EN为0时,仿真没有结果
当EN为1时,仿真才可以成功捕获:
8、并入串出的移位寄存器
代码如下图所以
module crbc(
RST ,
CLK ,
EN ,
LOAD ,
IN ,
OUT );
input RST, CLK, EN, LOAD;
input [3:0]IN;
output OUT;
reg [3:0] shift_R;
reg OUT;
always @ (posedge CLK or posedge RST or posedge LOAD) begin
if(RST)
shift_R[3:0] <= 0;
else begin
if(LOAD) begin
shift_R[3:0] <= IN[3:0];
end
else begin
if(EN) begin
OUT = shift_R[3];
shift_R[3:1] <= shift_R[2:0];
shift_R[0] <= 0;
end
else begin
shift_R[3:0] <= shift_R[3:0];
end
end
end
end
endmodule