数字IC笔试题——接口转换电路(串行输入/并行输出寄存器)

题目如下:用Verilog 设计一个接口转换电路,接口timing如下图所示,假设clka频率为clkb频率的两倍(不同源,注意图中clock关系仅为示意),且两次有效访问(wra_n)的间隔时间足够长。

 方法一

按照传统的串行输入/并行输出寄存器来解决,不考虑满时钟域到快时钟域的同步打拍问题。

源代码:

module chuan_bing(

	input clka,clkb,//clka串行输入时钟,clkb并行输出时钟
	input da,//串行输入数据
	input rst_n,//异步复位低电平有效
	input wra_n,//输入使能低电平有效
	
	output [7:0]db,//并行输出
	output reg[2:0] cnt,//计数器:记录da输入的次数,从0计数,满7,wrb有效,输出并行数据
	output reg wrb//输出
);
	reg [7:0]db_reg;
//	reg wra_1,wra_2;
	assign db = (wrb)?(db_reg):8'hxx;//如果wrb有效,则db输出寄存器的值,否则输出0;
	
	//a时钟域
	//串行数据输入及存储
	always @(posedge clka, negedge rst_n) begin
		if(!rst_n) begin//如果复位,输出为0,计数器清零
			cnt <= 'b0;
			db_reg <= 8'hxx;
		end
		else if(!wra_n) begin//只在wra_n为0时 才计数
			cnt <= cnt + 'b1;
			db_reg <= {db_reg[6:0],da};
		end
	end
	
	//并行数据输出
	//快时钟域到慢时钟域需要打拍
	always @(posedge clkb, negedge rst_n) begin
		if(!rst_n)
			wrb <= 'b0;
		else if(wra_n && cnt=='b0) begin//wrb只在cnt计满值并溢出,且wra_n无效时输出
			wrb <= 'b1;
			cnt <= 'bxxx;
		end
		else if(wrb)//只让wrb有效一个周期,即输出只输出一个周期
			wrb <= 'b0;
	end
	
/*	always @(posedge clkb) begin
		wra_1 <= wra_n;
		wra_2 <= wra_1;
	end*/
	
endmodule

测试代码:

`timescale 1ns/1ns
module tb_chuan_bing;

	reg clka,clkb,da,rst_n,wra_n;
	wire [7:0] db;
	wire [2:0] cnt;
	wire wrb;
	
chuan_bing U1(
	.clka(clka),
	.clkb(clkb),
	.da(da),
	.rst_n(rst_n),
	.wra_n(wra_n),
	.db(db),
	.cnt(cnt),
	.wrb(wrb)
);
	initial begin
		clka = 0;
		clkb = 0;
		rst_n = 0;
		#5 rst_n = 1;
	end
	
			always begin 
			#10 clkb = ~clkb;
			end
			always begin 
			#5 clka = ~clka;
			end

	
	initial 
		begin
			wra_n = 1;
			#5 wra_n = 0;
			
			da = 1;#10;
			da = 1;#10;
			da = 0;#10;
			da = 0;#10;
			da = 0;#10;
			da = 0;#10;
			da = 1;#10;
			da = 1;#10;
			da = 'bx;
			wra_n = 1;
			#100;
			$stop;
		end

endmodule

仿真结果:

 仅从波形图上来看,实现了基本功能,但是没有考虑异步时钟域问题。


方法二

 源代码

module chuan_bing(

	input clka,clkb,//clka串行输入时钟,clkb并行输出时钟
	input da,//串行输入数据
	input wra_n,//输入使能低电平有效
	output reg wra_n_reg1, wra_n_reg2,
	output [7:0]db,//并行输出
	output wrb//输出
);
	reg [7:0]db_reg = 0;
//	reg wra_1,wra_2;

	
	//a时钟域
	//串行数据输入及存储
	always @(posedge clka) begin
		if(!wra_n) begin//只在wra_n为0时 才计数
			db_reg <= {db_reg[6:0],da};
		end
	end
	
	//并行数据输出
	//快时钟域到慢时钟域需要打拍
	//reg wra_n_reg1, wra_n_reg2;
	always @(posedge clkb) begin
		wra_n_reg1 <= wra_n ;
		wra_n_reg2 <= wra_n_reg1 ;
	end
	
	
	wire wra_n_check ; 
	assign wra_n_check = wra_n_reg1 &&(!wra_n_reg2); //异或亦可以
	assign wrb = wra_n_check ; 
	assign db = (wra_n_check == 1'b1) ? db_reg : 0;

	
endmodule

 仿真代码:

`timescale 1ns/1ns
module tb_chuan_bing;
	reg clka ;
	reg wra_n;
	reg da ;
	reg clkb ;
	wire [7:0] db ;
	wire wrb ;
	wire wra_n_reg1, wra_n_reg2;

	initial begin
		clka  = 0 ;
		#3 ;
		clkb  = 0 ; 
	end
	initial begin
		wra_n = 1 ;
		@(posedge clka) wra_n = 0 ;
		da = $random%2 ;

		@(posedge clka) wra_n = 0 ;
		da = $random%2 ;

		@(posedge clka) wra_n = 0 ;
		da = $random%2 ;

		@(posedge clka) wra_n = 0 ;
		da = $random%2 ;

		@(posedge clka) wra_n = 0 ;
		da = $random%2 ;

		@(posedge clka) wra_n = 0 ;
		da = $random%2 ;

		@(posedge clka) wra_n = 0 ;
		da = $random%2 ;

		@(posedge clka) wra_n = 0 ;
		da = $random%2 ;

		@(posedge clka) wra_n = 1;

	end
always #5 clka = ~clka ; 
always #10 clkb = ~clkb ; 


chuan_bing my_chuan_bing (
	.clka(clka) ,
	.wra_n(wra_n),
	.da(da) , 
	.clkb(clkb) ,
	.db(db) , 
	.wrb(wrb),
	.wra_n_reg1(wra_n_reg1), 
	.wra_n_reg2(wra_n_reg2)
);


endmodule

仿真结果:

  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cheeky_man

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值