前言:
本专栏旨在记录高频笔面试手撕代码题,以备数字前端秋招,本专栏所有文章提供原理分析、代码及波形,所有代码均经过本人验证。
目录如下:
10.数字IC手撕代码-数据位宽转换器(宽-窄,窄-宽转换)
13.数字IC手撕代码-流水握手(利用握手解决流水线断流、反压问题)
18.数字IC手撕代码-双端口RAM(dual-port-RAM)
...持续更新
更多手撕代码题可以前往 数字IC手撕代码--题库
目录
题目描述
用 HDL 语言按照节省芯片面积的方式实现交织器,假定输入的数据 datain 顺序为 1、2、 3、…63,输入使能为 datain_ena,经交织器后输出的顺序要求为 1、10、19、28、37、 46、55、2、11、…
即行列交织,按行的顺序进按列的顺序出,输入输出数据均按时钟沿变化。实现时可自己 定义 ram 使用。
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18
19 20 21 22 23 24 25 26 27
28 29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44 45
46 47 48 49 50 51 52 53 54
55 56 57 58 59 60 61 62 63
解题思路
读题意得知,输入64个数,存成一个7*9的矩阵,然后按列输出。把题意转换一下,这里题目中所谓的交织器,其实就是实现一个矩阵转置的功能。把按行输入的矩阵,按列输出,并给出数据写入和读出有效使能。
代码
module matrix_trans(
input clk ,
input rstn ,
input [5:0] datain ,
input datain_ena ,
output [5:0] dataout ,
output reg dataout_ena
);
reg [5:0] ram [62:0]; //63 numbers
reg [5:0] addr_wr,addr_rd;
// write data
always @(posedge clk)begin
if(!rstn)begin
addr_wr <= 6'd0;
end
else if(datain_ena && addr_wr < 62)begin
addr_wr <= addr_wr + 1'b1;
end
else if(datain_ena && addr_wr ==62)begin
addr_wr <= 6'd1;
end
end
always @(posedge clk)begin
if(datain_ena)begin
ram[addr_wr] <= datain;
end
end
// read data
always @(posedge clk)begin
if(!rstn)begin
dataout_ena <= 1'b0;
end
else if(addr_rd == 6'd62)begin
dataout_ena <= 1'b0;
end
else if(addr_wr == 6'd62 && datain_ena == 1'b1)begin
dataout_ena <= 1'b1;
end
end
always @(posedge clk)begin
if(!rstn)begin
addr_rd <= 6'd0;
end
else if(dataout_ena==1'b1 && addr_rd < 62)begin
addr_rd <= addr_rd + 1'b1;
end
else if(dataout_ena==1'b1 && addr_rd == 62)begin
addr_rd <= 6'd0;
end
end
// 9*7
// 0=0,1=9,2=18,3=27,4=36,5=45,6=54, 7=1
assign dataout = ram[((addr_rd)%7)*9+addr_rd/7];
endmodule
testbench
module matrix_trans_tb();
reg clk,rstn;
reg [5:0] datain;
reg datain_ena;
wire [5:0] dataout;
wire dataout_ena;
always #5 clk = ~clk;
initial begin
clk <= 1'b0;
rstn <= 1'b0;
#20
rstn <= 1'b1;
#20
datain <= 6'd1;
#20
datain_ena <= 1'b1;
repeat(63)begin
@(posedge clk)begin
datain <= datain + 1'b1;
end
end
datain_ena <= 1'b0;
#2000
$finish();
end
initial begin
forever begin
@(posedge clk)begin
if(dataout_ena == 1'b1)begin
$display("dataout = %d", dataout);
end
end
end
end
//dump fsdb
initial begin
$fsdbDumpfile("matrix_trans.fsdb");
$fsdbDumpvars(0);
end
matrix_trans u_matrix_trans(
.clk (clk) ,
.rstn (rstn) ,
.datain (datain) ,
.datain_ena (datain_ena) ,
.dataout (dataout) ,
.dataout_ena (dataout_ena)
);
endmodule
波形
我们完成了按照矩阵行的形式,写入63个数,按照矩阵列的方式读出63个数,读出结果如图所示:
输出正确。
更多手撕代码题可以前往 数字IC手撕代码--题库