前言:
本专栏旨在记录高频笔面试手撕代码题,以备数字前端秋招,本专栏所有文章提供原理分析、代码及波形,所有代码均经过本人验证。
目录如下:
10.数字IC手撕代码-数据位宽转换器(宽-窄,窄-宽转换)
13.数字IC手撕代码-流水握手(利用握手解决流水线断流、反压问题)
18.数字IC手撕代码-双端口RAM(dual-port-RAM)
...持续更新
更多手撕代码题可以前往 数字IC手撕代码--题库
目录
题目描述
使用HDL实现脉冲密度调制(PDM),即根据输入12bit pdm_in,按下列要求输出不同占空比的方波:
① 当pdm_in>10,pdm_out即输出的波形占空比为4/pdm_in;
② 当pdm_in<=10,pdm_out不翻转输出固定值。
其输入输出接口为:
input clk;
input [11:0]pdm_in;
input reset;
output pdm_out;
解决思路
脉冲密度调制(PDM),通过调节波形的占空比来改变脉冲的密度。信号逻辑为高的时间T_hign除以周期T_cycle所得到的比值叫做占空比。
实现第一个要求,当pdm_in>10时,可以让新信号在4个clk周期为高,在(pdm_in-4)个clk周期为低,这样就实现了一个pdm_in分频,占空比为4/pdm_in。
第二个要求,当pdm_in<=10时,pdm_out就不让他翻转,并且让实现分频的计数器清零。
代码
module pdm(
input clk ,
input [11:0] pdm_in ,
input reset ,
output pdm_out
);
reg pdm_processed;
reg [11:0] count;
always @(posedge clk)begin
if(reset)begin
pdm_processed <= 1'd0;
end
else if(pdm_in > 10)begin
if(count <= 3)
pdm_processed <= 1'b1;
else if(count < pdm_in -1)
pdm_processed <= 1'b0;
else if(count == pdm_in-1)
pdm_processed <= 1'b0;
end
else begin // pdm_in <= 10
pdm_processed <= pdm_processed; //stay
end
end
always @(posedge clk)begin
if(reset)begin
count <= 12'd0;
end
else begin
if(pdm_in > 10 && count < pdm_in-1)begin
count <= count + 1'b1;
end
else if(pdm_in > 10 && count == pdm_in-1)begin // one pdm_out cycle finish
count <= 12'd0;
end
else begin // pdm_in <= 10
count <= 12'd0;
end
end
end
assign pdm_out = pdm_processed;
endmodule
testbench
module pdm_tb();
reg clk,reset;
wire pdm_out;
always #5 clk = ~clk;
reg [11:0] pdm_in;
initial begin
clk <= 1'b0;
reset <= 1'b1;
pdm_in <= 12'd0;
#20
reset <= 1'b0;
#20
pdm_in <= 12'd20;
#400
pdm_in <= 12'd12;
#240
pdm_in <= 12'd5;
#50
pdm_in <= 12'd12;
#30
pdm_in <= 12'd5;
#200
$finish();
end
//dump fsdb
initial begin
$fsdbDumpfile("pdm.fsdb");
$fsdbDumpvars(0);
end
pdm u_pdm(
.clk (clk) ,
.pdm_in (pdm_in),
.reset (reset) ,
.pdm_out(pdm_out)
);
endmodule
输出波形
从波形中可以看到我们设置了pdm_in = 20,pdm_out如我们所想,输出为占空比4/20的方波。当设置pdm_in = 12时,pdm_out输出为占空比4/12的方波。当设置pdm_in < 10时,dpm_out保持原来的状态不变。
更多手撕代码题可以前往 数字IC手撕代码--题库