12.31信号位宽转换(整数,非整数),时钟分频(奇数,偶数,任意小数,占空比),自动售货机(1,2),游戏机

本文主要是介绍12.31信号位宽转换(整数,非整数),时钟分频(奇数,偶数,任意小数,占空比),自动售货机(1,2),游戏机,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

非整数倍数据位宽转换8to12

所谓非整数倍,就是利用一个cnt去周期性决定寄存器里怎么输出,这个cnt的值,是最小公倍数

寄存器就正常的寄存,怎么输入怎么寄存 

`timescale 1ns/1nsmodule width_8to12(input 				   clk 		,   input 			      rst_n		,input				      valid_in	,input	[7:0]			   data_in	,output  reg			   valid_out,output  reg [11:0]   data_out
);
reg[7:0]data_lock;
reg[1:0]valid_cnt;
always@(posedge clk,negedge rst_n)beginif(!rst_n)data_lock<=0;else if(valid_in)data_lock<=data_in;
end
always@(posedge clk,negedge rst_n)beginif(!rst_n)valid_cnt<=0;else if(valid_in)beginif(valid_cnt==2'd2)valid_cnt<=0;elsevalid_cnt<=valid_cnt+1;end
end
always@(posedge clk,negedge rst_n)beginif(!rst_n)valid_out<=0;else if(valid_in&&valid_cnt==1)valid_out<=1;else if(valid_in&&valid_cnt==2)valid_out<=1;elsevalid_out<=0;
end
always@(posedge clk,negedge rst_n)beginif(!rst_n)data_out<=0;else if(valid_in&&valid_cnt==1)data_out<={data_lock,data_in[7:4]};else if(valid_in&&valid_cnt==2)data_out<={data_lock[3:0],data_in};
end
endmodule

为什么不需要2个8bit的寄存器进行数据缓存:

根据时序图, data_out是在两个数据输入之后的下一个时钟周期产生输出,如果采用两个寄存器缓存两个数据,那么第二个数据还没缓存进寄存器后就要输出数据,这样不能实现满足时序要求的数据输出。

根据时序图,数据是在第二个数据到来之后输出,当仅有一个数据到来时,不产生输出,所以内部设计一个计数器(valid_cnt),用来指示数据接收状态。当检测到valid_in拉高时,valid_cnt加1,valid_cnt在0-2之间循环,valid_cnt复位值是0。当valid_cnt是1或2,且valid_in为高时,输出数据,valid_out拉高。

当valid_cnt==1且valid_in为高时,data_out <= {data_lock, data_in[7:4]};当valid_cnt==2且valid_in为高时,data_out <= {data_lock[3:0], data_in}。

就是说,复位的时候,寄存器里一个也没有,所以就不能输出,然后存了一个后,就是1,再来就可以输出,这时输出,就输出存的8个以及新输入的前4个,并且进到2,表示此时寄存器里存的是第二个输入的,而且前半个已经输出过了,该输出后四个,所以此时要输出,就是输出寄存器的后四个以及新输入的全部,这时候寄存器内部实际上也就相当于空了

也就是说valid_cnt决定输出信号,怎么处理寄存器里的信号

电路图

 

 

是时序逻辑就是要用触发器,<=最直接的就是D触发器  

 整数倍数据位宽转换8to16

`timescale 1ns/1nsmodule width_8to16(input 				   clk 		,   input 				   rst_n		,input				      valid_in	,input	   [7:0]		   data_in	,output	reg			valid_out,output   reg [15:0]	data_out
);
reg[0:0]cnt;
reg[7:0]ram;
always@(posedge clk,negedge rst_n)beginif(!rst_n)cnt<=0;else if(valid_in)cnt<=(cnt)?0:1;else cnt<=cnt;
end
always@(posedge clk,negedge rst_n)beginif(!rst_n)ram<=0;else if(valid_in)ram<=data_in; elseram<=ram;
end
always@(posedge clk,negedge rst_n)beginif(!rst_n)begindata_out<=0;valid_out<=0;endelse if(cnt&&valid_in)begindata_out<={ram,data_in};valid_out<=1;endelse begindata_out<=data_out;valid_out<=0;end
end
endmodule

注意有if情况遗漏时,自动生成锁存器锁存之前的状态

电路图

QN代表反态,即取反

空线代表不利用相应的信号,即不做后续的输出 

简单的逻辑就是生成一个简单的D触发器 

 

 

这里的D信号,就是控制触发器现态Q的信号,做一些处理,就是二路选择器,然后上面是一个与门;上面的没有是因为锁存的是8位的信号,不是0或1 

 时钟分频(偶数

`timescale 1ns/1nsmodule even_div(input     wire rst ,input     wire clk_in,output    wire clk_out2,output    wire clk_out4,output    wire clk_out8);
//*************code***********//
reg clk2,clk4,clk8;
always@(posedge clk_in,negedge rst)beginif(!rst)clk2<=0;elseclk2<=~clk2;
end
always@(posedge clk2,negedge rst)beginif(!rst)clk4<=0;elseclk4<=~clk4;
end
always@(posedge clk4,negedge rst)beginif(!rst)clk8<=0;elseclk8<=~clk8;
end
assign clk_out8=clk8;
assign clk_out4=clk4;
assign clk_out2=clk2;
//*************code***********//
endmodule

D触发器

D触发器构建电路图,就是<=右边的为输入的D信号,左边的就是输出的Q现态信号

 D触发器接口,有控制触发器触发的时钟信号,以及D信号,就是等式右侧的信号,输出的就是转换后的信号

占空比50%的奇数分频

`timescale 1ns/1nsmodule odo_div_or#(parameter N = 7)(input    wire  rst ,input    wire  clk_in,output   wire  clk_out7);reg [3:0]            cnt ;always @(posedge clk_in or negedge rst) beginif (!rst) begincnt    <= 'b0 ;endelse if (cnt == N-1) begincnt    <= 'b0 ;endelse begincnt    <= cnt + 1'b1 ;endendreg                  clkp ;always @(posedge clk_in or negedge rst) beginif (!rst) beginclkp <= 1'b0 ;endelse if (cnt == (N>>1)) begin clkp <= 1 ;endelse if (cnt == N-1) begin clkp <= 0 ;endendreg                  clkn ;always @(negedge clk_in or negedge rst) beginif (!rst) beginclkn <= 1'b0 ;endelse if (cnt == (N>>1) ) begin clkn <= 1 ;endelse if (cnt == N-1) begin clkn <= 0 ;endendassign clk_out7 = clkp | clkn ;endmodule

对于奇数分频电路,主要难点在于50%占空比的实现。单触发沿在奇数分频中是没有办法实现50%占空比的,因此需要考虑使用双边沿加组合逻辑实现50%占空比 

clkout7的翻转第一次是在上升沿,第二次是在下降沿。

任意小数分频

请设计一个可以实现任意小数分频的时钟分频器,比如说8.7分频的时钟信号

注意rst为低电平复位

提示:

其实本质上是一个简单的数学问题,即如何使用最小公倍数得到时钟周期的分别频比。

设小数为nn,此处以8.7倍分频的时钟周期为例。

首先,由于不能在硬件上进行小数的运算(比如2.1个时钟这种是不现实的,也不存在3.3个寄存器),小数分频不能做到分频后每个时钟周期都是源时钟的nn倍,也无法实现占空比为1/2,因此,考虑小数分频,其实现方式应当为53个clkout时钟周期是10个clkin时钟周期的8.7倍。

其实和非整数倍数据转位宽差不多,

非整数倍数据转位宽,是用一个计数器,去记录当前是输出到第几个阶段了

用一个寄存器,然后记录当前输入的信号,最后就依据计数器的信号,做出相应的输出,结合此时输出的信号;

不同的点在于,非整数倍的数据位宽转换,每个时钟周期内都会输出信号

而小数分频器,是一定时间内为1,一定时间内为0

分频器,是把信号频率变慢,原来10秒内跳10次,现在只跳1次

思路就是逼近模拟,在大的周期上表现的是小数分频,小的周期里就用奇数分频以及偶数分频逼近,然后一个计数器去记录大的周期,一个计数器就是实现每个小的周期上的分频;那个大的周期上的,决定此时小的周期上是用什么分频器,是奇数还是偶数;然后用一个FLAG标志,去记录当前是用奇数分频器还是偶数分频器,这个FLAG在中间某一点以及整个大周期结束时去进行更换,中间某一点通过计算得到 

`timescale 1ns/1nsmodule div_M_N(input  wire clk_in,input  wire rst,output wire clk_out
);parameter M_N = 8'd87; parameter c89 = 8'd24;  // 8/9时钟切换点parameter div_e = 5'd8; //偶数周期parameter div_o = 5'd9; //奇数周期
//*************code***********//reg [3:0] clk_cnt;reg [6:0] cyc_cnt;reg div_flag;reg clk_out_r;always@(posedge clk_in or negedge rst) beginif(~rst)clk_cnt <= 0;else if(~div_flag)clk_cnt <= clk_cnt==(div_e-1)? 0: clk_cnt+1;elseclk_cnt <= clk_cnt==(div_o-1)? 0: clk_cnt+1;endalways@(posedge clk_in or negedge rst) beginif(~rst)cyc_cnt <= 0;elsecyc_cnt <= cyc_cnt==(M_N-1)? 0: cyc_cnt+1;endalways@(posedge clk_in or negedge rst) beginif(~rst)div_flag <= 0;elsediv_flag <= cyc_cnt==(M_N-1)||cyc_cnt==(c89-1)? ~div_flag: div_flag;endalways@(posedge clk_in or negedge rst) beginif(~rst)clk_out_r <= 0;else if(~div_flag)clk_out_r <= clk_cnt<=((div_e>>2)+1);elseclk_out_r <= clk_cnt<=((div_o>>2)+1);endassign clk_out = clk_out_r;
//*************code***********//
endmodule

 在电路图当中,画触发器,就是先看时钟信号是什么,接上去,然后看复位信号是什么,接上去;再就是对应D信号,选触发器,对于<=,就是用D触发器,左侧就是输出的Q现态信号,右侧就是输入的D信号,遇到三目表达式或者else if 选择,就是选择器,选择出一个信号接到D信号上

无占空比要去的奇数分频

所谓占空比,就是在一个周期内0和1所占的比例。

以小数分频器上题为例,要实现小数分频器,在大周期里,flag在周期末以及中间某一点去更新,中间某一点就决定了什么时候反转,也决定了flag的占空比

同理在分频器中,输出分频信号什么时候反转,就是对应中间某一点,但是一定会在周期末进行反转,即cnt==分频数时。

选取中间点时,占空比是百分之五十

 

`timescale 1ns/1nsmodule odd_div (    input     wire rst ,input     wire clk_in,output    wire clk_out5
);
//*************code***********//
reg[2:0]cnt;
reg clko;
always@(posedge clk_in,negedge rst)beginif(!rst)cnt<=0;elsecnt<=cnt==4?0:cnt+1;
end
always@(posedge clk_in,negedge rst)beginif(!rst)clko<=0;elseclko<=cnt<=1;
end
assign clk_out5=clko;
//*************code***********//
endmodule

自动贩售机1

状态机

`timescale 1ns/1ns
module seller1(input wire clk  ,input wire rst  ,input wire d1 ,input wire d2 ,input wire d3 ,output reg out1,output reg [1:0]out2
);
parameter s0=0,s1=1,s2=2,s3=3,s4=4,s5=5,s6=6;
reg[2:0]cs;
reg[2:0]ns;
wire[2:0]is;
assign is={d1,d2,d3};//将输入的控制信号并在一起
always@(posedge clk,negedge rst)beginif(!rst)cs<=s0;elsecs<=ns;
endalways@(*)begincase(cs)s0:begincase(is)3'b100:ns=s1;3'b010:ns=s2;3'b001:ns=s4;default:ns=ns;endcaseends1:begincase(is)3'b100:ns=s2;3'b010:ns=s3;3'b001:ns=s5;default:ns=ns;endcaseend		s2:begincase(is)3'b100:ns=s3;3'b010:ns=s4;3'b001:ns=s6;default:ns=ns;endcaseenddefault:beginns=s0;endendcase
endalways@(posedge clk,negedge rst)beginif(!rst)beginout1<=0;out2<=0;endelse begincase(ns)s3:begin out1<=1;out2<=0;ends4:beginout1<=1;out2<=1;ends5:beginout1<=1;out2<=2;ends6:beginout1<=1;out2<=3;enddefault:beginout1<=0;out2<=0;endendcaseend
end
endmodule

自动贩售机2

sel为0买第一种饮料,为1买第二种,s3时就可以买了,不过只能买第一种

一旦能买,次态就只能是0,表示这一次付款的终止,然后找零在输出去执行

输出,只能是MEALY机,即输出与当前状态以及输入信号有关,不能是MOORE机,否则状态太多

是MEALY机就是输出一方面取决于现态,一方面取决于输入信号,这里就是SEL信号,或者可以写一个二段式,

用MOORE机的话,判断输出用次态,则不能确定到底是要买什么,需要SEL以及现态共同确定一个状态才行

`timescale 1ns/1nsmodule seller2(input wire clk  ,input wire rst  ,input wire d1 ,input wire d2 ,input wire sel ,output reg out1,output reg out2,output reg out3
);
//*************code***********//parameter S0=0, S0_5=1, S1=2, S1_5=3, S2=4, S2_5=5, S3=6;reg[2:0] state, nstate;always@(posedge clk or negedge rst) beginif(~rst)state <= 0;elsestate <= nstate;endalways@(*) begincase(state)S0     : nstate = d1? S0_5:d2? S1:nstate;S0_5   : nstate = d1? S1:d2? S1_5:nstate;S1     : nstate = d1? S1_5:d2? S2:nstate;S1_5   : nstate = ~sel? S0:d1? S2:d2? S2_5:nstate;S2     : nstate = ~sel? S0:d1? S2_5:d2? S3:nstate;default: nstate = S0;endcaseendalways@(*) beginif(~rst) begin{out1, out2, out3} = 3'b000;endelse begincase(state)S0, S0_5, S1: {out1, out2, out3} = 0;S1_5        : {out1, out2, out3} = ~sel? 3'b100: 3'b000;S2          : {out1, out2, out3} = ~sel? 3'b101: 3'b000;S2_5        : {out1, out2, out3} = ~sel? 3'b101: 3'b010;S3          : {out1, out2, out3} = ~sel? 3'b101: 3'b011;default     : {out1, out2, out3} = 3'b000;endcaseendend
//*************code***********//
endmodule

游戏机计费程序

`timescale 1ns/1nsmodule game_count
(input rst_n, //异位复位信号,低电平有效input clk, 	//时钟信号input [9:0]money,input set,input boost,output reg[9:0]remain,output reg yellow,output reg red
);always@(posedge clk or negedge rst_n) beginif(~rst_n) beginyellow <= 0;red    <= 0;endelse beginyellow <= remain<10&&remain;red    <= boost? remain<2: remain<1;endendalways@(posedge clk or negedge rst_n) beginif(~rst_n) remain <= 0;else if(boost)remain <= set     ? remain+money:remain<2? remain: remain-2;elseremain <= set     ? remain+money:remain<1? remain: remain-1;end
endmodule
`timescale 1ns/1nsmodule game_count(input rst_n, //异位复位信号,低电平有效input clk, 	//时钟信号input [9:0]money,input set,input boost,output reg[9:0]remain,output reg yellow,output reg red);always@(posedge clk or negedge rst_n)beginif(~rst_n)remain <= 0;else beginif(boost==0)remain <= set==1? remain+money: remain-1;else if(boost==1)remain <= set==1? remain+money: remain-2;endendalways@(posedge clk or negedge rst_n)beginif(~rst_n)beginyellow <= 0;red <= 0;endelse beginif(remain < 1)beginyellow <= 0;red <= 1;endelse if(remain < 10)beginyellow <= 1;red <= 0;endelse beginyellow <= 0;red <= 0;endendendendmodule

这篇关于12.31信号位宽转换(整数,非整数),时钟分频(奇数,偶数,任意小数,占空比),自动售货机(1,2),游戏机的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/563621

相关文章

Linux使用dd命令来复制和转换数据的操作方法

《Linux使用dd命令来复制和转换数据的操作方法》Linux中的dd命令是一个功能强大的数据复制和转换实用程序,它以较低级别运行,通常用于创建可启动的USB驱动器、克隆磁盘和生成随机数据等任务,本文... 目录简介功能和能力语法常用选项示例用法基础用法创建可启动www.chinasem.cn的 USB 驱动

Python 标准库time时间的访问和转换问题小结

《Python标准库time时间的访问和转换问题小结》time模块为Python提供了处理时间和日期的多种功能,适用于多种与时间相关的场景,包括获取当前时间、格式化时间、暂停程序执行、计算程序运行时... 目录模块介绍使用场景主要类主要函数 - time()- sleep()- localtime()- g

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

无线路由器哪个品牌好用信号强? 口碑最好的三个路由器大比拼

《无线路由器哪个品牌好用信号强?口碑最好的三个路由器大比拼》不同品牌在信号覆盖、稳定性和易用性等方面各有特色,如何在众多选择中找到最适合自己的那款无线路由器呢?今天推荐三款路由器让你的网速起飞... 今天我们来聊聊那些让网速飞起来的路由器。在这个信息爆炸的时代,一个好路由器简直就是家庭网编程络的心脏。无论你

电脑显示hdmi无信号怎么办? 电脑显示器无信号的终极解决指南

《电脑显示hdmi无信号怎么办?电脑显示器无信号的终极解决指南》HDMI无信号的问题却让人头疼不已,遇到这种情况该怎么办?针对这种情况,我们可以采取一系列步骤来逐一排查并解决问题,以下是详细的方法... 无论你是试图为笔记本电脑设置多个显示器还是使用外部显示器,都可能会弹出“无HDMI信号”错误。此消息可能

Java将时间戳转换为Date对象的方法小结

《Java将时间戳转换为Date对象的方法小结》在Java编程中,处理日期和时间是一个常见需求,特别是在处理网络通信或者数据库操作时,本文主要为大家整理了Java中将时间戳转换为Date对象的方法... 目录1. 理解时间戳2. Date 类的构造函数3. 转换示例4. 处理可能的异常5. 考虑时区问题6.

基于C#实现将图片转换为PDF文档

《基于C#实现将图片转换为PDF文档》将图片(JPG、PNG)转换为PDF文件可以帮助我们更好地保存和分享图片,所以本文将介绍如何使用C#将JPG/PNG图片转换为PDF文档,需要的可以参考下... 目录介绍C# 将单张图片转换为PDF文档C# 将多张图片转换到一个PDF文档介绍将图片(JPG、PNG)转

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo