赞
踩
// VL1 四选一多路器 // 这一题主要得知道,always块里赋值的话都得是reg型 // 不管是阻塞赋值还是非阻塞赋值 `timescale 1ns/1ns module mux4_1( input [1:0]d1,d2,d3,d0,sel, output reg [1:0]mux_out ); always @ (*)begin case(sel) 2'd0: mux_out = d3; 2'd1: mux_out = d2; 2'd2: mux_out = d1; 2'd3: mux_out = d0; endcase end endmodule
// VL2 用verilog实现两个串联的异步复位的T触发器 // 没太理解那个波形图,但是T触发器就是这种,1翻转0不变 // 学会用if else if else语句 // 然后这个题的复位还是低电平 `timescale 1ns/1ns module Tff_2 ( input data,clk,rst, output reg q ); reg q0; always @ (posedge clk or negedge rst) begin if(~rst) q0 <= 1'd0; else if(data) q0 <= ~q0; else q0 <= q0; end always @ (posedge clk or negedge rst) begin if(~rst) q <= 1'd0; else if(q0) q <= ~q; else q <= q; end endmodule
// VL3 奇偶校验(该题通过的答案是错的) // 若有奇数个1,奇校验为0,偶校验为1 // 若有偶数个1,奇校验为1,偶校验为0 // 奇校验:添加校验位后,数位中的1总数是奇数 // 偶校验:添加校验位后,数位中的1总数是偶数 // 思路位对bus按位,异或若有奇数个1则为1,那么奇校验 // 然后结合sel,sel为0是奇校验, `timescale 1ns/1ns module odd_sel( input [31:0] bus, input sel, output check ); assign check = sel ? ^bus : ~(^bus); // assign check = sel ? ~(^bus) : ^bus; // 真的正确答案 endmodule
// VL4 移位运算与乘法(稍有不规范) // 建议是分段式写always块,这里没这么做 // 关于在非阻塞赋值的右侧使用,逻辑判断/三目运算符 // 其实always块以if else判断可以不用begin end // 这题的测试文件还没写 `timescale 1ns/1ns module multi_sel( input [7:0] d, input clk,rst, output reg input_grant, output reg [10:0] out ); reg [1:0] cnt; reg [7:0] d0; always @ (posedge clk or negedge rst) if(~rst) begin out <= 11'd0; d0 <= 8'd0; cnt <= 2'd0; input_grant <= 1'd0; end else begin cnt <= cnt + 2'd1; input_grant <= (cnt==2'd0); d0 <= (cnt==2'd0) ? d : d0; case(cnt) 2'd0: out <= d; 2'd1: out <= d0 + {d0,1'd0}; 2'd2: out <= d0 + {d0,1'd0} + {d0,2'd0}; 2'd3: out <= {d0,3'd0}; endcase end endmodule
// VL5 位拆分与运算 // 和上题差不多,更简单点 `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 ); reg [15:0] d0; always @ (posedge clk or negedge rst)begin if(~rst)begin d0 <= 16'd0; out <= 5'd0; validout <= 1'd0; end else begin case(sel) 2'd0: begin d0<=d; out<=5'd0; validout<=1'd0; end 2'd1: begin out<=d0[3:0]+d0[7:4]; validout<=1'd1;end 2'd2: begin out<=d0[3:0]+d0[11:8]; validout<=1'd1;end 2'd3: begin out<=d0[3:0]+d0[15:12]; validout<=1'd1;end endcase end end endmodule
// VL6 多功能数据处理器 // 和上题差不多,更简单点 `timescale 1ns/1ns module data_select( input clk,rst_n, input signed [7:0] a,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 else begin case(select) 2'd0: c <= a; 2'd1: c <= b; 2'd2: c <= a + b; 2'd3: c <= a - b; endcase end end endmodule
// VL7 求两个数的差值 // 没啥特别,用if else if代替嵌套if else `timescale 1ns/1ns module data_minus( input clk,rst_n, input [7:0] a,b, output reg [8:0] c ); always @ (posedge clk or negedge rst_n)begin if(~rst_n) c <= 9'd0; else if(a>b) c <= a-b; else c <= b-a; end endmodule
// VL8 使用generate…for语句简化代码
// generate语法的使用,里边搭配for循环
`timescale 1ns/1ns
module gen_for_module(
input [7:0] data_in,
output [7:0] data_out
);
generate genvar i;
for(i=0;i<8;i=i+1)begin:gen
assign data_out[i]=data_in[7-i];
end
endgenerate
endmodule
// VL9 使用子模块实现三输入数的大小比较 // 使用if else if代替嵌套 if else // 新的模块例化方式(当知道模块内部信号定义顺序时可以这么写) // 关于这个题一定要要用三次比较!!!!! // 如果只用两次比较,由于并行比较,第一级输出和第二级输入不是同clk `timescale 1ns/1ns module main_mod( input clk,rst_n, input [7:0] a,b,c, output [7:0] d ); wire [7:0]i,j; slave_mod mod1(clk,rst_n,a,b,i); slave_mod mod2(clk,rst_n,a,c,j); slave_mod mod3(clk,rst_n,i,j,d); endmodule module slave_mod( input clk,rst_n, input [7:0] in_1,in_2, output reg [7:0] out ); always @ (posedge clk or negedge rst_n)begin if(~rst_n) out <= 8'd0; else if(in_1<in_2) out<=in_1; else out<=in_2; end endmodule
// VL10 使用函数实现数据的大小端转换 // 这里有复位,题目意思就是复位的时候输出的值为0 // 学习function的用法,有时间结合task语法一起学一下!!!!!! `timescale 1ns/1ns module function_mod( input clk,rst_n, input [3:0] a,b, output [3:0] c,d ); function [3:0] f1; input [3:0] d; begin f1[0]=d[3]; f1[1]=d[2]; f1[2]=d[1]; f1[3]=d[0]; end endfunction assign c = rst_n ? f1(a) : 4'd0; assign d = rst_n ? f1(b) : 4'd0; endmodule
// VL11 4位数值比较器电路 // 直接比较不就行了 `timescale 1ns/1ns module comparator_4( input [3:0] A,B, output reg Y2,Y1,Y0 ); always @(*) begin Y2=(A>B);Y1=(A==B);Y0=(A<B); end endmodule // 根据题目要求,还是要用门级电路来做 module comparator_4( input [3:0] A,B, output wire Y2,Y1,Y0 ); reg Da3,Da2,Da1,Da0,De3,De2,De1,De0; always @ (*) begin Da3=(A[3]&~B[3]);Da2=(A[2]&~B[2]);Da1=(A[1]&~B[1]);Da0=(A[0]&~B[0]); De3=~(A[3]^B[3]);De2=~(A[2]^B[2]);De1=~(A[1]^B[1]);De0=(~A[0]^B[0]); end assign Y2 = Da3 | De3&Da2 | De3&De2&Da1 | De3&De2&De1&Da0; assign Y1 = De3&De2&De1&De0; assign Y0 = ~Y2&~Y1; endmodule
// VL12 4bit超前进位加法器电路 // 用卡诺图化简,分别算出Sum和Cin // Si=Ai^Bi^Ci 、 Ci+1=AiBi+(Ai+Bi)Ci `timescale 1ns/1ns module lca_4( input [3:0] A_in,B_in, input C_1, output reg CO, output reg [3:0] S ); reg [3:0] C; always @ (*) begin C[0] = C_1; C[1] = A_in[0]&B_in[0] | (A_in[0]|B_in[0])&C[0]; C[2] = A_in[1]&B_in[1] | (A_in[1]|B_in[1])&C[1]; C[3] = A_in[2]&B_in[2] | (A_in[2]|B_in[2])&C[2]; CO = C[3]; S = A_in^B_in^C; end endmodule
// VL13 优先编码器电路1 // 使用casex语法按照给出的真值表输出对应的结果 `timescale 1ns/1ns module encoder_0( input [8:0] I_n , output reg [3:0] Y_n ); always @ (*)begin casex(I_n) 9'b0xxx_xxxx_x: Y_n = 4'b0110; 9'b10xx_xxxx_x: Y_n = 4'b0111; 9'b110x_xxxx_x: Y_n = 4'b1000; 9'b1110_xxxx_x: Y_n = 4'b1001; 9'b1111_0xxx_x: Y_n = 4'b1010; 9'b1111_10xx_x: Y_n = 4'b1011; 9'b1111_110x_x: Y_n = 4'b1100; 9'b1111_1110_x: Y_n = 4'b1101; 9'b1111_1111_0: Y_n = 4'b1110; 9'b1111_1111_1: Y_n = 4'b1111; default: Y_n = 4'b1111; endcase end endmodule
// VL14 用优先编码器①实现键盘编码电路 `timescale 1ns/1ns module encoder( input [8:0] I_n , output reg [3:0] Y_n ); // 这里都是取反, always @(*)begin casex(I_n) 9'b111111111 : Y_n = 4'b1111; // I=9'b000000000 Y=4'b0000 按键0 9'b111111110 : Y_n = 4'b1110; // I=9'b000000001 Y=4'b0001 按键1 9'b11111110x : Y_n = 4'b1101; // I=9'b00000001x Y=4'b0010 按键2 9'b1111110xx : Y_n = 4'b1100; // I=9'b0000001xx Y=4'b0011 按键3 9'b111110xxx : Y_n = 4'b1011; // I=9'b000001xxx Y=4'b0100 按键4 9'b11110xxxx : Y_n = 4'b1010; // I=9'b00001xxxx Y=4'b0101 按键5 9'b1110xxxxx : Y_n = 4'b1001; // I=9'b0001xxxxx Y=4'b0110 按键6 9'b110xxxxxx : Y_n = 4'b1000; // I=9'b001xxxxxx Y=4'b0111 按键7 9'b10xxxxxxx : Y_n = 4'b0111; // I=9'b01xxxxxxx Y=4'b1000 按键8 9'b0xxxxxxxx : Y_n = 4'b0110; // I=9'b1xxxxxxxx Y=4'b1001 按键9 default : Y_n = 4'b1111; // I=9'bxxxxxxxxx Y=4'b0000 按键× endcase end endmodule // 这题怪就怪在输入的S_n有10位,意思就是把S_n[0]作为判断依据 // 从状态栏可见:S_n全为1时,L_n也全1,表示按键0按下 // 然后关于GS的状态,通过的答案是认为GS=1,代表没按键按下 // 这个也好理解,没按键按下只有一种情况,方便判断,拉高说明空闲了 // 意思就是当Y全为零,同时输入也全为零时,认为按键0,GS=0 // 意思就是当Y全为零,但是输入没有时,认为按键没按下,GS=1 module key_encoder( input [9:0] S_n , output wire [3:0] L , output wire GS ); wire [3:0] L_n; encoder encoder(S_n[9:1],L_n); assign L = ~L_n; assign GS = ~(S_n[0]&L_n[0]&L_n[1]&L_n[2]&L_n[3]); // assign GS = ~((S_n[0]==1'd1)&(L==4'd0)); endmodule
// VL15 优先编码器Ⅰ // 没啥特别的,根据真值表来编 `timescale 1ns/1ns module encoder_83( input [7:0] I , input EI , output reg [2:0] Y , output reg GS , output reg EO ); always @ (*)begin if(EI) casex(I) 8'b0000_0000: begin Y = 3'b000; GS = 1'b0; EO = 1'b1; end 8'b0000_0001: begin Y = 3'b000; GS = 1'b1; EO = 1'b0; end// 1 8'b0000_001x: begin Y = 3'b001; GS = 1'b1; EO = 1'b0; end// 2 8'b0000_01xx: begin Y = 3'b010; GS = 1'b1; EO = 1'b0; end// 3 8'b0000_1xxx: begin Y = 3'b011; GS = 1'b1; EO = 1'b0; end// 4 8'b0001_xxxx: begin Y = 3'b100; GS = 1'b1; EO = 1'b0; end// 5 8'b001x_xxxx: begin Y = 3'b101; GS = 1'b1; EO = 1'b0; end// 6 8'b01xx_xxxx: begin Y = 3'b110; GS = 1'b1; EO = 1'b0; end// 7 8'b1xxx_xxxx: begin Y = 3'b111; GS = 1'b1; EO = 1'b0; end// 8 default : begin Y = 3'b000; GS = 1'b0; EO = 1'b0; end endcase else begin Y = 3'b000; GS = 1'b0; EO = 1'b0; end end endmodule
// VL16 使用8线-3线优先编码器Ⅰ实现16线-4线优先编码器 // 两片级联的方式进行操作,通过对第二块的GS的值进行判断 // GS2=0:Y={0,Y1} GS=GS1 EO=EO1 // GS2=1:Y={1,Y2} GS=1 EO=0 `timescale 1ns/1ns module encoder_83( input [7:0] I , input EI , output wire [2:0] Y , output wire GS , output wire EO ); assign Y[2] = EI & (I[7] | I[6] | I[5] | I[4]); assign Y[1] = EI & (I[7] | I[6] | ~I[5]&~I[4]&I[3] | ~I[5]&~I[4]&I[2]); assign Y[0] = EI & (I[7] | ~I[6]&I[5] | ~I[6]&~I[4]&I[3] | ~I[6]&~I[4]&~I[2]&I[1]); assign EO = EI&~I[7]&~I[6]&~I[5]&~I[4]&~I[3]&~I[2]&~I[1]&~I[0]; assign GS = EI&(I[7] | I[6] | I[5] | I[4] | I[3] | I[2] | I[1] | I[0]); endmodule module encoder_164( input [15:0] A , input EI , output wire [3:0] L , output wire GS , output wire EO ); wire GS1,GS2,EO1,EO2; wire [2:0] Y1,Y2; encoder_83 encoder_1(A[7 :0],EI,Y1,GS1,EO1); encoder_83 encoder_2(A[15:8],EI,Y2,GS2,EO2); assign {L,GS,EO} = GS_2 ? {{1'b1,Y2},1'b1,1'b0} : {{1'b0,Y1},GS1,EO1}; endmodule
// VL17 用3-8译码器实现全减器 // 通过画卡诺图的方式先把全减器的逻辑表达式定下来: // D=A^B^Ci 、 Co=~AB+(~A+B)Ci; // 然后根据对应的ABC的值,查找对应的译码器输出值 module decoder_38( input E, input [2:0] A, output reg [7:0] Y ); always @(*) if(!E) Y = 8'b00000000; else if(A==3'b000) Y = 8'b00000001; else if(A==3'b001) Y = 8'b00000010; else if(A==3'b010) Y = 8'b00000100; else if(A==3'b011) Y = 8'b00001000; else if(A==3'b100) Y = 8'b00010000; else if(A==3'b101) Y = 8'b00100000; else if(A==3'b110) Y = 8'b01000000; else if(A==3'b111) Y = 8'b10000000; else Y = 8'b00000000; endmodule module decoder1( input A,B,Ci, output D,Co ); wire [7:0] Y; decoder_38 decoder_38(1'b1,{A,B,Ci},Y); assign D = Y[1]|Y[2]|Y[4]|Y[7]; assign Co = Y[1]|Y[2]|Y[3]|Y[7]; endmodule
// VL18 实现3-8译码器1 用基础门电路实现 // 根据图片来,输出由输入决定 `timescale 1ns/1ns module decoder_38( input E1_n,E2_n,E3,A0,A1,A2, output Y0_n,Y1_n,Y2_n,Y3_n,Y4_n,Y5_n,Y6_n,Y7_n ); wire E ; assign E = E3 & ~E2_n & ~E1_n; assign Y0_n = ~(E & ~A2 & ~A1 & ~A0); assign Y1_n = ~(E & ~A2 & ~A1 & A0); assign Y2_n = ~(E & ~A2 & A1 & ~A0); assign Y3_n = ~(E & ~A2 & A1 & A0); assign Y4_n = ~(E & A2 & ~A1 & ~A0); assign Y5_n = ~(E & A2 & ~A1 & A0); assign Y6_n = ~(E & A2 & A1 & ~A0); assign Y7_n = ~(E & A2 & A1 & A0); endmodule
// VL19 使用3-8译码器1实现逻辑函数 // 例化时注意顺序 // 根据逻辑表达式发现ABC=1,3,6,7时L为1,然后和对应的Y挂钩即可 `timescale 1ns/1ns module decoder_38( input E1_n,E2_n,E3,A0,A1,A2, output Y0_n,Y1_n,Y2_n,Y3_n,Y4_n,Y5_n,Y6_n,Y7_n ); wire E ; assign E = E3 & ~E2_n & ~E1_n; assign Y0_n = ~(E & ~A2 & ~A1 & ~A0); assign Y1_n = ~(E & ~A2 & ~A1 & A0); assign Y2_n = ~(E & ~A2 & A1 & ~A0); assign Y3_n = ~(E & ~A2 & A1 & A0); assign Y4_n = ~(E & A2 & ~A1 & ~A0); assign Y5_n = ~(E & A2 & ~A1 & A0); assign Y6_n = ~(E & A2 & A1 & ~A0); assign Y7_n = ~(E & A2 & A1 & A0); endmodule module decoder0( input A,B,C, output L ); wire Y0,Y1,Y2,Y3,Y4,Y5,Y6,Y7; decoder_38 decoder_38(1'b0,1'b0,1'b1,C,B,A,Y0,Y1,Y2,Y3,Y4,Y5,Y6,Y7); assign L = ~Y1 | ~Y3 | ~Y6 | ~Y7; endmodule
// VL20 数据选择器实现逻辑电路 // 这题有意思的就在于对这个选择器的理解上 // 和前面题很像,先确定逻辑表达式,然后分配到输入输出 // L = A&B | A&~C | B&C 以A C作为输入 结果作为输出 `timescale 1ns/1ns module data_sel( input S0,S1,D0,D1,D2,D3, output Y ); assign Y = ~S1 & (~S0&D0 | S0&D1) | S1&(~S0&D2 | S0&D3); endmodule module sel_exp( input A,B,C, output L ); data_sel data_sel(A,C,1'b0,1'b1,B,B,L); endmodule
// VL21 根据状态转移表实现时序电路 // 注意题目给的Y用的是wire型,是想要用组合逻辑来操作Y; // 这里就比较麻烦,直接在状态机里一起走时序不是更好 // 但这应该是和几段式状态机相关吧,一段放时序,一段放组合 // 常规方案:一开始的思路,就画出状态转移说明 `timescale 1ns/1ns module seq_circuit( input A,clk,rst_n, output Y ); reg [1:0] state; always @ (posedge clk or negedge rst_n) begin if(~rst_n) begin state <= 2'b0; end else begin case(state) 2'b00: if(A) state<=2'b11;else state<=2'b01; 2'b01: if(A) state<=2'b00;else state<=2'b10; 2'b10: if(A) state<=2'b01;else state<=2'b11; 2'b11: if(A) state<=2'b10;else state<=2'b00; endcase end end assign Y = (state==2'b11); endmodule // 方案二:题目是说用D触发器和必要逻辑门实现 // 通过画卡诺图方式化简来操作:(在下一题中比较明显) `timescale 1ns/1ns module seq_circuit( input A,clk,rst_n, output Y ); reg Q1,Q0; always @ (posedge clk or negedge rst_n) begin if(~rst_n) begin Q1 <= 1'b0; Q0 <= 1'b0; end else begin Q1 <= A^Q1^Q0; Q0 <= ~Q0; end end assign Y = Q1&Q0; endmodule
// VL22 根据状态转移图实现时序电路 // 和上面那个题一样的画卡诺图来解 `timescale 1ns/1ns module seq_circuit( input C,clk,rst_n, output Y ); reg Q1,Q0; always @ (posedge clk or negedge rst_n) begin if(~rst_n) begin Q1 <= 1'b0; Q0 <= 1'b0; end else begin Q1 <= ~C&Q0 | Q1&Q0 | C&Q1 ; Q0 <= ~C&Q0 | ~Q1&Q0 | C&~Q1; end end assign Y = Q1&Q0|C&Q1; endmodule
//VL23 ROM的简单实现 // 这一题在这边关于这个变量的申明特别有意思!! `timescale 1ns/1ns module rom( input clk,rst_n, input [7:0] addr, output wire [3:0] data ); reg [3:0] rom[7:0]; always @ (posedge clk or negedge rst_n) begin rom[0] <= 4'd0 ; rom[1] <= 4'd2 ; rom[2] <= 4'd4 ; rom[3] <= 4'd6 ; rom[4] <= 4'd8 ; rom[5] <= 4'd10; rom[6] <= 4'd12; rom[7] <= 4'd14; end assign data = rom[addr]; endmodule
// VL24 边沿检测 // 通过打一拍的方式获得delay,通过取反相与的方式找到边沿 // 不知道为啥不能直接赋值,说什么会出现不定态,很迷惑?????? `timescale 1ns/1ns module edge_detect( input clk,rst_n,a, output reg rise,down ); reg delay; always @ (posedge clk) delay <= a; always @ (posedge clk or negedge rst_n) begin if(~rst_n) begin rise <= 1'b0; down <= 1'b0; end else if(~delay&a) begin rise <= 1'b1; down <= 1'b0; end else if(~a&delay) begin rise <= 1'b0; down <= 1'b1; end else begin rise <= 1'b0; down <= 1'b0; end end endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。