基于Verilog的PCM编码实验

实验目的

1.使用EDA技术和硬件描述语言(Verilog)实现现代通信技术中的PCM编码技术。

2.加深对课程所学EDA技术以及PCM编码过程的理解。

实验原理

  1. PCM(Pulse Code Modulation)脉冲编码调制是数字通信的编码方式之一。主要过程是将话音、图像等模拟信号每隔一定时间进行取样,使其离散化,同时将抽样值按分层单位四舍五入取整量化,同时将抽样值按一组二进制码来表示抽样脉冲的幅值。
    2.FPGA中的ROM是一种只读存储器,主要用来存储固化的初始化配置数据。在本实验中,使用ROM(Read-Only Memory)来存储模拟信号的样值。
    3.ROM中的模拟信号样值数据用Matlab生成mif文件,再将此文件添加至ROM核中。
    4.A律13折线近似法:

A律13折线
首先对信号幅值进行归一化处理,即信号的幅值在±1之间。
0~1范围 一分为二,中间点为1/2,取1/2~1之间为第八段
0~1/2范围 一分为二,中间点为1/4,取1/4~1/2为第七段
0~1/4范围 一分为二,中间点为1/8,取1/8~1/4为第六段
0~1/8范围 一分为二,中间点为1/16,取1/16~1/8为第五段
0~1/16范围 一分为二,中间点为1/32,取1/32~1/16为第四段
0~1/32范围 一分为二,中间点为1/64,取1/64~1/32为第三段
0~1/64范围 一分为二,中间点为1/128,取1/128~1/64为第二段
0~1/128范围 ,取0~1/128为第一段。
最后将每个(非均匀)线段再均匀分为16个量化间隔(0~15),这样共有16*16=256个量化级(话音)。
最小量化间隔△:第八段落长度最短,长度为1/128,段内再16等分,每一个小段就是1/2048,这就是最小量化间隔△。

5.八位折叠码:
C1为极性码, C2 C3 C4 为段落码, C5 C6 C7 C8为段内码;具体规则为:抽样值大于0,则极性码为1,小于0则极性码为0。
在这里插入图片描述
在这里插入图片描述

实验原理框图

在这里插入图片描述
具体编码过程的状态机框图

实验步骤

1、由于PCM编码过程输入的是模拟信号,所以要用ModelSim输出一段模拟信号,这里使用Quartus软件的ROM核来存储模拟信号的样值。样值的输入采用Matlab生成mif文件,再将文件导入ROM核中。在设置ROM核时可以选择自动生成ROM.v文件,将其作为底层模块。
2、顶层模块的设计:使用状态机进行PCM的编码过程,采用8位码。

代码部分

rom.v

module rom (
	address,
	clock,
	q);//自动生成的rom.v文件

	input	[11:0]  address;
	input	  clock;
	output	[11:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1	  clock;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

	wire [11:0] sub_wire0;
	wire [11:0] q = sub_wire0[11:0];

	altsyncram	altsyncram_component (
				.address_a (address),
				.clock0 (clock),
				.q_a (sub_wire0),
				.aclr0 (1'b0),
				.aclr1 (1'b0),
				.address_b (1'b1),
				.addressstall_a (1'b0),
				.addressstall_b (1'b0),
				.byteena_a (1'b1),
				.byteena_b (1'b1),
				.clock1 (1'b1),
				.clocken0 (1'b1),
				.clocken1 (1'b1),
				.clocken2 (1'b1),
				.clocken3 (1'b1),
				.data_a ({12{1'b1}}),
				.data_b (1'b1),
				.eccstatus (),
				.q_b (),
				.rden_a (1'b1),
				.rden_b (1'b1),
				.wren_a (1'b0),
				.wren_b (1'b0));
	defparam
		altsyncram_component.address_aclr_a = "NONE",
		altsyncram_component.clock_enable_input_a = "BYPASS",
		altsyncram_component.clock_enable_output_a = "BYPASS",
		altsyncram_component.init_file = "sin_code.mif",
		altsyncram_component.intended_device_family = "Cyclone IV E",
		altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
		altsyncram_component.lpm_type = "altsyncram",
		altsyncram_component.numwords_a = 4096,
		altsyncram_component.operation_mode = "ROM",
		altsyncram_component.outdata_aclr_a = "NONE",
		altsyncram_component.outdata_reg_a = "CLOCK0",
		altsyncram_component.widthad_a = 12,
		altsyncram_component.width_a = 12,
		altsyncram_component.width_byteena_a = 1;


endmodule

代码解释:这里rom模块中定义了两个输入变量clock(时钟)和address(地址),和一个输出变量q,当到达时钟上升沿时会输出当前地址下的值。这个模块在本实验中将作为子模块被顶层模块调用。
顶层模块

module  PCM(
					input clk,
					input rst_n,
					input [11:0] address1,address2,
					input [11:0] data,
					output [11:0] readdata1,readdata2,
					output reg [7:0]  pcm );
rom	rom_inst1 (
	.address ( address1 ),
	.clock ( clk ),
	.q ( readdata1 )
	);
rom	rom_inst2 (
	.address ( address2 ),
	.clock ( clk ),
	.q ( readdata2 )
	);

reg [5:0] state;
integer mid1,mid2;
always@(clk)
begin 
	mid1=data;
	mid2=mid1-2047;
	
	if(!rst_n)
	begin
	state<='b000_000;
	end
	else 
	begin	
//极性码部分
	if(mid2>0)
	begin mid1=mid2;pcm[7]=1;end
	else
	begin mid1=-mid2;pcm[7]=0;end
//段落码部分
	case(state)
	'b000_000:
	begin
	state='b000_001;
	end
	'b000_001:
	begin
	if(mid1>=128)	//处于后4段
	begin pcm[6]=1;state='b100_010;end
        else
	begin pcm[6]=0;state='b000_010;end//处于前4段
	end
	'b100_010:
	begin
	if(mid1>=512)	//处于后四段中的后两段
	begin pcm[5]=1;state='b100_011;end
        else//处于后四段中的后两段
	begin pcm[5]=0;state='b000_011;end
	end
	'b000_010:
	begin
	if(mid1>=32)//处于前四段中的后两段	
	begin pcm[5]=1;state='b100_100;end
        else//处于前四段中的前两段
	begin pcm[5]=0;state='b000_100;end
	end
        
	'b100_011:
	begin
	if(mid1>=1024)	//处于第八段
	begin pcm[4]=1;state='b111_000;end
        else//处于第七段
	begin pcm[4]=0;state='b110_000;end
	end
	'b000_011:
	begin
	if(mid1>=256)	//处于第六段
	begin pcm[4]=1;state='b101_000;end
        else//处于处于第五段
	begin pcm[4]=0;state='b100_000;end
	end
	'b100_100:
	begin
	if(mid1>=64)	//处于第四段
	begin pcm[4]=1;state='b011_000;end
        else//处于第三段
	begin pcm[4]=0;state='b010_000;end
	end
	'b000_100:
	begin
	if(mid1>=16)	//处于第二段
	begin pcm[4]=1;state='b001_000;end
        else//处于第一段
	begin pcm[4]=0;state='b000_111;end
	end
//段内码部分
	'b111_000: //第八段段内编码
	begin
	pcm[3:0]=(mid1-1024)/64;
	state='b000_000;
	end
	'b110_000: //第七段段内编码
	begin
	pcm[3:0]=(mid1-512)/32;
	state='b000_000;
	end
	'b101_000: //第六段段内编码
	begin
	pcm[3:0]=(mid1-256)/16;
	state='b000_000;
	end
	'b100_000: //第五段段内编码
	begin
	pcm[3:0]=(mid1-128)/8;
	state='b000_000;
	end
	'b011_000: //第四段段内编码
	begin
	pcm[3:0]=(mid1-64)/4;
	state='b000_000;
	end
	'b010_000: //第三段段内编码
	begin
	pcm[3:0]=(mid1-32)/2;
	state='b000_000;
	end
	'b001_000: //第二段段内编码
	begin
	pcm[3:0]=(mid1-16)/1;
	state='b000_000;
	end
	'b000_111: //第一段段内编码
	begin
	pcm[3:0]=(mid1)/1;
	state='b000_000;
	end
	endcase
end
end

endmodule

代码解释:在此模块中,共两次例化了rom模块,一次是输出模拟信号,另外一次是进行信号抽样。除了例化外,就是PCM编码函数。由于A律13折线法正值和负值部分各2048个量化电平,而输入的模拟信号的幅值是0-4096,所以在量化时,将大于2048的减去2048量化为正电平,小于2048的减去2048量化为负电平,正好可以对应PCM量化时的正负各2048个量化电平。

实验结果

1、输出模拟信号波形图

在这里插入图片描述
2、采样波形图

在这里插入图片描述

3、具体采样值

在这里插入图片描述
4、量化值
在这里插入图片描述
5、PCM编码输出
在这里插入图片描述
6、全部仿真波形图

在这里插入图片描述

实验所用软件

Quartus (Quartus Prime 18.1) Lite Edition
ModelSim - Intel FPGA Starter Edition 10.5b (Quartus Prime 18.1)
Matlab 2022

  • 51
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值