• FPGA面试题


    入门篇1~24题

    VL1 四选一多路器

    解法一 三目运算符

    使用assign连续赋值语句 + 三目运算符 ? :

    1. `timescale 1ns/1ns
    2. module mux4_1(
    3. input [1:0]d1,d2,d3,d0,
    4. input [1:0]sel,
    5. output [1:0]mux_out
    6. );
    7. //*************code***********//
    8.    
    9. assign mux_out = (sel == 2'b00) ? d3 : ((sel == 2'b01) ? d2 : (sel == 2'b10) ? d1 : d0);
    10. //*************code***********//
    11. endmodule

    解法二 case语句

    使用always过程赋值语句 + case语句

    1. `timescale 1ns/1ns
    2. module mux4_1(
    3. input [1:0]d1,d2,d3,d0,
    4. input [1:0]sel,
    5. output [1:0]mux_out
    6. );
    7. //*************code***********//
    8. reg [1:0] mux_out_reg;
    9. always @ (*)
    10. begin
    11.     case(sel)
    12.         2'b00:mux_out_reg = d3;
    13.         2'b01:mux_out_reg = d2;
    14.         2'b10:mux_out_reg = d1;
    15.         2'b11:mux_out_reg = d0;
    16.         default : mux_out_reg = d0;
    17.     endcase
    18. end 
    19.     
    20. assign mux_out = mux_out_reg;
    21. //*************code***********//
    22. endmodule

    相关扩展

    题解 | Verilog刷题解析及对应笔试面试注意点【1-5】(涉及复位、有符号数问题等)

    VL2 异步复位的串联T触发器

    注意 T 触发器的概念,来 1 翻转,来 0 保持。
    注意理解同步复位和异步复位。联发科数字IC简答题(9)——异步复位同步释放问题

    1. `timescale 1ns/1ns
    2. module Tff_2 (
    3.   input wire data, clk, rst,
    4.   output reg q  
    5. );
    6.     
    7. // 1. 复位
    8. //2. T触发器,D触发器
    9. //*************code***********//
    10. reg q1;
    11. always @ (posedge clk or negedge rst)
    12. begin
    13.     if(!rst) begin
    14.         q1 <1'b0;
    15.     end 
    16.     else begin
    17.         if( data )
    18.             q1 <= ~q1;
    19.         else 
    20.             q1 <= q1;
    21.     end 
    22. end 
    23. always @ (posedge clk or negedge rst)
    24. begin
    25.     if(!rst) begin
    26.         q <1'b0;
    27.     end 
    28.     else begin
    29.         if( q1 )
    30.             q <= ~q;
    31.         else 
    32.             q <= q;
    33.     end 
    34. end 
    35. //*************code***********//
    36. endmodule

    VL3 奇偶校验(实际上应该是奇偶检测)

    实际上这里做的是奇偶检测,如果是奇数个 1 则结果为 1,使用单目运算符 ^ 即可。

    1. `timescale 1ns/1ns
    2. module odd_sel(
    3.   input [31:0] bus,
    4.   input sel,
    5.   output check
    6. );
    7. //*************code***********//
    8. wire check_tmp;
    9.     
    10. // 单目运算符
    11. assign check_tmp = ^bus;
    12. //  assign check = (sel == 1'b1) ? check_tmp : ~check_tmp;
    13.     
    14. reg check_reg;
    15. always @ (*) begin
    16.     if(sel) begin
    17.         check_reg = check_tmp;
    18.     end
    19.     else begin
    20.         check_reg = ~check_tmp;
    21.     end 
    22. end 
    23. assign check = check_reg;
    24. //*************code***********//
    25. endmodule

    VL4 移位运算与乘法

    FSM 有限状态机思想,计数值就是状态。 注意在第一次获得数据的时候进行暂存。

    1. `timescale 1ns/1ns
    2. module multi_sel(
    3.   input [7:0]d ,
    4.   input clk,
    5.   input rst,
    6.   output reg input_grant,
    7.   output reg [10:0]out
    8. );
    9. //*************code***********//
    10. reg [1:0] count;    // 0 1 2 3
    11. always @ (posedge clk or negedge rst)
    12. begin
    13.     if(~rst) begin
    14.         count <2'b0;
    15.     end 
    16.     else begin
    17.         count <= count + 1'b1;
    18.     end 
    19. end 
    20. // FSM 有限状态机思想,计数值就是状态
    21. reg [7:0] d_reg;
    22. always @ (posedge clk or negedge rst)
    23. begin
    24.     if(~rst) begin
    25.         out <11'b0;
    26.         input_grant <= 1'b0;
    27.         d_reg <= 8'b0;
    28.     end 
    29.     else begin
    30.         case( count ) 
    31.             2'b00 : begin
    32.                 out <= d;
    33.                 d_reg <= d;
    34.                 input_grant <= 1'b1;
    35.             end 
    36.             2'b01 : begin
    37.                 out <= d_reg + {d_reg, 1'b0};    // *1 + *2
    38.                 input_grant <= 1'b0;
    39.             end 
    40.             2'b10 : begin
    41.                 out <= d_reg + {d_reg, 1'b0} + {d_reg, 2'b0};
    42.                 input_grant <= 1'b0;
    43.             end 
    44.             2'b11 : begin 
    45.                 out <= {d_reg, 3'b0};
    46.                 input_grant <= 1'b0;
    47.             end 
    48.             default : begin 
    49.                 out <= d;
    50.                 input_grant <= 1'b0;
    51.             end 
    52.         endcase
    53.     end 
    54. end 
    55. //*************code***********//
    56. endmodule

    VL5 位拆分与运算

    1. `timescale 1ns/1ns
    2. module data_cal(
    3.   input clk,
    4.   input rst,
    5.   input [15:0]d,
    6.   input [1:0]sel,
    7.   output [4:0]out, // wire
    8.   output validout // wire
    9. );
    10. //*************code***********//
    11. reg [15:0] d_reg;
    12. wire [3:0] d0;
    13. wire [3:0] d1;
    14. wire [3:0] d2;
    15. wire [3:0] d3;
    16. assign d0 = d_reg[3:0];
    17. assign d1 = d_reg[7:4];
    18. assign d2 = d_reg[11:8];
    19. assign d3 = d_reg[15:12];
    20. reg [4:0] out_reg;
    21. reg validout_reg;
    22. always @ (posedge clk or negedge rst)
    23.     begin
    24.         if( ~rst ) begin
    25.             out_reg <5'b0;
    26.             validout_reg <= 1'b0;
    27.             d_reg <= 16'b0;
    28.         end 
    29.         else begin
    30.             case( sel ) 
    31.                 2'b00 : begin
    32.                     d_reg <= d;
    33.                     out_reg <= 5'b0;
    34.                     validout_reg <= 1'b0;    
    35.                 end 
    36.                 2'b01 : begin
    37.                     d_reg <= d_reg;
    38.                     out_reg <= d_reg[3:0] + d_reg[7:4];// d0 + d1;
    39.                     validout_reg <= 1'b1;    
    40.                 end 
    41.                  2'b10 : begin
    42.                      d_reg <= d_reg;
    43.                     out_reg <= d0 + d2;
    44.                     validout_reg <= 1'b1;    
    45.                 end 
    46.                  2'b11 : begin
    47.                      d_reg <= d_reg;
    48.                     out_reg <= d0 + d3;
    49.                     validout_reg <= 1'b1;    
    50.                 end 
    51.                 default : begin
    52.                     out_reg <= 5'b0;
    53.                     validout_reg <= 1'b0;  
    54.                 end 
    55.             endcase
    56.         end 
    57.     end
    58. assign out = out_reg;
    59. assign validout = validout_reg;
    60. //*************code***********//
    61. endmodule

    VL6 多功能数据处理器

    题解 | Verilog刷题解析及对应笔试面试注意点【6-9】(涉及==和===、for展开问题等)

    1. `timescale 1ns/1ns
    2. module data_select(
    3.  input clk,
    4.  input rst_n,
    5.  input signed[7:0]a,
    6.  input signed[7:0]b,
    7.  input [1:0]select,
    8.  output reg signed [8:0]c
    9. );
    10.     
    11. always @ (posedge clk or negedge rst_n)
    12. begin
    13.     if( ~rst_n ) begin
    14.         c <9'b0;
    15.     end 
    16.     else begin
    17.         case ( select )
    18.             2'b00 : begin
    19.                 c <= {a[7], a};
    20.             end 
    21.             2'b01 : begin
    22.                 c <= {b[7], b};
    23.             end 
    24.             2'b10 : begin
    25.                 c <= {a[7], a} + {b[7], b};
    26.             end 
    27.             2'b11 : begin
    28.                 c <= {a[7], a} - {b[7], b};
    29.             end 
    30.             default : begin
    31.                 c <= 9'b0;
    32.             end 
    33.         endcase
    34.     end 
    35. end     
    36.  
    37. endmodule

    VL7 求两个数的差值

    1. `timescale 1ns/1ns
    2. module data_minus(
    3.  input clk,
    4.  input rst_n,
    5.  input [7:0]a,
    6.  input [7:0]b,
    7.  output  reg [8:0]c
    8. );
    9.     
    10. always @ (posedge clk or negedge rst_n)
    11. begin
    12.     if( ~rst_n ) begin
    13.         c <= 8'b0;
    14.     end 
    15.     else begin
    16.         if( a > b ) begin
    17.             c <= a - b;
    18.         end 
    19.         else begin
    20.             c <= b - a;
    21.         end 
    22.     end 
    23. end    
    24.     
    25. endmodule

    VL8 使用generate...for语句简化代码

    分别给出generate...for和for的代码,可以对比不同点。

    使用generate...for

    1. `timescale 1ns/1ns
    2. module gen_for_module
    3.     input [7:0] data_in,
    4.     output [7:0] data_out
    5. );
    6. // 1. 必须使用 genvar 声明循环变量
    7. // begin后面必须起个名字
    8. genvar ii;
    9. generate for(ii = 0; ii < 8; ii = ii+1) 
    10.     begin : aaa_i
    11.         assign data_out[ii] = data_in[7-ii];
    12.     end
    13. endgenerate
    14. endmodule

    使用for

    1. `timescale 1ns/1ns
    2. module gen_for_module
    3.     input [7:0] data_in,
    4.     output [7:0] data_out
    5. );
    6.     
    7. // 2. for
    8. integer i;
    9. reg [7:0] dout_reg;
    10. always @ (*) begin
    11.     for(i = 0; i < 8; i = i+1) begin 
    12.         dout_reg[i] = data_in[7-i];
    13.     end 
    14. end 
    15. assign data_out = dout_reg;
    16. endmodule

    VL9 使用子模块实现三输入数的大小比较

    解法一 使用时序逻辑子模块

    需要调用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,显然不符合要求。

    1. `timescale 1ns/1ns
    2. module main_mod(
    3.  input clk,
    4.  input rst_n,
    5.  input [7:0]a,
    6.  input [7:0]b,
    7.  input [7:0]c,
    8.  
    9.  output [7:0]d
    10. );
    11. // T 时刻的 a 和 b,T+1 时刻出来 tmp1
    12. wire [7:0] tmp1;    // a b 的最小值
    13. child_mod U0(
    14.     .clk      ( clk ),
    15.     .rst_n    ( rst_n ),
    16.     .a        ( a ),
    17.     .b        ( b ),
    18.     .d        ( tmp1 )
    19. );
    20. // T 时刻的 a 和 c,T+1 时刻出来 tmp2
    21. wire [7:0] tmp2;    // a c 的最小值
    22. child_mod U1(
    23.     .clk      ( clk ),
    24.     .rst_n    ( rst_n ),
    25.     .a        ( a ),
    26.     .b        ( c ),
    27.     .d        ( tmp2 )
    28. );
    29. // T+1 时刻的 tmp1 和 tmp2,T+2 时刻出来 d
    30. child_mod U2(
    31.     .clk      ( clk ),
    32.     .rst_n    ( rst_n ),
    33.     .a        ( tmp1 ),
    34.     .b        ( tmp2 ),
    35.     .d        ( d )
    36. );
    37. endmodule
    38. // 子模块
    39. module child_mod(
    40.     input clk,
    41.     input rst_n,
    42.     input [7:0]a,
    43.     input [7:0]b,
    44.     output [7:0]d
    45. );
    46. reg [7:0] d_reg;
    47. always @ (posedge clk or negedge rst_n)
    48. begin
    49.     if( ~rst_n ) begin
    50.         d_reg <8'b0;
    51.     end 
    52.     else begin
    53.         if( a > b )
    54.             d_reg <= b;
    55.         else
    56.             d_reg <= a;
    57.     end 
    58. end
    59. assign d = d_reg;
    60. endmodule

    解法二 使用组合逻辑子模块,需要打两拍

    组合逻辑的子模块,就不存在时序逻辑中的延时问题,所以调用的时候用2个子模块就可以完成3个数的比较,为了符合时序波形的要求,多打一拍。

    1. `timescale 1ns/1ns
    2. module main_mod(
    3.  input clk,
    4.  input rst_n,
    5.  input [7:0]a,
    6.  input [7:0]b,
    7.  input [7:0]c,
    8.  
    9.  output [7:0]d
    10. );
    11. wire [7:0] tmp1;    // a b 的最小值
    12. child_mod U0(
    13.     .a        ( a ),
    14.     .b        ( b ),
    15.     .d        ( tmp1 )
    16. );
    17.     
    18. wire [7:0] tmp2;    // a c 的最小值
    19. child_mod U1(
    20.     .a        ( tmp1 ),
    21.     .b        ( c ),
    22.     .d        ( tmp2 )
    23. );
    24.   
    25. reg [7:0] d_reg;
    26. reg [7:0] d_reg2;
    27. always @ (posedge clk or negedge rst_n)
    28.     begin
    29.         if( ~rst_n ) begin
    30.             d_reg <8'b0;
    31.             d_reg2 <= 8'b0;
    32.         end 
    33.         else begin
    34.             d_reg <= tmp2;
    35.             d_reg2 <= d_reg;
    36.         end 
    37.     end
    38. assign d = d_reg2;
    39.     
    40. endmodule
    41. module child_mod(
    42.     input [7:0]a,
    43.     input [7:0]b,
    44.     output [7:0]d
    45. );
    46. assign d = (a>b) ? b : a;
    47. endmodule

    VL10 使用函数实现数据大小端转换

    题解 | Verilog刷题解析【10】function和task的使用、相关笔试题

    1. `timescale 1ns/1ns
    2. module function_mod(
    3.   input clk,
    4.   input rst_n,
    5.     
    6.  input [3:0]a,
    7.  input [3:0]b,
    8.  
    9.  output [3:0]c,
    10.  output [3:0]d
    11. );
    12. /*       
    13. function <返回值的类型或范围>函数名;
    14.      <端口说明语句>
    15.      <变量类型说明语句>
    16.    begin
    17.      <语句>
    18.   end
    19. endfunction
    20. */       
    21. function [3:0] begin_end;
    22.     input [3:0] data_in;
    23.     begin
    24.         begin_end[0] = data_in[3];
    25.         begin_end[1] = data_in[2];
    26.         begin_end[2] = data_in[1];
    27.         begin_end[3] = data_in[0];
    28.     end 
    29. endfunction
    30. assign c = begin_end(a);
    31. assign d = begin_end(b);
    32. endmodule

    VL11 4位数值比较器电路

    1. `timescale 1ns/1ns
    2. module comparator_4(
    3.   input  [3:0]    A    ,
    4.   input  [3:0]    B    ,
    5.   output  wire    Y2    , //A>B
    6.   output  wire    Y1    , //A=B
    7.   output  wire    Y0      //A<B
    8. );
    9.     
    10. 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]));
    11. assign Y1 = (A[3]==B[3])&&(A[2]==B[2])&&(A[1]==B[1])&&(A[0]==B[0]);
    12. assign Y0 = (~Y2) & (~Y1);
    13.     
    14. endmodule

    VL12 4bit超前进位加法器电路

    1. `timescale 1ns/1ns
    2. module lca_4(
    3.   input  [3:0]    A_in  ,
    4.   input  [3:0]    B_in  ,
    5.   input           C_1   ,
    6.   output  wire   CO    ,
    7.   output  wire [3:0]  S
    8. );
    9.     
    10. wire [3:0] G;
    11. wire [3:0] P;
    12. assign G[0] = A_in[0] & B_in[0];
    13. assign G[1] = A_in[1] & B_in[1];
    14. assign G[2] = A_in[2] & B_in[2];
    15. assign G[3] = A_in[3] & B_in[3];
    16. assign P[0] = A_in[0] ^ B_in[0];
    17. assign P[1] = A_in[1] ^ B_in[1];
    18. assign P[2] = A_in[2] ^ B_in[2];
    19. assign P[3] = A_in[3] ^ B_in[3];
    20. wire [3:0] C;
    21. assign S[0] = P[0] ^ C_1;
    22. assign S[1] = P[1] ^ C[0];
    23. assign S[2] = P[2] ^ C[1];
    24. assign S[3] = P[3] ^ C[2];
    25. assign CO = C[3];
    26. assign C[0] = G[0] | P[0]&C_1;
    27. assign C[1] = G[1] | P[1]&C[0];
    28. assign C[2] = G[2] | P[2]&C[1];
    29. assign C[3] = G[3] | P[3]&C[2];
    30.     
    31. endmodule

    13~20不建议做了,没有太大意义,这里只给出13~16的代码。

    VL13 优先编码器电路1

    1. `timescale 1ns/1ns
    2. module encoder_0(
    3.    input      [8:0] I_n   ,   
    4.    output reg [3:0] Y_n   
    5. );
    6.       
    7. always @ (*) 
    8.   begin 
    9.     casex(I_n)
    10.       9'b1_1111_1111 : Y_n = 4'b1111;
    11.       9'b0_xxxx_xxxx : Y_n = 4'b0110;
    12.       9'b1_0xxx_xxxx : Y_n = 4'b0111;
    13.       9'b1_10xx_xxxx : Y_n = 4'b1000;
    14.       9'b1_110_xxxx : Y_n = 4'b1001;
    15.       9'b1_1110_xxxx : Y_n = 4'b1010;
    16.       9'b1_1111_0xxx : Y_n = 4'b1011;
    17.       9'b1_1111_10xx : Y_n = 4'b1100;
    18.       9'b1_1111_110x : Y_n = 4'b1101;
    19.       9'b1_1111_1110 : Y_n = 4'b1110;
    20.       default : Y_n = 4'b1111;
    21.     endcase
    22.   end 
    23.   
    24. endmodule

    VL14 用优先编码器1实现键盘编码电路

    1. `timescale 1ns/1ns
    2. module encoder_0(
    3.    input      [8:0]         I_n   ,   
    4.    output reg [3:0]         Y_n   
    5. );
    6. always @(*)
    7. begin
    8.    casex(I_n)
    9.       9'b111111111 : Y_n = 4'b1111;
    10.       9'b0xxxxxxxx : Y_n = 4'b0110;
    11.       9'b10xxxxxxx : Y_n = 4'b0111;
    12.       9'b110xxxxxx : Y_n = 4'b1000;
    13.       9'b1110xxxxx : Y_n = 4'b1001;
    14.       9'b11110xxxx : Y_n = 4'b1010;
    15.       9'b111110xxx : Y_n = 4'b1011;
    16.       9'b1111110xx : Y_n = 4'b1100;
    17.       9'b11111110x : Y_n = 4'b1101;
    18.       9'b111111110 : Y_n = 4'b1110;
    19.       default      : Y_n = 4'b1111;
    20.    endcase    
    21. end 
    22.      
    23. endmodule
    24. module key_encoder(
    25.     input      [9:0]         S_n   ,    
    26.     output wire[3:0]         L     ,
    27.     output wire              GS
    28. );
    29.     
    30. wire [3:0] LL;
    31. encoder_0  U0(
    32.    .I_n( S_n[9:1] )   ,
    33.    .Y_n( LL )   
    34. )
    35. assign L = ~LL;
    36. assign GS = ((LL == 4'b1111) && (S_n[0] == 1)) ? 0 : 1;
    37.     
    38. endmodule

    VL15 优先编码器2——8线-3线优先编码器

    1. `timescale 1ns/1ns
    2. module encoder_83(
    3.    input      [7:0]       I   ,
    4.    input                  EI  ,  
    5.    output wire [2:0]      Y   ,
    6.    output wire            GS  ,
    7.    output wire            EO    
    8. );
    9.     
    10. reg [2:0] Y_Reg;
    11. reg GS_Reg;
    12. reg EO_Reg;
    13. always @ (*) 
    14. begin 
    15.     if( EI == 1'b0 ) begin 
    16.         Y_Reg 3'b0;
    17.         GS_Reg = 1'b0;
    18.         EO_Reg = 1'b0;
    19.     end 
    20.     else begin
    21.         casex(I)
    22.             8'b0000_0000 : begin
    23.                 Y_Reg = 3'b0;
    24.                 GS_Reg = 1'b0;
    25.                 EO_Reg = 1'b1;                        
    26.             end 
    27.             8'b1xxx_xxxx : begin
    28.                 Y_Reg = 3'b111;
    29.                 GS_Reg = 1'b1;
    30.                 EO_Reg = 1'b0;                        
    31.             end
    32.             8'b01xx_xxxx : begin
    33.                 Y_Reg = 3'b110;
    34.                 GS_Reg = 1'b1;
    35.                 EO_Reg = 1'b0;                        
    36.             end
    37.             8'b001x_xxxx : begin
    38.                 Y_Reg = 3'b101;
    39.                 GS_Reg = 1'b1;
    40.                 EO_Reg = 1'b0;                        
    41.             end
    42.             8'b0001_xxxx : begin
    43.                 Y_Reg = 3'b100;
    44.                 GS_Reg = 1'b1;
    45.                 EO_Reg = 1'b0;                        
    46.             end
    47.             8'b0000_1xxx : begin
    48.                 Y_Reg = 3'b011;
    49.                 GS_Reg = 1'b1;
    50.                 EO_Reg = 1'b0;                        
    51.             end
    52.             8'b0000_01xx : begin
    53.                 Y_Reg = 3'b010;
    54.                 GS_Reg = 1'b1;
    55.                 EO_Reg = 1'b0;                        
    56.             end
    57.             8'b0000_001x : begin
    58.                 Y_Reg = 3'b001;
    59.                 GS_Reg = 1'b1;
    60.                 EO_Reg = 1'b0;                        
    61.             end
    62.             8'b0000_0001 : begin
    63.                 Y_Reg = 3'b000;
    64.                 GS_Reg = 1'b1;
    65.                 EO_Reg = 1'b0;                        
    66.             end
    67.         endcase
    68.     end 
    69. end 
    70. assign Y = Y_Reg;
    71. assign GS = GS_Reg;
    72. assign EO = EO_Reg;
    73.     
    74. endmodule

    VL16 使用8线-3线优先编码器实现16线-4线优先编码器

    1. `timescale 1ns/1ns
    2. module encoder_83(
    3.    input      [7:0]       I   ,
    4.    input                  EI  ,
    5.    
    6.    output wire [2:0]      Y   ,
    7.    output wire            GS  ,
    8.    output wire            EO    
    9. );
    10. assign Y[2] = EI & (I[7] | I[6] | I[5] | I[4]);
    11. assign Y[1] = EI & (I[7] | I[6] | ~I[5]&~I[4]&I[3] | ~I[5]&~I[4]&I[2]);
    12. assign Y[0] = EI & (I[7] | ~I[6]&I[5] | ~I[6]&~I[4]&I[3] | ~I[6]&~I[4]&~I[2]&I[1]);
    13. assign EO = EI&~I[7]&~I[6]&~I[5]&~I[4]&~I[3]&~I[2]&~I[1]&~I[0];
    14. assign GS = EI&(I[7] | I[6] | I[5] | I[4] | I[3] | I[2] | I[1] | I[0]);
    15. //assign GS = EI&(| I);
    16.          
    17. endmodule
    18. module encoder_164(
    19.    input      [15:0]      A   ,
    20.    input                  EI  ,
    21.    
    22.    output wire [3:0]      L   ,
    23.    output wire            GS  ,
    24.    output wire            EO    
    25. );
    26.    
    27. wire [2:0] Y_1;
    28. wire GS_1;
    29. wire EO_1;
    30. encoder_83 U0(
    31.    .I(A[15:8])   ,
    32.    .EI(EI)  ,
    33.    .Y(Y_1)   ,
    34.    .GS(GS_1)  ,
    35.    .EO(EO_1)    
    36. );
    37. wire [2:0] Y_0;
    38. wire GS_0;
    39. wire EO_0;
    40. encoder_83 U1(
    41.     .I(A[7:0])   ,
    42.     .EI(EO_1)  ,   
    43.     .Y(Y_0)   ,
    44.     .GS(GS_0)  ,
    45.     .EO(EO_0)    
    46. );
    47.     
    48. assign GS = GS_1 | GS_0;
    49. assign EO = EO_0;
    50. assign L[3] = GS_1;
    51. assign L[2] = Y_1[2] | Y_0[2];
    52. assign L[1] = Y_1[1] | Y_0[1];
    53. assign L[0] = Y_1[0] | Y_0[0];
    54.     
    55. endmodule

    VL17~20 不建议做

    VL21 根据状态转移表实现时序电路

    FSM有限状态机问题,两段式。

    • 摩尔型:输出只与当前状态有关;

    • 米利型;输出不仅与当前状态有关,还有当前输入有关;

    1. `timescale 1ns/1ns
    2. module seq_circuit(
    3.     input                A   ,
    4.     input                clk ,
    5.     input                rst_n,
    6.     output   wire        Y   
    7. );
    8.     
    9. reg [1:0] curr_state;
    10. reg [1:0] next_state;
    11. // one step
    12. always @ (posedge clk or negedge rst_n)
    13. begin
    14.     if( ~rst_n ) begin
    15.         curr_state <2'b00;
    16.         next_state <= 2'b00;
    17.     end 
    18.     else begin
    19.         curr_state <= next_state;
    20.     end 
    21. end 
    22.     
    23. // two step
    24. always @ (*) 
    25. begin
    26.     case(curr_state)
    27.         2'b00 : next_state = (A == 1'b1) ? 2'b11 : 2'b01;
    28.         2'b01 : next_state = (A == 1'b1) ? 2'b00 : 2'b10;
    29.         2'b10 : next_state = (A == 1'b1) ? 2'b01 : 2'b11;
    30.         2'b11 : next_state = (A == 1'b1) ? 2'b10 : 2'b00;
    31.         default : next_state = 2'b00;
    32.     endcase
    33. end
    34.     
    35. assign Y = (curr_state == 2'b11) ? 1 : 0;
    36.     
    37. endmodule

    VL22 使用状态转移图实现时序电路

    1. `timescale 1ns/1ns
    2. module seq_circuit(
    3.    input                C   ,
    4.    input                clk ,
    5.    input                rst_n,
    6.  
    7.    output   wire        Y   
    8. );
    9.     
    10. reg [1:0] curr_state;
    11. reg [1:0] next_state;
    12. // one step
    13. always @ (posedge clk or negedge rst_n)
    14. begin
    15.     if( ~rst_n ) begin
    16.         curr_state <2'b00;
    17.         next_state <= 2'b00;
    18.     end 
    19.     else begin
    20.         curr_state <= next_state;
    21.     end 
    22. end 
    23. // two step
    24. always @ (*)
    25. begin
    26.     case(curr_state)
    27.         2'b00 : next_state = (C == 1'b1) ? 2'b01 : 2'b00;
    28.         2'b01 : next_state = (C == 1'b1) ? 2'b01 : 2'b11;
    29.         2'b10 : next_state = (C == 1'b1) ? 2'b10 : 2'b00;
    30.         2'b11 : next_state = (C == 1'b1) ? 2'b10 : 2'b11;
    31.         default : next_state = 2'b00;
    32.     endcase
    33. end
    34. assign Y = ((curr_state == 2'b11) | ((curr_state == 2'b10)&&(C == 1'b1)) )? 1 : 0;
    35.     
    36. endmodule

    VL23 ROM的简单实现

    1. `timescale 1ns/1ns
    2. module rom(
    3.  input clk,
    4.  input rst_n,
    5.  input [7:0]addr,
    6.  output [3:0]data
    7. );
    8.     
    9. reg [3:0] romreg[7:0];
    10. integer i;
    11. always @ (posedge clk or negedge rst_n)
    12. begin
    13.     if( ~rst_n ) begin
    14.         romreg[0] <4'd0;
    15.         romreg[1] <= 4'd2;
    16.         romreg[2] <= 4'd4;
    17.         romreg[3] <= 4'd6;
    18.         romreg[4] <= 4'd8;
    19.         romreg[5] <= 4'd10;
    20.         romreg[6] <= 4'd12;
    21.         romreg[7] <= 4'd14;
    22.     end 
    23.     else begin
    24.         // romreg[0] <= romreg[0];
    25.         // ...
    26.         // romreg[7] <= romreg[7];
    27.         for(i = 0; i < 8; i = i+1) begin : rom_i
    28.             romreg[i] <= romreg[i];
    29.         end 
    30.     end 
    31. end
    32. assign data = romreg[addr];
    33. endmodule

    VL24 边沿检测

    1. `timescale 1ns/1ns
    2. module edge_detect(
    3.  input clk,
    4.  input rst_n,
    5.  input a,
    6.  
    7.  output reg rise,
    8.  output reg down
    9. );
    10.     
    11. reg a1;
    12. always @ (posedge clk or negedge rst_n)
    13. begin
    14.     if( ~rst_n ) begin
    15.         a1 <1'b0;
    16.         rise <= 1'b0;
    17.         down <= 1'b0;
    18.     end 
    19.     else begin
    20.         a1 <= a;
    21.         if(a & ~a1)
    22.             rise <= 1'b1;
    23.         else 
    24.             rise <= 1'b0;
    25.         if(~a & a1)
    26.             down <= 1'b1;
    27.         else
    28.             down <= 1'b0;
    29.     end 
    30. end 
    31.         
    32. endmodule
  • 相关阅读:
    你需要知道的 TCP 三次握手
    蓝桥杯每日一题2023.10.19
    书写高质量sql的一些建议
    C语言 | Leetcode C语言题解之第513题找树左下角的值
    MonkeyRunner测试步骤
    redis集群
    springboot依赖的小知识点
    多线程06:条件变量
    什么是 SYN 洪水攻击?如何防护?
    ChatGPT搭建AI网站实战
  • 原文地址:https://blog.csdn.net/m0_61687959/article/details/125533695