/2021.08.05修改
今天和一个朋友讨论这个题,发现我之前写的代码存在两个问题:第一,不能直接对多bit数据进行打两拍;第二,这个写法,没有考虑到clk_out是clk_in的四倍及其以上,所以状态机回到1‘b0后仍然会跳转到1‘b1,会重复采数据(原来从1‘b0跳转到1‘b1的条件是valid_i_r1为1,这是不全面的)。所以问题的关键是怎么判断一次输入数据传输的开始和结束。大家可以先思考一下,第一部分和第二部分是不太对的,正确的结果放在第三部分。

//2020.08.02错误版本
修正后的部分见第三部分。
使用verilog或者VHDl设计一个从4bit到1bit的转换电路,valid_i/valid_o为高电平代表输入/输出数据是有效的,valid_i可能不连续,clk_in是d_i的时钟,clk_out是d_o的时钟,clk_out的频率是clk_in的频率的4倍及以上,rst为异步复位信号,高有效。
一下代码是经过仿真测试了功能的。

1、verilog代码
设计思路是:先用同步器将有效信号valid_i同步到clk_o(单比特慢时钟域到快时钟域的同步),我顺便也把data_in同步到clk_o时钟域来了(这里是多bit,不知道可行不。,存疑,希望大佬看到的时候能答疑一下),再执行并转串的操作。

module patose(
input clk_i,
input clk_o,
input rst,
input [3:0]data_in,
input valid_i,
output reg data_out,
output reg valid_o
);reg data_out_r;
reg [3:0]data_in_r;
reg [3:0]data_in_r1;
reg valid_i_r;
reg valid_i_r1;
reg state;
reg [3:0]data_in_r2;
reg [2:0]cnt;
always@(posedge clk_o)
if(rst)begin    data_in_r<=0;data_in_r1<=0;valid_i_r<=0;valid_i_r1<=0;end
elsebegin data_in_r<=data_in;data_in_r1<=data_in_r;valid_i_r<=valid_i;valid_i_r1<=valid_i_r;endalways@(posedge clk_o or posedge rst)
if(rst)begindata_out<=0;valid_o<=0;state<=1'b0;cnt<=0;data_in_r2<=0;valid_o<=0;end
elsebegincase(state)1'b0:if(valid_i_r1)begindata_out<=data_in_r1[0];data_in_r2<={1'b0,data_in_r1[3:1]};state<=2'b01;cnt<=cnt+1;valid_o<=1;endelsebegindata_out<=0;valid_o<=0;state<=1'b0;cnt<=0;data_in_r2<=0;valid_o<=0;              end1'b1: beginif(cnt==4)begindata_out<=data_in_r2[0];data_in_r2<={1'b0,data_in_r2[3:1]};cnt<=0;state<=2'b00;valid_o<=0;endelsebegincnt<=cnt+1;data_out<=data_in_r2[0];data_in_r2<={1'b0,data_in_r2[3:1]};valid_o<=valid_o;endendendcaseendendmodule

2、仿真文件

module patose_tst();reg clk_i;
reg clk_o;
reg rst  ;
reg [3:0]data_in;
reg valid_i     ;
wire data_out   ;
wire valid_o    ;patose U_patose(
. clk_i   (clk_i   ),
. clk_o   (clk_o   ),
. rst     (rst     ),
. data_in (data_in ),
. valid_i (valid_i ),
. data_out(data_out),
. valid_o (valid_o )
);initial
begin
data_in=0;
clk_i=1;
clk_o=1;
rst=1;
#40 rst=0;
#40 data_in=4'b1011;valid_i=1;
#40 data_in=4'b1001;
#40 valid_i=0;endalways #20 clk_i=~clk_i;
always #5 clk_o=~clk_o;endmodule

3、修正后的代码
(1)
先说一下思路,这个题的考点:第一是跨时钟域;第二是并转串;跨时钟域的话我是只对valid_i进行跨时钟域,数据的处理我其实还是不知道对不对,后面知道怎么做了再来更新。并转串其实比较常规,看代码就能理解。
还有一个隐含的条件就是:数据可能是连续来的,也可能不是连续来的。
那,怎么判断每一次来的4bit数据传输开始和结束呢?传输结束比较好判断,就是传输开始后用一个计数器即可。开始怎么判断呢?大家可以思考一下这里。
我是这样想的:才开始想用valid_i_r1的上升沿来判断,但是呢如果数据是连续来的这个办法就不可行了,这只能适用于数据是断开的情况。后面我发现一个特征,就是每次4bit都会有clk_i出现上升沿,所以开始传输的条件可以为clk_i出现上升沿且valid_i有效。这个是大致的一个思考过程,大家可以画图帮助理解。
(2)设计文件

`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2021/07/31 19:27:59
// Design Name:
// Module Name: patose
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module patose(
input clk_i,
input clk_o,
input rst,
input [3:0]data_in,
input valid_i,
output reg data_out,
output reg valid_o
);reg data_out_r;
reg [3:0]data_in_r;
reg [3:0]data_in_r1;
reg valid_i_r;
reg valid_i_r1;
reg state;
reg [3:0]data_in_r2;
reg [2:0]cnt;
//wire posclk_i_flg;//clk_i出现上升沿的标志reg posclk_i_flg;
reg clk_i_r;
reg clk_i_r1;always@(posedge clk_o)
if(rst)
begin clk_i_r<=0;clk_i_r1<=0;end
else  begin clk_i_r<=clk_i;clk_i_r1<=clk_i_r;end
//assign posclk_i_flg=(clk_i_r==1&&clk_i_r1==0)?1:0;
always@(posedge clk_o)
if(rst)
posclk_i_flg<=0;
else if(clk_i_r==1&&clk_i_r1==0)
posclk_i_flg<=1;
else posclk_i_flg<=0;always@(posedge clk_o)
if(rst)begin    //data_in_r<=0;//data_in_r1<=0;valid_i_r<=0;valid_i_r1<=0;end
elsebegin //data_in_r<=data_in;//data_in_r1<=data_in_r;valid_i_r<=valid_i;valid_i_r1<=valid_i_r;endalways@(posedge clk_o)
if(rst)begindata_out<=0;valid_o<=0;state<=1'b0;cnt<=0;data_in_r2<=0;valid_o<=0;end
elsebegincase(state)1'b0:if(valid_i_r1&&posclk_i_flg)begin//data_out<=data_in_r1[0];data_out<=data_in[0];//data_in_r2<={1'b0,data_in_r1[3:1]};data_in_r2<={1'b0,data_in[3:1]};state<=2'b01;cnt<=cnt+1;valid_o<=1;endelsebegindata_out<=0;valid_o<=0;state<=1'b0;cnt<=0;data_in_r2<=0;valid_o<=0;              end1'b1: beginif(cnt==4)begindata_out<=data_in_r2[0];data_in_r2<={1'b0,data_in_r2[3:1]};cnt<=0;state<=1'b0;valid_o<=0;endelsebegincnt<=cnt+1;data_out<=data_in_r2[0];data_in_r2<={1'b0,data_in_r2[3:1]};valid_o<=valid_o;endendendcaseendendmodule

(3)仿真文件:

`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2021/07/31 19:29:38
// Design Name:
// Module Name: patose_tst
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module patose_tst();reg clk_i;
reg clk_o;
reg rst  ;
reg [3:0]data_in;
reg valid_i     ;
wire data_out   ;
wire valid_o    ;patose U_patose(
. clk_i   (clk_i   ),
. clk_o   (clk_o   ),
. rst     (rst     ),
. data_in (data_in ),
. valid_i (valid_i ),
. data_out(data_out),
. valid_o (valid_o )
);initial
begin
data_in=0;
clk_i=1;
clk_o=1;
valid_i=0;
rst=1;
#40 rst=0;
#40 data_in=4'b1011;valid_i=1;
#40 data_in=4'b1001;
#40 valid_i=0;
#80 valid_i=1;
data_in=4'b1101;
#40 valid_i=0;
#80 valid_i=1;
data_in=4'b1001;
#40 valid_i=0;endalways #20 clk_i=~clk_i;
always #2  clk_o=~clk_o;endmodule

(3)波形图

正确的波形(输出时钟频率为输入时钟频率10倍的情况)

之前的仿真文件设置的输出时钟频率刚好为输入时钟频率的4倍,隐藏了我的设计错误。错误现象如下:

大家在阅读的过程中,如果发现不对的地方,欢迎大家批评指正。

秋招手撕代码:4bit转换为1bit,且是慢时钟域到快时钟域相关推荐

  1. 数字IC秋招手撕代码(二)50%占空比的三分频

    数字IC秋招手撕代码(二)50%占空比的三分频 题目 设计思路 与逻辑分频 代码 或逻辑分频 代码 异或逻辑分频 代码 题目 用verilog实现三分频电路,要求输出50%占空比 设计思路 如果不限制 ...

  2. 秋招手撕代码:verilog实现常规8-3编码器和优先级8-3编码器

    1.常规的8-3编码器(一次输入只有一个1) //8-3编码器:常规8-3编码器,每次的输入只有1个1,编码输出结果为1所处的位置module encoder( input D0, input D1, ...

  3. 秋招总结:遇到的手撕代码题

    2020年秋招总结:遇到的手撕代码题 跟谁学 一面:求连续子数组的最大和(力扣 53) [思路:力扣系列略,题解区都比我讲得好] 二面:翻转字符串中的每个单词(简单题,比较常见,没去找对应的原题) [ ...

  4. FPGA秋招面试手撕代码20+

    目录 前言 1.序列检测器 (1)三段式状态机实现方式 (2)移位寄存器实现方式 2.序列生成器 (1)移位寄存器方式实现 (2)计数器方式实现 (3)三段式状态机方式实现 3.分频 (1)偶数分频 ...

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

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

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

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

  7. 数字IC手撕代码--小米科技(除法器设计)

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

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

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

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

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

最新文章

  1. LDAPserver的安装
  2. CTFshow php特性 web125
  3. ubuntu 查看cpu运行频率_Ubuntu下调整CPU运行频率并对其进行监视
  4. DirectShow学习
  5. treeview调用数据库成树
  6. 论文浅尝 | SMBOP: Semi-autoregressive Bottom-up Semantic Parsing
  7. 电脑上我的文档图标不见了怎么办
  8. 对PHP输入输出流学习和认识
  9. 如何理解,互联网架构“高并发”?
  10. mysql嵌套查询效率低_mysql的嵌套查询效率很低
  11. Scrum 敏捷项目管理
  12. 四象限里的正弦、余弦和正切(四象限反正切函数的原理)
  13. mysql er图注释_powerdesigner 生成mysql带注释的ER图
  14. Vue核心技术-39,vue-router-向路由组件传递数据
  15. 中国氨基酸表面活性剂市场前景展望与发展建议分析报告2022-2028年
  16. OpenStack使用Placement做资源管理时虚拟机无法调度的一次排错记录
  17. 时间序列模型SCINet(代码解析)
  18. android 图表实现,Android实现图表绘制和展示
  19. 智能泥石流泥水位监测预警系统解决方案
  20. 新导部队营房室内人员定位系统解决方案

热门文章

  1. 成都盛迈坤电商:评价怎么有效回复
  2. android 苹果开发进度,IOS 锁屏音乐信息显示(进度条,歌名等信息。)
  3. NR/5G - 系统消息变更
  4. 中职网络安全操作系统渗透
  5. word样式管理:如何对样式进行修改删除
  6. php固定红包 + 随机红包算法
  7. 商标注册过程中,如何避免字体侵权?
  8. 黄油安卓_寻找可爱,定义外观为黄油皇家字符
  9. CSS实现的带头像的彩色垂直菜单源码
  10. 趣谈C语言(基础篇)