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

2023-11-02

 前言:

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

目录如下:

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

波形


题目

以上是泰凌微公司的笔试真题,手撕一个代码,题目描述如下:

        假设每个clock cycle输入是一个3-bit数据信号,现在需要按次序整形成5-bit数据信号输出,并给出valid信号。其中LSB First,请用Verilog/VHDL给出代码。

sample data:

输入:000,110,011,011,010,010,011...   即:(000|11 0|011 |0 11|010|010|01 1)

输出:00011,00110,11010,01001,1...     即:(000 11|0 011  0|11010| 010 01|1)

        该题目,仔细阅读就会发现,序列都是同一条序列,分割方式不同;说白了其实就是一个位宽转换题,然后加握手信号。实现一个含握手的3-5bit的位宽转换模块。这个题目,华子也考过类似的,或者说很多公司爱考这玩意。


概念解释

下面解释下,题目中出现的概念

1、LSB(Least Significant Bit)--最低有效位

    LSB代表二进制中最小的单位,可以用来指示数字很小的变化。也就是说,LSB是一个二进制数字中的第0位(即最低位),具有权值为2^0,可以用来检测数的奇偶性。

2、MSB(Most Significant Bit)--最高有效位

    MSB代表一个n位二进制数字中的n-1位,具有最高的权值2^(n-1).对于有符号的二进制数,负数采用反码或补码形式,此时MSB用来表示符号,msb为1表示负数,0表示正数。


实现原理

         好的,解释完概念,题目的意思就非常明白了,实现一个含有握手信号的3-5 bit位宽转换器,输入为3bit,输出5bit,且输入的3bit从低位开始排,即输入000,110时,第一个5bit输出的是000 11,而不是10 000,也就是题目说的LSB First

思路分析

        ① 输入第一个3bit,无法输出;

        ② 输入第二个3bit,此时存数6bit,可以输出一次5bit,余下1bit;valid=1;

        ③ 输入第三个3bit,此时由于输出过一次5bit,余下1bit,加上这第三次输入的3bit,此时存数4bit,无法输出;

        ④ 输入第四个3bit,此时存数7bit,可以输出一次5bit,余下2bit;valid=1;

        ⑤ 输入第五个3bit,此时存数5bit,可以输出一次5bit,存数为0bit,状态循环可回到初始状态。valid=1;

        显然每五次输入是一个轮回,这是因为15bit是3bit和5bit 的最小公倍数,因此每输入15/3=5次,就输出15/5=3次。如此反复循环。

        根据分析我们看到,输出有效的时间点是第二次输入后、第四次输入后、第五次输入后,因此我们可以用一个计数器counter来作为valid信号的判据,当计数器为2、4、5时,valid都拉高即可。理清思路,代码就很好写了。

代码:

计数器,来计入总共输入了几次3bit数据: 

reg [2:0] counter;
always @(posedge clk)begin  //handshake counter
  if(!rstn)begin
    counter <= 3'd0; 
  end
  else if(ready_i && valid_i && (counter<=3))begin
    counter <= counter + 1'b1; 
  end
  else if(ready_i && valid_i && (counter==4))begin
    counter <= 3'd0;
  end
en

当输入第二次、第四次、第五次时,valid信号拉高:

reg [6:0] data_store;
always @(posedge clk)begin
  if(!rstn)begin
    valid_o_temp <= 1'b0;
  end
  else if(ready_i && valid_i)begin

    if((counter==1) || (counter==3) || (counter==4))begin     //valid_o output
      valid_o_temp <= 1'b1;
    end
    else begin
      valid_o_temp <= 1'b0;
    end

    case(counter)
      3'd0:data_store[6:4] <=  data_in;                       //store 3bit no output
      3'd1:data_store      <= {data_store[6:4],data_in,1'b0}; //store 6bit but output 5bit 
      3'd2:data_store      <= {data_store[3:0],data_in};      //store 4bit no output
      3'd3:data_store      <= {data_store[3:0],data_in};      //store 7bit output 5bit
      3'd4:data_store      <= {data_store[1:0],data_in,2'd0}; //store 5bit output 5bit
    endcase

  end
end

        case语句内的作用是将数据进行移位。因为最多情况下是存储7bit数据,然后输出5bit,所以存储输入数据的空间只需要7bit就够了。用7bit 的 data_store来存储输入数据;

第一次输入的3bit数据存储在data_store的高3位,不输出5bit数据;

第二次输入的3bit数据存储在data_store的高4-6位。此时,valid信号拉高,然后输出5bit 数据 data_out 等于data_store的高5bit即可;

第三次输入的3bit数据,让data_store左移三位,然后存储在低三位,不输出5bit数据;

第四次输入的3bit数据,让data_store左移三位,然后存储在低三位,此时7bit空间存满,因为进行了两次“左移三位”,所以此时7bit数据的最高位,就是原来7bit数据的最低位,也就是在第二次输入数据时,存储6bit输出5bit后,剩下的那1bit数据。再输出高5bit数据;余2bit

低五次输入的3bit数据,与上一阶段余下的2bit数据,凑5bit,放在data_store的高5位,输出。 


代码

module tailinwei#(

)(
  input         clk       ,
  input         rstn      ,
  input   [2:0] data_in   ,
  output  [4:0] data_out  ,
  
  input         ready_i   ,
  input         valid_i   ,
  output        ready_o   ,
  output        valid_o
);

reg valid_o_temp,valid_onebeat;
reg [2:0] counter;
always @(posedge clk)begin  //handshake counter
  if(!rstn)begin
    counter <= 3'd0; 
  end
  else if(ready_i && valid_i && (counter<=3))begin
    counter <= counter + 1'b1; 
  end
  else if(ready_i && valid_i && (counter==4))begin
    counter <= 3'd0;
  end
end

always @(posedge clk)begin
  if(ready_i)begin
    valid_onebeat <= valid_i;   //valid_i one beat
  end
end

reg [6:0] data_store;
always @(posedge clk)begin
  if(!rstn)begin
    valid_o_temp <= 1'b0;
  end
  else if(ready_i && valid_i)begin

    if((counter==1) || (counter==3) || (counter==4))begin     //valid_o output
      valid_o_temp <= 1'b1;
    end
    else begin
      valid_o_temp <= 1'b0;
    end

    case(counter)
      3'd0:data_store[6:4] <=  data_in;                       //store 3bit no output
      3'd1:data_store      <= {data_store[6:4],data_in,1'b0}; //store 6bit but output 5bit 
      3'd2:data_store      <= {data_store[3:0],data_in};      //store 4bit no output
      3'd3:data_store      <= {data_store[3:0],data_in};      //store 7bit output 5bit
      3'd4:data_store      <= {data_store[1:0],data_in,2'd0}; //store 5bit output 5bit
    endcase

  end
end

assign data_out = data_store[6:2];          // get high 5bit to output 
assign valid_o  = valid_o_temp && valid_onebeat;

endmodule

testbench

tb:整个testbench部分的激励,就按照题目的意思生成。 

module tailinwei_tb();

reg clk,rstn;

always #5 clk = ~clk;

wire ready_o,valid_o;
reg  ready_i,valid_i;

reg   [2:0] data_in;
wire  [4:0] data_out;

initial begin
  clk     <= 1'b0;
  rstn    <= 1'b0;
  ready_i <= 1'b1;
  valid_i <= 1'b0;
  #20
  rstn    <= 1'b1;
  data_in <= 3'b000;
  valid_i <= 1'b1; 

  #10 data_in <= 3'b110;
  #10 data_in <= 3'b011;
  #10 data_in <= 3'b011;
  #10 data_in <= 3'b010;
  #10 data_in <= 3'b010;
  #10 data_in <= 3'b011;
  #10
  valid_i <= 1'b0;
  #50
  $stop();
end

tailinwei u_tailinwei(
  .clk(clk),
  .rstn(rstn),
  .data_in(data_in),
  .data_out(data_out),

  .ready_i(ready_i),
  .valid_i(valid_i),
  .ready_o(ready_o),
  .valid_o(valid_o)
);

endmodule

波形

输入:000,110,011,011,010,010,011...   即:(000|11 0|011 |0 11|010|010|01 1)

输出:00011,00110,11010,01001,1...     即:(000 11|0 011  0|11010| 010 01|1)

每次输出数据时,valid信号有效,如波形所示。 


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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数字IC手撕代码-泰凌微笔试真题 的相关文章

  • thinkpad x1e 隐士进入bios

    thinkpad x1e 隐士进入bios 启动的时候 同时按 fn f1 两个键需要连续不停的按 bios页 同时按 fn f12 两个键需要连续不停的按 简单页 1 选择方向键startup 然后选择Boot按回车键 更改第一启动项从外

随机推荐

  • Pycharm报错Non-zero exit code (2)

    问题现象 通常我们拿到一个Python项目后 项目中有requirement txt文件 里面有列出需要安装的三方库 使用pycharm直接安装这些库时 报错 Non zero exit code 2 解决方案 第一种临时解决方案 是在py
  • 大佬为你揭秘微信支付的系统架构,你想知道的都在这里了

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由李跃森发表于云 社区专栏 李跃森 腾讯云PostgreSQL首席架构师 腾讯数据库团队架构师 负责微信支付商户系统核心数据库的架构设计和研发 PostgreSQL x2社区核心
  • mybatis Example条件查询

    Criterion是最基本 最底层的Where条件 用于字段级的筛选 Criteria Criteria包含一个Cretiron的集合 每一个Criteria对象内包含的Cretiron之间是由AND连接的 是逻辑与的关系 oredCrit
  • 2023 第十四届蓝桥杯模拟赛(第三期)题解

    文章目录 最小的十六进制 Excel的列 相等日期 取数 最大连通分块 哪一天 信号覆盖 清理水草 最长滑行 区间最小值 单调队列O n 优先队列O NlgN 线段树O NlgN 个人Java题解 据我所知题目一样的 可以参考一下 欢迎评论
  • 集成开放平台接口中心基于IdentityServer4的鉴权机制

    源宝导读 企业数字化生态建设中为解决集成多样性和资源统一管理的痛点引入企业级网关 网关作为资源访问的大门 身份认证鉴权是其业务的重中之重 本文将介绍企业级网关 天际集成开放平台是如何通过IdentityServer4来做到身份认证和鉴权业务
  • QT 5.6.1使用虚拟键盘,适用于arm-linux

    获取源码 https github com hanshuaipeng QtInputMethod GooglePinyin git 编译后得到的文件 包含全志A64 IMX6ULL和UBUNTU可用的 so文件 https download
  • 清华大学的计算机课程表,清华大学计算机专业课程表

    清华大学计算机专业课程表 应用泛函分析4学分 流形上的微积分4 秋 数论与编码 代数编码理论3 春 初等数论与多项式2 秋 应用统计3学分 必修不少于12学分 允许在院系教务部门认可下选修理学院的同类型课程 以下课程中必修4 门课 不少于1
  • AS 3.4.1 gradle问题

    编译后报错信息大概如下 Gradle s dependency cache may be corrupt this sometimes occurs after a network connection timeout Re downloa
  • 2023年国家护网0day-poc/exp漏洞全汇总(目前已更新到91个..实时更新中...)

    文章目录 前言 0x01 Sxf 报表系统 版本有限制 0x02 E Cology 某版本 SQL注入漏洞 0x03 某恒明御运维审计与风险控制系统xmlrpc sock任意用户添加漏洞 0x04 泛微 E Cology 某版本 SQL注入
  • Qt 多种方式读写二进制文件

    将文本数据写入二进制文件 然后从二进制文件中读出 还原为文本数据 include mainwindow h include
  • 服务器数码管不显示,单片机数码管亮但是没有数字咋回事?

    题目要求是 利用ADC0809设计一个简易数字电压表 要求可以测量0 5V之间8路输入电压值 电压值由4位LED数码管显示 并在数码管上轮流显示或单路选择显示 2 测量最小分辨率为0 019V 测量误差约为 0 02V include un
  • 【05】Nginx之Rewrite功能配置

    Rewrite是Nginx服务器提供的一个重要基本功能 是Web服务器产品中几乎必备的功能 主要的作用是用来实现URL的重写 注意 Nginx服务器的Rewrite功能的实现依赖于PCRE的支持 因此在编译安装Nginx服务器之前 需要安装
  • 【Python】 numpy数组操作

    数据类型转换 frame gt ndarray 函数 table name np array frame name import numpy as np data array np array data print type data ar
  • API测试方案

    接口测试方案 目录 一 简介 一 定义 二 为什么做接口测试 1 越底层发现bug 修复成本越低 越早发现bug 修复成本越低 2 前后端按约定的接口开发 接口测好了 前端随便改 后端不用变 3 如今的系统复杂度不断上升 传统的测试方法成本
  • Ubuntu 指定文件默认打开方式(以QT Creator为例)

    Ubuntu 14 04 32位系统 想用QT Creator做Ubuntu下的代码编辑器 以前安装的QT4 8 6自带QT Creator 2 4 1版本太老 现在的QT Creator在Linux下已经都是64位版本了 官方最后的Lin
  • Python装饰器学习

    第一步 最简单的函数 准备附加额外功能 1 2 3 4 5 6 7 8 coding gbk 示例1 最简单的函数 表示调用了两次 def myfunc print myfunc called myfunc myfunc 第二步 使用装饰函
  • 运行项目报错Unable to build: the file dx.jar was not loaded from the SDK folder!

    在Eclipse中运行项目时 报题目中的错误 出现该问题的原因是高版本 如26 0 0 的build tools中的dx jar不可用 可能是兼容问题 因此问题的解决方法有两种 使用低版本 如25 0 2 build tools中的dx j
  • Vivado的FIR IP核实现低通滤波器

    本文介绍如何使用Vivado的FIR IP核实现低通滤波器 我们将设计一个采样频率为10MHz 通带0 1MHz 阻带高于2MHz的FIR低通滤波器 测试时 滤波器的输入信号为1MHz和3MHz的正弦波的叠加信号 期望滤波器能输出失真较小的
  • 高德地图显示影藏交通图层

    效果如图 核心代码 this traffic new AMap TileLayer Traffic autoRefresh true 是否自动刷新 默认为false interval 180 刷新间隔 默认180s zIndex 10 zo
  • 数字IC手撕代码-泰凌微笔试真题

    前言 本专栏旨在记录高频笔面试手撕代码题 以备数字前端秋招 本专栏所有文章提供原理分析 代码及波形 所有代码均经过本人验证 目录如下 1 数字IC手撕代码 分频器 任意偶数分频 2 数字IC手撕代码 分频器 任意奇数分频 3 数字IC手撕代