题意整理
本题要求实现8bit数据至16bit数据的位宽转换电路,由接口电路图可知,valid_in信号会跟随指示data_in数据有效,同时要求输出valid_out信号跟随指示data_out数据。
观察时序图需要注意:
l valid_out和data_out是在两个数据输入之后的下一个时钟周期产生输出;
l 当仅有一个数据输入后,不会产生输出valid_out和data_out,而是会等待下一个数据到来之后完成两个数据的拼接,才产生输出valid_out和data_out。
题解主体
要实现8bit数据至16bit数据的位宽转换,必须要用寄存器将先到达的数据进行缓存。8bit数据至16bit数据,相当于2个输入数据拼接成一个输出数据,出于对资源的节省以及时序要求,采用1个8bit的寄存器(data_lock)进行数据缓存。
为什么不需要2个8bit的寄存器进行数据缓存:
根据时序图, data_out是在两个数据输入之后的下一个时钟周期产生输出,如果采用两个寄存器缓存两个数据,那么第二个数据还没缓存进寄存器后就要输出数据,这样不能实现时序要求的数据输出。
根据时序图,数据是在第二个数据到来之后输出,当仅有一个数据到来时,不产生输出,所以内部需要一个指示信号(flag),用来指示数据缓存状态。当data_lock内已缓存第一个数据时,flag拉高,当第二个数据到来后flag拉低。
内部时序描述如下:
根据时序图和思路整理,关键电路如下:
flag产生电路
data_lock缓存电路
valid_out产生电路
data_out产生电路
结合时序图,将电路转换成Verilog代码描述如下:
reg [7:0] data_lock; //data buffer reg flag ; //input data buff in data_lock always @(posedge clk or negedge rst_n ) begin if(!rst_n) data_lock <= 'd0; else if(valid_in && !flag) data_lock <= data_in; end //generate flag always @(posedge clk or negedge rst_n ) begin if(!rst_n) flag <= 'd0; else if(valid_in) flag <= ~flag; end //generate valid_out always @(posedge clk or negedge rst_n ) begin if(!rst_n) valid_out <= 'd0; else if(valid_in && flag) valid_out <= 1'd1; else valid_out <= 'd0; end //data stitching always @(posedge clk or negedge rst_n ) begin if(!rst_n) data_out <= 'd0; else if(valid_in && flag) data_out <= {data_lock, data_in}; end
参考答案
`timescale 1ns/1ns module 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 [7:0] data_lock; //data buffer reg flag ; //input data buff in data_lock always @(posedge clk or negedge rst_n ) begin if(!rst_n) data_lock <= 'd0; else if(valid_in && !flag) data_lock <= data_in; end //generate flag always @(posedge clk or negedge rst_n ) begin if(!rst_n) flag <= 'd0; else if(valid_in) flag <= ~flag; end //generate valid_out always @(posedge clk or negedge rst_n ) begin if(!rst_n) valid_out <= 'd0; else if(valid_in && flag) valid_out <= 1'd1; else valid_out <= 'd0; end //data stitching always @(posedge clk or negedge rst_n ) begin if(!rst_n) data_out <= 'd0; else if(valid_in && flag) data_out <= {data_lock, data_in}; end endmodule