解法一 三目运算符
使用assign连续赋值语句 + 三目运算符 ? :
- `timescale 1ns/1ns
-
- module mux4_1(
- input [1:0]d1,d2,d3,d0,
- input [1:0]sel,
- output [1:0]mux_out
- );
- //*************code***********//
-
- assign mux_out = (sel == 2'b00) ? d3 : ((sel == 2'b01) ? d2 : (sel == 2'b10) ? d1 : d0);
-
- //*************code***********//
- endmodule
解法二 case语句
使用always过程赋值语句 + case语句
- `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_reg;
- always @ (*)
- begin
- case(sel)
- 2'b00:mux_out_reg = d3;
- 2'b01:mux_out_reg = d2;
- 2'b10:mux_out_reg = d1;
- 2'b11:mux_out_reg = d0;
- default : mux_out_reg = d0;
- endcase
- end
-
- assign mux_out = mux_out_reg;
-
- //*************code***********//
- endmodule
相关扩展
题解 | Verilog刷题解析及对应笔试面试注意点【1-5】(涉及复位、有符号数问题等)
注意 T 触发器的概念,来 1 翻转,来 0 保持。
注意理解同步复位和异步复位。联发科数字IC简答题(9)——异步复位同步释放问题
- `timescale 1ns/1ns
-
- module Tff_2 (
- input wire data, clk, rst,
- output reg q
- );
-
- // 1. 复位
- //2. T触发器,D触发器
- //*************code***********//
- reg q1;
- always @ (posedge clk or negedge rst)
- begin
- if(!rst) begin
- q1 <= 1'b0;
- end
- else begin
- if( data )
- q1 <= ~q1;
- else
- q1 <= q1;
- end
- end
-
- always @ (posedge clk or negedge rst)
- begin
- if(!rst) begin
- q <= 1'b0;
- end
- else begin
- if( q1 )
- q <= ~q;
- else
- q <= q;
- end
- end
-
- //*************code***********//
- endmodule
实际上这里做的是奇偶检测,如果是奇数个 1 则结果为 1,使用单目运算符 ^ 即可。
- `timescale 1ns/1ns
-
- module odd_sel(
- input [31:0] bus,
- input sel,
- output check
- );
- //*************code***********//
- wire check_tmp;
-
- // 单目运算符
- assign check_tmp = ^bus;
- // assign check = (sel == 1'b1) ? check_tmp : ~check_tmp;
-
- reg check_reg;
- always @ (*) begin
- if(sel) begin
- check_reg = check_tmp;
- end
- else begin
- check_reg = ~check_tmp;
- end
- end
-
- assign check = check_reg;
-
- //*************code***********//
- endmodule
FSM 有限状态机思想,计数值就是状态。 注意在第一次获得数据的时候进行暂存。
- `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] count; // 0 1 2 3
- always @ (posedge clk or negedge rst)
- begin
- if(~rst) begin
- count <= 2'b0;
- end
- else begin
- count <= count + 1'b1;
- end
- end
-
- // FSM 有限状态机思想,计数值就是状态
- reg [7:0] d_reg;
- always @ (posedge clk or negedge rst)
- begin
- if(~rst) begin
- out <= 11'b0;
- input_grant <= 1'b0;
- d_reg <= 8'b0;
- end
- else begin
- case( count )
- 2'b00 : begin
- out <= d;
- d_reg <= d;
- input_grant <= 1'b1;
- end
- 2'b01 : begin
- out <= d_reg + {d_reg, 1'b0}; // *1 + *2
- input_grant <= 1'b0;
- end
- 2'b10 : begin
- out <= d_reg + {d_reg, 1'b0} + {d_reg, 2'b0};
- input_grant <= 1'b0;
- end
- 2'b11 : begin
- out <= {d_reg, 3'b0};
- input_grant <= 1'b0;
- end
- default : begin
- out <= d;
- input_grant <= 1'b0;
- end
- endcase
- end
- end
- //*************code***********//
- endmodule
- `timescale 1ns/1ns
-
- module data_cal(
- input clk,
- input rst,
- input [15:0]d,
- input [1:0]sel,
- output [4:0]out, // wire
- output validout // wire
- );
- //*************code***********//
- reg [15:0] d_reg;
- wire [3:0] d0;
- wire [3:0] d1;
- wire [3:0] d2;
- wire [3:0] d3;
- assign d0 = d_reg[3:0];
- assign d1 = d_reg[7:4];
- assign d2 = d_reg[11:8];
- assign d3 = d_reg[15:12];
-
- reg [4:0] out_reg;
- reg validout_reg;
- always @ (posedge clk or negedge rst)
- begin
- if( ~rst ) begin
- out_reg <= 5'b0;
- validout_reg <= 1'b0;
- d_reg <= 16'b0;
- end
- else begin
- case( sel )
- 2'b00 : begin
- d_reg <= d;
- out_reg <= 5'b0;
- validout_reg <= 1'b0;
- end
- 2'b01 : begin
- d_reg <= d_reg;
- out_reg <= d_reg[3:0] + d_reg[7:4];// d0 + d1;
- validout_reg <= 1'b1;
- end
- 2'b10 : begin
- d_reg <= d_reg;
- out_reg <= d0 + d2;
- validout_reg <= 1'b1;
- end
- 2'b11 : begin
- d_reg <= d_reg;
- out_reg <= d0 + d3;
- validout_reg <= 1'b1;
- end
- default : begin
- out_reg <= 5'b0;
- validout_reg <= 1'b0;
- end
- endcase
- end
- end
-
- assign out = out_reg;
- assign validout = validout_reg;
-
- //*************code***********//
- endmodule
题解 | Verilog刷题解析及对应笔试面试注意点【6-9】(涉及==和===、for展开问题等)
- `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'b0;
- end
- else begin
- case ( select )
- 2'b00 : begin
- c <= {a[7], a};
- end
- 2'b01 : begin
- c <= {b[7], b};
- end
- 2'b10 : begin
- c <= {a[7], a} + {b[7], b};
- end
- 2'b11 : begin
- c <= {a[7], a} - {b[7], b};
- end
- default : begin
- c <= 9'b0;
- end
- endcase
- end
- end
-
- endmodule
- `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 ) begin
- c <= 8'b0;
- end
- else begin
- if( a > b ) begin
- c <= a - b;
- end
- else begin
- c <= b - a;
- end
- end
- end
-
- endmodule
分别给出generate...for和for的代码,可以对比不同点。
使用generate...for
- `timescale 1ns/1ns
-
- module gen_for_module(
- input [7:0] data_in,
- output [7:0] data_out
- );
-
- // 1. 必须使用 genvar 声明循环变量
- // begin后面必须起个名字
- genvar ii;
- generate for(ii = 0; ii < 8; ii = ii+1)
- begin : aaa_i
- assign data_out[ii] = data_in[7-ii];
- end
- endgenerate
-
- endmodule
使用for
- `timescale 1ns/1ns
-
- module gen_for_module(
- input [7:0] data_in,
- output [7:0] data_out
- );
-
- // 2. for
- integer i;
- reg [7:0] dout_reg;
- always @ (*) begin
- for(i = 0; i < 8; i = i+1) begin
- dout_reg[i] = data_in[7-i];
- end
- end
-
- assign data_out = dout_reg;
- endmodule
解法一 使用时序逻辑子模块
需要调用3个模块,这里很多同学可能疑惑为什么用3个而不是2个。
第一个模块:比较 T 时刻的 a 和 b,T+1 时刻出来 tmp1; 第二个模块:比较 T 时刻的 a 和 c,T+1 时刻出来 tmp2; 第三个模块:比较 T+1 时刻的 tmp1 和 tmp2,T+2 时刻出来 d;
如果只用2个子模块,那么 T 时刻比较 a 和 b 得到 tmp1,再比较 tmp1 和 c 的时候是 T+1 时刻的 c 和 T+1 时刻的 tmp1,而 tmp1 代表的是 T 时刻 a 和 b 的较小值,所以这时候比较的 T 时刻的 a、b 和 T+1 时刻的 c,显然不符合要求。
- `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
- );
-
- // T 时刻的 a 和 b,T+1 时刻出来 tmp1
- wire [7:0] tmp1; // a b 的最小值
- child_mod U0(
- .clk ( clk ),
- .rst_n ( rst_n ),
- .a ( a ),
- .b ( b ),
- .d ( tmp1 )
- );
-
- // T 时刻的 a 和 c,T+1 时刻出来 tmp2
- wire [7:0] tmp2; // a c 的最小值
- child_mod U1(
- .clk ( clk ),
- .rst_n ( rst_n ),
- .a ( a ),
- .b ( c ),
- .d ( tmp2 )
- );
-
- // T+1 时刻的 tmp1 和 tmp2,T+2 时刻出来 d
- child_mod U2(
- .clk ( clk ),
- .rst_n ( rst_n ),
- .a ( tmp1 ),
- .b ( tmp2 ),
- .d ( d )
- );
-
- endmodule
-
- // 子模块
- module child_mod(
- input clk,
- input rst_n,
- input [7:0]a,
- input [7:0]b,
- output [7:0]d
- );
-
- reg [7:0] d_reg;
- always @ (posedge clk or negedge rst_n)
- begin
- if( ~rst_n ) begin
- d_reg <= 8'b0;
- end
- else begin
- if( a > b )
- d_reg <= b;
- else
- d_reg <= a;
- end
- end
- assign d = d_reg;
-
- endmodule
解法二 使用组合逻辑子模块,需要打两拍
组合逻辑的子模块,就不存在时序逻辑中的延时问题,所以调用的时候用2个子模块就可以完成3个数的比较,为了符合时序波形的要求,多打一拍。
- `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] tmp1; // a b 的最小值
- child_mod U0(
- .a ( a ),
- .b ( b ),
- .d ( tmp1 )
- );
-
- wire [7:0] tmp2; // a c 的最小值
- child_mod U1(
- .a ( tmp1 ),
- .b ( c ),
- .d ( tmp2 )
- );
-
- reg [7:0] d_reg;
- reg [7:0] d_reg2;
- always @ (posedge clk or negedge rst_n)
- begin
- if( ~rst_n ) begin
- d_reg <= 8'b0;
- d_reg2 <= 8'b0;
- end
- else begin
- d_reg <= tmp2;
- d_reg2 <= d_reg;
- end
- end
-
- assign d = d_reg2;
-
- endmodule
-
- module child_mod(
- input [7:0]a,
- input [7:0]b,
- output [7:0]d
- );
-
- assign d = (a>b) ? b : a;
-
- endmodule
题解 | Verilog刷题解析【10】function和task的使用、相关笔试题
- `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
- );
-
- /*
- function <返回值的类型或范围>函数名;
- <端口说明语句>
- <变量类型说明语句>
- begin
- <语句>
- end
- endfunction
- */
- function [3:0] begin_end;
- input [3:0] data_in;
- begin
- begin_end[0] = data_in[3];
- begin_end[1] = data_in[2];
- begin_end[2] = data_in[1];
- begin_end[3] = data_in[0];
- end
- endfunction
-
- assign c = begin_end(a);
- assign d = begin_end(b);
-
- endmodule
- `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<B
- );
-
- assign Y2 = (A[3]>B[3]) | ((A[3]==B[3])&&(A[2]>B[2])) | ((A[3]==B[3])&&(A[2]==B[2])&&(A[1]>B[1])) | ((A[3]==B[3])&&(A[2]==B[2])&&(A[1]==B[1])&&(A[0]>B[0]));
- assign Y1 = (A[3]==B[3])&&(A[2]==B[2])&&(A[1]==B[1])&&(A[0]==B[0]);
- assign Y0 = (~Y2) & (~Y1);
-
- endmodule
- `timescale 1ns/1ns
-
- module lca_4(
- input [3:0] A_in ,
- input [3:0] B_in ,
- input C_1 ,
- output wire CO ,
- output wire [3:0] S
- );
-
- wire [3:0] G;
- wire [3:0] P;
-
- assign G[0] = A_in[0] & B_in[0];
- assign G[1] = A_in[1] & B_in[1];
- assign G[2] = A_in[2] & B_in[2];
- assign G[3] = A_in[3] & B_in[3];
-
- assign P[0] = A_in[0] ^ B_in[0];
- assign P[1] = A_in[1] ^ B_in[1];
- assign P[2] = A_in[2] ^ B_in[2];
- assign P[3] = A_in[3] ^ B_in[3];
-
- wire [3:0] C;
-
- assign S[0] = P[0] ^ C_1;
- assign S[1] = P[1] ^ C[0];
- assign S[2] = P[2] ^ C[1];
- assign S[3] = P[3] ^ C[2];
- assign CO = C[3];
-
- assign C[0] = G[0] | P[0]&C_1;
- assign C[1] = G[1] | P[1]&C[0];
- assign C[2] = G[2] | P[2]&C[1];
- assign C[3] = G[3] | P[3]&C[2];
-
- endmodule
13~20不建议做了,没有太大意义,这里只给出13~16的代码。
- `timescale 1ns/1ns
-
- module encoder_0(
- input [8:0] I_n ,
- output reg [3:0] Y_n
- );
-
- always @ (*)
- begin
- casex(I_n)
- 9'b1_1111_1111 : Y_n = 4'b1111;
- 9'b0_xxxx_xxxx : Y_n = 4'b0110;
- 9'b1_0xxx_xxxx : Y_n = 4'b0111;
- 9'b1_10xx_xxxx : Y_n = 4'b1000;
- 9'b1_110_xxxx : Y_n = 4'b1001;
- 9'b1_1110_xxxx : Y_n = 4'b1010;
- 9'b1_1111_0xxx : Y_n = 4'b1011;
- 9'b1_1111_10xx : Y_n = 4'b1100;
- 9'b1_1111_110x : Y_n = 4'b1101;
- 9'b1_1111_1110 : Y_n = 4'b1110;
- default : Y_n = 4'b1111;
- endcase
- end
-
- endmodule
- `timescale 1ns/1ns
-
- module encoder_0(
- input [8:0] I_n ,
- output reg [3:0] Y_n
- );
-
- always @(*)
- begin
- casex(I_n)
- 9'b111111111 : Y_n = 4'b1111;
- 9'b0xxxxxxxx : Y_n = 4'b0110;
- 9'b10xxxxxxx : Y_n = 4'b0111;
- 9'b110xxxxxx : Y_n = 4'b1000;
- 9'b1110xxxxx : Y_n = 4'b1001;
- 9'b11110xxxx : Y_n = 4'b1010;
- 9'b111110xxx : Y_n = 4'b1011;
- 9'b1111110xx : Y_n = 4'b1100;
- 9'b11111110x : Y_n = 4'b1101;
- 9'b111111110 : Y_n = 4'b1110;
- default : Y_n = 4'b1111;
- endcase
- end
-
- endmodule
- module key_encoder(
- input [9:0] S_n ,
- output wire[3:0] L ,
- output wire GS
- );
-
- wire [3:0] LL;
- encoder_0 U0(
- .I_n( S_n[9:1] ) ,
- .Y_n( LL )
- );
-
- assign L = ~LL;
- assign GS = ((LL == 4'b1111) && (S_n[0] == 1)) ? 0 : 1;
-
- endmodule
- `timescale 1ns/1ns
-
- module encoder_83(
- input [7:0] I ,
- input EI ,
- output wire [2:0] Y ,
- output wire GS ,
- output wire EO
- );
-
- reg [2:0] Y_Reg;
- reg GS_Reg;
- reg EO_Reg;
- always @ (*)
- begin
- if( EI == 1'b0 ) begin
- Y_Reg = 3'b0;
- GS_Reg = 1'b0;
- EO_Reg = 1'b0;
- end
- else begin
- casex(I)
- 8'b0000_0000 : begin
- Y_Reg = 3'b0;
- GS_Reg = 1'b0;
- EO_Reg = 1'b1;
- end
- 8'b1xxx_xxxx : begin
- Y_Reg = 3'b111;
- GS_Reg = 1'b1;
- EO_Reg = 1'b0;
- end
- 8'b01xx_xxxx : begin
- Y_Reg = 3'b110;
- GS_Reg = 1'b1;
- EO_Reg = 1'b0;
- end
- 8'b001x_xxxx : begin
- Y_Reg = 3'b101;
- GS_Reg = 1'b1;
- EO_Reg = 1'b0;
- end
- 8'b0001_xxxx : begin
- Y_Reg = 3'b100;
- GS_Reg = 1'b1;
- EO_Reg = 1'b0;
- end
- 8'b0000_1xxx : begin
- Y_Reg = 3'b011;
- GS_Reg = 1'b1;
- EO_Reg = 1'b0;
- end
- 8'b0000_01xx : begin
- Y_Reg = 3'b010;
- GS_Reg = 1'b1;
- EO_Reg = 1'b0;
- end
- 8'b0000_001x : begin
- Y_Reg = 3'b001;
- GS_Reg = 1'b1;
- EO_Reg = 1'b0;
- end
- 8'b0000_0001 : begin
- Y_Reg = 3'b000;
- GS_Reg = 1'b1;
- EO_Reg = 1'b0;
- end
- endcase
- end
- end
-
- assign Y = Y_Reg;
- assign GS = GS_Reg;
- assign EO = EO_Reg;
-
- endmodule
- `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]);
- //assign GS = EI&(| I);
-
- endmodule
-
- module encoder_164(
- input [15:0] A ,
- input EI ,
-
- output wire [3:0] L ,
- output wire GS ,
- output wire EO
- );
-
- wire [2:0] Y_1;
- wire GS_1;
- wire EO_1;
- encoder_83 U0(
- .I(A[15:8]) ,
- .EI(EI) ,
- .Y(Y_1) ,
- .GS(GS_1) ,
- .EO(EO_1)
- );
-
- wire [2:0] Y_0;
- wire GS_0;
- wire EO_0;
- encoder_83 U1(
- .I(A[7:0]) ,
- .EI(EO_1) ,
- .Y(Y_0) ,
- .GS(GS_0) ,
- .EO(EO_0)
- );
-
- assign GS = GS_1 | GS_0;
- assign EO = EO_0;
- assign L[3] = GS_1;
- assign L[2] = Y_1[2] | Y_0[2];
- assign L[1] = Y_1[1] | Y_0[1];
- assign L[0] = Y_1[0] | Y_0[0];
-
- endmodule
FSM有限状态机问题,两段式。
摩尔型:输出只与当前状态有关;
米利型;输出不仅与当前状态有关,还有当前输入有关;
- `timescale 1ns/1ns
-
- module seq_circuit(
- input A ,
- input clk ,
- input rst_n,
- output wire Y
- );
-
- reg [1:0] curr_state;
- reg [1:0] next_state;
- // one step
- always @ (posedge clk or negedge rst_n)
- begin
- if( ~rst_n ) begin
- curr_state <= 2'b00;
- next_state <= 2'b00;
- end
- else begin
- curr_state <= next_state;
- end
- end
-
- // two step
- always @ (*)
- begin
- case(curr_state)
- 2'b00 : next_state = (A == 1'b1) ? 2'b11 : 2'b01;
- 2'b01 : next_state = (A == 1'b1) ? 2'b00 : 2'b10;
- 2'b10 : next_state = (A == 1'b1) ? 2'b01 : 2'b11;
- 2'b11 : next_state = (A == 1'b1) ? 2'b10 : 2'b00;
- default : next_state = 2'b00;
- endcase
- end
-
- assign Y = (curr_state == 2'b11) ? 1 : 0;
-
- endmodule
- `timescale 1ns/1ns
-
- module seq_circuit(
- input C ,
- input clk ,
- input rst_n,
-
- output wire Y
- );
-
- reg [1:0] curr_state;
- reg [1:0] next_state;
- // one step
- always @ (posedge clk or negedge rst_n)
- begin
- if( ~rst_n ) begin
- curr_state <= 2'b00;
- next_state <= 2'b00;
- end
- else begin
- curr_state <= next_state;
- end
- end
-
- // two step
- always @ (*)
- begin
- case(curr_state)
- 2'b00 : next_state = (C == 1'b1) ? 2'b01 : 2'b00;
- 2'b01 : next_state = (C == 1'b1) ? 2'b01 : 2'b11;
- 2'b10 : next_state = (C == 1'b1) ? 2'b10 : 2'b00;
- 2'b11 : next_state = (C == 1'b1) ? 2'b10 : 2'b11;
- default : next_state = 2'b00;
- endcase
- end
-
- assign Y = ((curr_state == 2'b11) | ((curr_state == 2'b10)&&(C == 1'b1)) )? 1 : 0;
-
- endmodule
- `timescale 1ns/1ns
-
- module rom(
- input clk,
- input rst_n,
- input [7:0]addr,
- output [3:0]data
- );
-
- reg [3:0] romreg[7:0];
- integer i;
- always @ (posedge clk or negedge rst_n)
- begin
- if( ~rst_n ) begin
- romreg[0] <= 4'd0;
- romreg[1] <= 4'd2;
- romreg[2] <= 4'd4;
- romreg[3] <= 4'd6;
- romreg[4] <= 4'd8;
- romreg[5] <= 4'd10;
- romreg[6] <= 4'd12;
- romreg[7] <= 4'd14;
- end
- else begin
- // romreg[0] <= romreg[0];
- // ...
- // romreg[7] <= romreg[7];
- for(i = 0; i < 8; i = i+1) begin : rom_i
- romreg[i] <= romreg[i];
- end
- end
- end
-
- assign data = romreg[addr];
-
- endmodule
- `timescale 1ns/1ns
-
- module edge_detect(
- input clk,
- input rst_n,
- input a,
-
- output reg rise,
- output reg down
- );
-
- reg a1;
- always @ (posedge clk or negedge rst_n)
- begin
- if( ~rst_n ) begin
- a1 <= 1'b0;
- rise <= 1'b0;
- down <= 1'b0;
- end
- else begin
- a1 <= a;
- if(a & ~a1)
- rise <= 1'b1;
- else
- rise <= 1'b0;
- if(~a & a1)
- down <= 1'b1;
- else
- down <= 1'b0;
- end
- end
-
- endmodule