题解 | #非整数倍数据位宽转换8to12#

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

http://www.nowcoder.com/practice/11dfedff55fd4c24b7f696bed86190b1

简析

输入:valid_in , data_in[7:0]
输出:valid_out, data_out[11:0]
alt
注意,题目给出的波形图是data_lock不是data_in。但可以大概推断出输入输出的关系。
首先设置数据暂存器data_lock,每次都存入有效的输入数据。

reg [7:0] data_lock;
always@(posedge clk or negedge rst_n) begin
    if(~rst_n)
      	data_lock <= 0;
    else
      	data_lock <= valid_in? data_in: data_lock;
end

alt
每三个有效输入可以组成两个输出,而且每个输入都会有不同的valid_outdata_out。所以可以使用三状态状态机,三种状态分别对应第一个有效输入、第二个有效输入和第三个有效输入。

parameter ONE=1, TWO=2, THREE=3;
reg [1:0] state, nstate;

always@(posedge clk or negedge rst_n) begin
    if(~rst_n)
      	state <= ONE;
    else
      	state <= nstate;
end

always@(*) begin
    if(~rst_n)
      	nstate = ONE;
    else
      	case(state)
        	ONE    : nstate = valid_in? TWO  : ONE;
        	TWO    : nstate = valid_in? THREE: TWO;
        	THREE  : nstate = valid_in? ONE  : THREE;
        	default: nstate = ONE;
      	endcase
end

三种不同状态分别对应三种不同的输出。

always@(posedge clk or negedge rst_n) begin
    if(~rst_n)
      	data_out <= 0;
    else
      	case(state)
        	ONE    : data_out <= data_out;
        	TWO    : data_out <= valid_in? {data_lock, data_in[7:4]}: data_out;
        	THREE  : data_out <= valid_in? {data_lock[3:0], data_in}: data_out;
        	default: data_out <= 0;
      	endcase
end

最后,valid_out在第二和第三个有效输入后,也就是状态TWOTHREE,才为1,且只保持一个周期就会复位。

always@(posedge clk or negedge rst_n) begin
    if(~rst_n)
      	valid_out <= 0;
    else
      	valid_out <= (state==TWO||state==THREE)&&valid_in;  //valid_in用来使valid_out只拉高一个周期
end

代码

`timescale 1ns/1ns

module 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
);
    parameter ONE=1, TWO=2, THREE=3; 
    reg [1:0] state, nstate;
    reg [7:0] data_lock;
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            state <= ONE;
        else
            state <= nstate;
    end
    
    always@(*) begin
        if(~rst_n)
            nstate = ONE;
        else
            case(state)
                ONE    : nstate = valid_in? TWO  : ONE;
                TWO    : nstate = valid_in? THREE: TWO;
                THREE  : nstate = valid_in? ONE  : THREE;
                default: nstate = ONE;
            endcase
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            data_lock <= 0;
        else
            data_lock <= valid_in? data_in: data_lock;
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            data_out <= 0;
        else
            case(state)
                ONE    : data_out <= data_out;
                TWO    : data_out <= valid_in? {data_lock, data_in[7:4]}: data_out;
                THREE  : data_out <= valid_in? {data_lock[3:0], data_in}: data_out;
                default: data_out <= 0;
            endcase
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            valid_out <= 0;
        else
            valid_out <= (state==TWO||state==THREE)&&valid_in;
    end
endmodule
Verilog篇题解 文章被收录于专栏

本人对牛客网verilog篇题目一些理解

全部评论

相关推荐

10-06 12:46
门头沟学院 Java
跨考小白:定时任务启动
点赞 评论 收藏
分享
勤奋努力的椰子这就开摆:美团骑手在美团工作没毛病
投递美团等公司10个岗位
点赞 评论 收藏
分享
16 收藏 评论
分享
牛客网
牛客企业服务