• 数字IC手撕代码-XX公司笔试真题(串并转换控制)


     前言: 

            本专栏旨在记录高频笔面试手撕代码题,以备数字前端秋招,本专栏所有文章提供原理分析、代码及波形,所有代码均经过本人验证。

    目录如下:

    1.数字IC手撕代码-分频器(任意偶数分频)

    2.数字IC手撕代码-分频器(任意奇数分频)

    3.数字IC手撕代码-分频器(任意小数分频)

    4.数字IC手撕代码-异步复位同步释放

    5.数字IC手撕代码-边沿检测(上升沿、下降沿、双边沿)

    6.数字IC手撕代码-序列检测(状态机写法)

    7.数字IC手撕代码-序列检测(移位寄存器写法)

    8.数字IC手撕代码-半加器、全加器

    9.数字IC手撕代码-串转并、并转串

    10.数字IC手撕代码-数据位宽转换器(宽-窄,窄-宽转换)

    11.数字IC手撕代码-有限状态机FSM-饮料机

    12.数字IC手撕代码-握手信号(READY-VALID)

    13.数字IC手撕代码-流水握手(利用握手解决流水线断流、反压问题)

    14.数字IC手撕代码-泰凌微笔试真题

    15.数字IC手撕代码-平头哥技术终面手撕真题

    16.数字IC手撕代码-兆易创新笔试真题

    17.数字IC手撕代码-乐鑫科技笔试真题(4倍频)

    18.数字IC手撕代码-双端口RAM(dual-port-RAM)

            ...持续更新

    更多手撕代码题可以前往 数字IC手撕代码--题库


    目录

    题目描述

    解题思路

    代码

    testbench

    输出波形


    题目描述

            将数据进行串转并处理,输入 3780 个串行比特,每个数据占一个时钟周期,输入共占 3780 个时钟,要求并行输出 63 个 bit,共 60 个时钟输出完.其时序示意图如下: 第 1 个时钟并行输出 0,60,…,3720,做为 bus 整体输出 第 2 个时钟并行输出 1,61,…3721 第 60 个时钟并行输出 59,119,…3779 注意每次并行输出仅占一个时钟周期,60 个时钟周期便输出完. 输出与输入的相对时延关系任意即可。

    解题思路

            这道题乍一眼看上去好像很简单,串并转换就行了,但其实涉及到一个单bit数据位置的问题,不仅如此,如果写出来的代码不是“一次性”的,能经得住背靠背传输、以及间断传输的考验的话,代码还是需要写一段把所有情况考虑进去的。

            重新理一下题目的意思,题目是实现一个串并的转换,每周期输入1bit数据,共在3780个周期内完成输入3780个1bit数据。因为并行输出是在串行输入全部完成后进行的,因此我们需要将3780个串行输入存储起来,可以用RAM也可以用寄存器直接存储。并行输出,每次输出63bit,共输出60周期,60*63bit=3780bit。

            这里的关键在于并行输出的相邻bit是跳跃式的,0、60、120...;1、61、121...;因此找到并行输出和串行输入之间的映射关系尤为重要。可以用一个60*63=3780的一维数组data_store去存储输入的串行数据。我的思路是用一个地址addr来索引每次存储在一维数组data_store的位置,然后每63个周期为一个loop,总共有60个loop,在一个loop中,往一维数组里面写入单bit数据,位置分别存放在59,119,179,...,3719,3779。每经过63周期(存完63bit数据),一维数组就右移1bit(左边高bit,右边低bit)。这样子经过62次shift后,第一个写入的单bit数据就会被shift到最低位,一开始写在62位置的bit,会被移位到0位置,一开始写在3779位置的bit,会被移位到3717位置。       最后,在经过60loop之后,3780个单bit数据都输入完了,我们就可以输出高bit数据,把output_valid输出有效信号拉高,同时一周期输出一次63bit,输出60次63bit,完成串行转并行。

    1. reg [5:0] shiftcount;
    2. always @(posedge clk)begin
    3. if(data_in_ena && loop_row == 6'd0)begin
    4. data_store[addr] <= serial_data;
    5. end
    6. else if(data_in_ena && loop_row != 6'd0 && count_row == 6'd0)begin
    7. data_store <= {1'b0,data_store[3779:64],serial_data,data_store[62:1]}; //should shift 63 times 60bit shift one times
    8. shiftcount <= shiftcount + 1'b1;
    9. end
    10. else if(data_in_ena && loop_row != 6'd0 && count_row > 6'd0)begin
    11. data_store[addr] <= serial_data;
    12. end
    13. end
    14. always @(posedge clk)begin
    15. if(!rstn)begin
    16. addr <= 12'd62;
    17. shiftcount <= 6'd0;
    18. end
    19. else if(data_in_ena && count_row < 59)begin
    20. addr <= 63*count_row+12'd125; //addr belongs to {62,125,188,...,3779}
    21. end
    22. else if(data_in_ena && count_row == 59)begin
    23. addr <= 12'd62;
    24. end
    25. end

    代码

    1. module serial_to_parallel (
    2. input clk ,
    3. input rstn ,
    4. input serial_data ,
    5. input data_in_ena ,
    6. output [62:0] parallel_data ,
    7. output reg data_out_ena
    8. );
    9. reg [3779:0] data_store;
    10. reg [11:0] addr;
    11. reg [62:0] parallel_data_reg;
    12. reg [5:0] count_column,count_row; //one column is once parallel_data
    13. reg [5:0] loop_column,loop_row;
    14. reg [5:0] output_count;
    15. reg output_valid;
    16. always @(posedge clk)begin //one loop ,save 63 bits data, so count_column belongs to [0,62]
    17. if(!rstn)begin
    18. count_column <= 6'd0;
    19. end
    20. else if(data_in_ena && count_column < 6'd62)begin
    21. count_column <= count_column + 1'b1;
    22. end
    23. else if(data_in_ena && count_column == 6'd62)begin
    24. count_column <= 6'd0;
    25. end
    26. end
    27. always @(posedge clk)begin //count_row belongs to [0,59]
    28. if(!rstn)begin
    29. count_row <= 6'd0;
    30. end
    31. else if(data_in_ena && count_row < 6'd59)begin
    32. count_row <= count_row + 1'b1;
    33. end
    34. else if(data_in_ena && count_row == 6'd59)begin
    35. count_row <= 6'd0;
    36. end
    37. end
    38. always @(posedge clk)begin //loop_column belongs to [0,59]
    39. if(!rstn)begin
    40. loop_column <= 6'd0;
    41. end
    42. else if(count_column == 6'd62 && loop_column < 6'd59)begin
    43. loop_column <= loop_column + 1'b1;
    44. end
    45. else if(count_column == 6'd62 && loop_column == 6'd59)begin
    46. loop_column <= 6'd0;
    47. end
    48. end
    49. always @(posedge clk)begin //loop_row belongs to [0,62]
    50. if(!rstn)begin
    51. loop_row <= 6'd0;
    52. end
    53. else if(count_row == 6'd59 && loop_row < 6'd62)begin
    54. loop_row <= loop_row + 1'b1;
    55. end
    56. else if(count_row == 6'd59 && loop_row == 6'd62)begin
    57. loop_row <= 6'd0;
    58. end
    59. end
    60. reg [5:0] shiftcount;
    61. always @(posedge clk)begin
    62. if(data_in_ena && loop_row == 6'd0)begin
    63. data_store[addr] <= serial_data;
    64. end
    65. else if(data_in_ena && loop_row != 6'd0 && count_row == 6'd0)begin
    66. data_store <= {1'b0,data_store[3779:64],serial_data,data_store[62:1]}; //should shift 63 times 60bit shift one times
    67. shiftcount <= shiftcount + 1'b1;
    68. end
    69. else if(data_in_ena && loop_row != 6'd0 && count_row > 6'd0)begin
    70. data_store[addr] <= serial_data;
    71. end
    72. end
    73. always @(posedge clk)begin
    74. if(!rstn)begin
    75. addr <= 12'd62;
    76. shiftcount <= 6'd0;
    77. end
    78. else if(data_in_ena && count_row < 59)begin
    79. addr <= 63*count_row+12'd125; //addr belongs to {62,125,188,...,3779}
    80. end
    81. else if(data_in_ena && count_row == 59)begin
    82. addr <= 12'd62;
    83. end
    84. end
    85. //parallel output
    86. genvar i ;
    87. generate
    88. for (i=0;i<=59;i=i+1)begin
    89. always @(posedge clk)begin
    90. if(output_valid == 1'b1)begin
    91. case(output_count)
    92. i:parallel_data_reg <= data_store[i*63+62:i*63];
    93. endcase
    94. end
    95. end
    96. end
    97. endgenerate
    98. always @(posedge clk)begin
    99. if(!rstn)begin
    100. output_valid <= 1'b0;
    101. end
    102. else if(count_column == 6'd62 && loop_column == 6'd59)begin
    103. output_valid <= 1'b1;
    104. end
    105. else if(output_valid == 1'b1 && output_count == 6'd59)begin
    106. output_valid <= 1'b0;
    107. end
    108. end
    109. always @(posedge clk)begin
    110. if(!rstn)begin
    111. output_count <= 6'd0;
    112. end
    113. else if(output_valid == 1'b1 && output_count < 6'd59)begin
    114. output_count <= output_count + 1'b1;
    115. end
    116. else begin
    117. output_count <= 6'd0;
    118. end
    119. end
    120. always @(posedge clk)begin
    121. data_out_ena <= output_valid; //one beat late
    122. end
    123. assign parallel_data = parallel_data_reg;
    124. endmodule

    testbench

    1. module serial_to_parallel_tb();
    2. reg clk,rstn;
    3. reg serial_data,data_in_ena;
    4. wire [62:0] parallel_data;
    5. wire data_out_ena;
    6. always #5 clk = ~clk;
    7. initial begin
    8. clk <= 1'd0;
    9. rstn <= 1'd0;
    10. serial_data <= 1'b1;
    11. #16
    12. rstn <= 1'b1;
    13. forever begin
    14. repeat(3780)begin
    15. #10
    16. serial_data <= serial_data + 1'b1;
    17. data_in_ena <= 1'b1;
    18. end
    19. repeat(60)begin
    20. #10
    21. data_in_ena <= 1'b0;
    22. end
    23. end
    24. end
    25. initial begin
    26. #100000
    27. $finish();
    28. end
    29. //dump fsdb
    30. initial begin
    31. $fsdbDumpfile("serial_to_parallel.fsdb");
    32. $fsdbDumpvars(0);
    33. end
    34. serial_to_parallel u_serial_to_parallel(
    35. .clk (clk) ,
    36. .rstn (rstn) ,
    37. .serial_data (serial_data) ,
    38. .data_in_ena (data_in_ena) ,
    39. .parallel_data (parallel_data) ,
    40. .data_out_ena (data_out_ena)
    41. );
    42. endmodule

    输出波形

            支持背靠背传输,3780周期输入单bit数据,之后输入有效信号拉低60周期,此时输出有效信号拉高,输出60周期63bit的并行数据。


     更多手撕代码题可以前往 数字IC手撕代码--题库

  • 相关阅读:
    升级到.NET 6 后突然发现EFCore访问MySQL出现问题-没有 get_QueryProvider实现
    WebStorm安装教程
    道通转债,微芯转债,博22转债上市价格预测
    设A和B是两个单链表(带头结点),其中元素递增有序。设计一个算法从A和B中的公共元素产生新链表C,要求不破坏A,B。
    9. 内核、文件系统加载工具
    【性能测试】稳定性/并发压力测试的TPS计算+5W并发场景设计...
    牛客小白月赛60-D-游戏购买!
    一文详解快速排序详细到极致
    SQLITE存储时间数据报警语法错误,syntax error
    教培机构怎么做在线教育直播
  • 原文地址:https://blog.csdn.net/qq_57502075/article/details/127838432