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

news2024/12/23 13:43:25

 前言: 

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

目录如下:

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,完成串行转并行。


reg [5:0] shiftcount;
always @(posedge clk)begin
    if(data_in_ena && loop_row == 6'd0)begin
        data_store[addr] <= serial_data;
    end
    else if(data_in_ena && loop_row != 6'd0 && count_row == 6'd0)begin
        data_store <= {1'b0,data_store[3779:64],serial_data,data_store[62:1]}; //should shift 63 times   60bit shift one times 
        shiftcount <= shiftcount + 1'b1;
    end
    else if(data_in_ena && loop_row != 6'd0 && count_row > 6'd0)begin
        data_store[addr] <= serial_data;
    end
end

always @(posedge clk)begin
    if(!rstn)begin
        addr <= 12'd62;
        shiftcount <= 6'd0;
    end
    else if(data_in_ena && count_row < 59)begin
        addr <= 63*count_row+12'd125;  //addr belongs to {62,125,188,...,3779}  
    end
    else if(data_in_ena && count_row == 59)begin
        addr <= 12'd62;
    end
end

代码

            ,
    input               rstn            ,
    input               serial_data     ,
    input               data_in_ena     ,

    output      [62:0]  parallel_data   ,
    output  reg         data_out_ena
);

reg [3779:0] data_store;
reg [11:0] addr;
reg [62:0] parallel_data_reg;

reg [5:0] count_column,count_row; //one column is once parallel_data
reg [5:0] loop_column,loop_row;

reg [5:0] output_count;
reg output_valid;

always @(posedge clk)begin     //one loop ,save 63 bits data, so count_column belongs to [0,62]
    if(!rstn)begin
        count_column <= 6'd0;
    end
    else if(data_in_ena && count_column < 6'd62)begin
        count_column <= count_column + 1'b1;
    end
    else if(data_in_ena && count_column == 6'd62)begin
        count_column <= 6'd0;
    end
end

always @(posedge clk)begin     //count_row belongs to [0,59]
    if(!rstn)begin
        count_row <= 6'd0;
    end
    else if(data_in_ena && count_row < 6'd59)begin
        count_row <= count_row + 1'b1;
    end
    else if(data_in_ena && count_row == 6'd59)begin
        count_row <= 6'd0;
    end
end


always @(posedge clk)begin      //loop_column belongs to [0,59]
    if(!rstn)begin
        loop_column <= 6'd0;
    end
    else if(count_column == 6'd62 && loop_column < 6'd59)begin
        loop_column <= loop_column + 1'b1;
    end
    else if(count_column == 6'd62 && loop_column == 6'd59)begin
        loop_column <= 6'd0;
    end
end

always @(posedge clk)begin      //loop_row belongs to [0,62]
    if(!rstn)begin
        loop_row <= 6'd0;
    end
    else if(count_row == 6'd59 && loop_row < 6'd62)begin
        loop_row <= loop_row + 1'b1;
    end
    else if(count_row == 6'd59 && loop_row == 6'd62)begin
        loop_row <= 6'd0;
    end
end


reg [5:0] shiftcount;
always @(posedge clk)begin
    if(data_in_ena && loop_row == 6'd0)begin
        data_store[addr] <= serial_data;
    end
    else if(data_in_ena && loop_row != 6'd0 && count_row == 6'd0)begin
        data_store <= {1'b0,data_store[3779:64],serial_data,data_store[62:1]}; //should shift 63 times   60bit shift one times 
        shiftcount <= shiftcount + 1'b1;
    end
    else if(data_in_ena && loop_row != 6'd0 && count_row > 6'd0)begin
        data_store[addr] <= serial_data;
    end
end

always @(posedge clk)begin
    if(!rstn)begin
        addr <= 12'd62;
        shiftcount <= 6'd0;
    end
    else if(data_in_ena && count_row < 59)begin
        addr <= 63*count_row+12'd125;  //addr belongs to {62,125,188,...,3779}  
    end
    else if(data_in_ena && count_row == 59)begin
        addr <= 12'd62;
    end
end

//parallel output
genvar i ;
generate
    for (i=0;i<=59;i=i+1)begin
        always @(posedge clk)begin
            if(output_valid == 1'b1)begin
                case(output_count)
                    i:parallel_data_reg <= data_store[i*63+62:i*63];
                endcase
            end
        end
    end
endgenerate

always @(posedge clk)begin
    if(!rstn)begin
        output_valid <= 1'b0;
    end
    else if(count_column == 6'd62 && loop_column == 6'd59)begin
        output_valid <= 1'b1;
    end
    else if(output_valid == 1'b1 && output_count == 6'd59)begin
        output_valid <= 1'b0;
    end
end

always @(posedge clk)begin
    if(!rstn)begin
        output_count <= 6'd0;
    end
    else if(output_valid == 1'b1 && output_count < 6'd59)begin
        output_count <= output_count + 1'b1;
    end
    else begin
        output_count <= 6'd0;
    end
end

always @(posedge clk)begin
    data_out_ena <= output_valid; //one beat late
end

assign parallel_data = parallel_data_reg;

endmodule

testbench

module serial_to_parallel_tb();

reg clk,rstn;
reg serial_data,data_in_ena;

wire [62:0] parallel_data;
wire  data_out_ena;

always #5 clk = ~clk;
initial begin
    clk <= 1'd0;
    rstn <= 1'd0;
    serial_data <= 1'b1;
    #16
    rstn <= 1'b1;
    forever begin
        repeat(3780)begin
            #10
            serial_data <= serial_data + 1'b1;
            data_in_ena <= 1'b1;
        end
        repeat(60)begin
            #10
            data_in_ena <= 1'b0;
        end
    end
end
initial begin
    #100000
    $finish();
end

//dump fsdb 
initial begin 
    $fsdbDumpfile("serial_to_parallel.fsdb");
    $fsdbDumpvars(0);
end 

serial_to_parallel u_serial_to_parallel(
    .clk            (clk)               ,  
    .rstn           (rstn)              ,
    .serial_data    (serial_data)       ,
    .data_in_ena    (data_in_ena)       ,

    .parallel_data  (parallel_data)     ,
    .data_out_ena   (data_out_ena)
);

endmodule

输出波形

yH5BAAAAAAALAAAAAAOAA4AAAIMhI+py+0Po5y02qsKADs=wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

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

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/12081.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JetsonNano部署yolo5 c++ onnx

编译OpenCV最新4.5.x版本 Jetson Nano自带的OpenCV版本比较低&#xff0c;Jetpack4.6对应的OpenCV版本为4.1的 而OpenCV当前最新版本已经到了4.5跟4.6了&#xff0c;4.5.x中OpenCV DNN支持了很多新的模型推理跟新的特性都无法在OpenCV4.1上演示&#xff0c;所以我决定从源码编…

Go语言 02

2.1 下载安装 Go Golang 中文网 Go 的安装也是十分的简洁、简单。就是 Next。哈哈 ~ 输入 go version 来查看是否安装完成吧 ~ 2.2 配置环境变量和工作目录 GOROOT&#xff1a;C:\Environment\Go 意味着 Go 在哪里。 在配置 GOPATH 之前&#xff0c;先把用户的 GOPATH 删掉。…

远程预付费电能管理系统在工业园的应用,主要功能有哪些?

安科瑞 李可欣 具体可咨询&#xff1a;Acrel_lkx 0概述 本项目为凌云工业园提供解决方案。本项目共有DDSY1352-NK/DTSY1352-NK预付费计量表41台&#xff0c;针对凌云工业园商业用电实现用电的智能化管理&#xff0c;通过安科瑞终端预付费电能表计来计量每个商铺的用电量&am…

web前端-html-css-background背景(color样式,image图片,repeat重复方式,position定位,简写)

背景 背景样式和背景图片重复方式 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title><style type"text/css">.box1 {width: 1024px;height: 724px;margin: 0 auto;/*设置背景样式*/backgr…

Go-Zero环境搭建

Go-Zero环境搭建go-zero 需要安装的组件1 Protobuf下载安装需要先下载protoc执行器2 Protobuf下Go、GRPC插件的安装3 goctl 安装go-zero 需要安装的组件 protocprotoc-gen-goprotoc-gen-go-grpcgoctl 1 Protobuf下载安装 需要先下载protoc执行器 到 https://github.com/pro…

磷酸酶、转录因子、KRAS ——“不可成药”靶点?

不可成药的三大类靶点 传统的药物靶点绝大部分是具有适合的结合位点和明确的活性位点的蛋白质。药物分子往往通过“占位驱动”的药理学作用模式发挥作用。这种方法虽然可行&#xff0c;但并不能适用于所有的靶蛋白&#xff0c;尤其是在蛋白本身缺乏相应的结合口袋、蛋白的内源性…

天然产物化合物库

据文献报道&#xff0c;在传统药物研发时代&#xff0c;天然产物是新药研发最重要的、也几乎是独有的源泉&#xff0c;当时超过 80% 的药物均是原始天然产物或者其类似物&#xff1b;随着有机化学、药物化学、计算机技术等的发展&#xff0c;即使到了人工合成小分子药物占主导地…

Neo4J超详细专题教程,快来收藏起来吧

Neo4J超详细教程 Lecture&#xff1a;波哥 一、Neo4J相关介绍 1.为什么需要图数据库 随着社交、电商、金融、零售、物联网等行业的快速发展&#xff0c;现实社会织起了了一张庞大而复杂的关系 网&#xff0c;传统数据库很难处理关系运算。大数据行业需要处理的数据之间的关系随…

webpack5 import动态导入实现按需加载并给文件统一命名

想要实现按需加载,动态导入模块。还需要额外配置: console.log("hello main");document.getElementById("btn").onClick = function () {// 动态导入 --> 实现按需加载 -->then是加载成功要做的处理不处理的话可以不写import( "./js/math.j…

【yarn】任务日志丢失问题分析

【yarn】任务日志丢失问题分析 故事背景 今天中午收到了一个报警邮件通知。内容大致为&#xff1a;有一个正在 yarn上运行的flink的实时任务挂掉了。 针对上述的现象&#xff0c;我们的开发工程师先打开yarn的web ui找到对应的job的任务页面。查询任务日志。 点击这个log&am…

java计算机毕业设计springboot+vue宠物服务管理系统

项目介绍 计算机网络的发展,促进了社会各行业的进步,带来了经济快速增长。用户通过本平台发布宠物趣事,进行展示,在平台上和用户进行实时的交流沟通,达成交易。用户登录后,把想要交易的宠物周边商品发布到平台上,进行交易,提高了效率,减少了时间成本,并且在交易过程中,宠物服务…

c语言(看一遍就会操作,小马教一步步教你如何文件操作)

前言&#xff1a; ^ _ ^文件操作想必大家掌握的并不熟练&#xff0c;确实因为我们用的并不多&#xff0c;而本节内容能够让大家初步认识文件操作&#xff0c;从文件认识到文件使用&#xff0c;让我们对c语言文件操作有个初步的了解&#xff0c;在应用中可以看我用文件的形式完…

java爬虫破解滑块验证码

使用技术&#xff1a;javaSelenium 废话&#xff1a; 有爬虫&#xff0c;自然就有反爬虫&#xff0c;就像病毒和杀毒软件一样&#xff0c;有攻就有防&#xff0c;两者彼此推进发展。而目前最流行的反爬技术验证码&#xff0c;为了防止爬虫自动注册&#xff0c;批量生成垃圾账号…

三菱FX系列控制脉冲伺服--DDRVA、DZRN、 ALTP、D8340、DPLSY指令的使用

一&#xff1a;文章主题 FX系列控制轴最常用的是脉冲控制的方式。本文基于实际开发案例&#xff0c;讲解三菱FX系列的运动控制指令&#xff0c;基于该文章能清楚指导通过脉冲控制伺服的基本原理和程序思路。 二&#xff1a;运动控制指令 2.1、DDRVA指令使用 1、DDRVA定义&#…

zabbix 自动发现与自动注册(接上章补充)

一、zabbix 自动发现 server CentOS7.6 192.168.130.70 / client CentOS7.6 192.168.130.10 / proxy CentOS7.6 192.168.130.60 / 1.zabbix server 主动的去发现所有的客户端&#xff0c;然后将客户端的信息登记在服务端上。 缺点是如果定义的网段中的主机数量多&#xff0c;…

MQTT X 1.9.0 发布:开箱即用的 bench 命令,MQTT 性能测试更便捷

近日&#xff0c;MQTT 5.0 客户端工具 MQTT X 1.9.0 正式发布。 新版本针对桌面客户端优化了一些细节上的 UI 样式与交互方式&#xff0c;新增了一个可以帮助用户更加快速和系统学习 MQTT 协议相关知识的页面&#xff0c;同时也修复了一些已知问题&#xff1b;针对命令行客户端…

c++基础(十七)——职工管理系统实现

一、项目的创建 打开visual studio之后&#xff0c;选择文件—新建—项目。出现弹窗后选择Visual C,填好名称即可。 接下来分别在对应的位置创建头文件以及源文件以及一个主函数文件"职工管理系统.cpp"&#xff1a; 二、系统界面的基本实现&#xff1a; 在头文件…

Qt音视频开发03-ffmpeg倍速播放(半倍速/2倍速/4倍速/8倍速)

一、前言 用ffmpeg做倍速播放&#xff0c;是好多年都一直没有实现的功能&#xff0c;有个做法是根据倍速参数&#xff0c;不断切换播放位置&#xff0c;实现效果不是很好&#xff0c;ffplay中的倍速就做得很好&#xff0c;而且声音无论倍速多少还非常柔和&#xff0c;有特别的…

Vue实现网页首屏加载动画、页面内请求数据加载loading

博主介绍 &#x1f4e2;点击下列内容可跳转对应的界面&#xff0c;查看更多精彩内容&#xff01; &#x1f34e;主页&#xff1a;水香木鱼 &#x1f34d;专栏&#xff1a;后台管理系统 文章目录 简介&#xff1a;这是一篇有关【Vue实现网页首屏加载动画、页面内请求数据加载lo…

如何使用html、css制作一个期末作业网站【羽毛球体育运动主题html网页设计】

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…