题解 | #非整数倍数据位宽转换8to12#
非整数倍数据位宽转换8to12
http://www.nowcoder.com/practice/11dfedff55fd4c24b7f696bed86190b1
简析
输入:valid_in , data_in[7:0]
输出:valid_out, data_out[11:0]
注意,题目给出的波形图是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
每三个有效输入可以组成两个输出,而且每个输入都会有不同的valid_out
和data_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
在第二和第三个有效输入后,也就是状态TWO
和THREE
,才为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篇题目一些理解