原文:基于FPGA的QPSK调制(VIVADO)-CSDN博客
//2024/8/12更新日记:根据前述优化方向进行优化,缩减了ROM大小,省略四个并行寄存器。
优化后代码如下:
QPSK调制模块修改如下:
module QPSK(
input sys_clk,
input sys_rst_n,
input data_clk,
input data_in,
output reg sw,
output [7:0]data_out,
output data_out_clk
);
reg [1:0]data_buffer=0;
reg [3:0]thera=0;
reg [3:0]now_thera=0;
wire carry_signal_clk;//载波频率
always @(negedge data_clk or negedge sys_rst_n)//串并转换
begin
if(sys_rst_n == 1'b0)
begin
data_buffer <= 2'd0;
sw<=1'd1;
end
else
begin
data_buffer[sw]=data_in;
sw<=~sw;
end
end
reg thera_cnt=0;
always @(posedge data_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
begin
thera<=4'd0;
end
else if(sw==1'd1)//接收完两bit数据
begin
case (data_buffer)
2'b00:
thera<={thera[1:0],2'd0};
2'b01:
thera<={thera[1:0],2'd1};
2'b10:
thera<={thera[1:0],2'd2};
2'b11:
thera<={thera[1:0],2'd3};
endcase
end
end
reg [7:0]rd_addr=0;
reg [7:0]rd_addr1=0;
reg [7:0]addr_thera_buf=0;
always @(thera)
begin
if(sys_rst_n == 1'b0)
addr_thera_buf<=8'd0;
else
begin
if(thera[1:0]==thera[3:2])
addr_thera_buf<=addr_thera_buf;
else
addr_thera_buf<=(thera[1:0]-thera[3:2])*8'd64;//根据相移量获取地址偏移量
end
end
always @(posedge data_out_clk or negedge sys_rst_n)//生成基础ROM地址
begin
if(sys_rst_n == 1'b0)
begin
rd_addr1<=8'd32;
rd_addr<=8'd32;
end
else
begin
rd_addr1<=rd_addr1+1'b1;//基础地址
rd_addr<=rd_addr1+addr_thera_buf;//基础地址加上地址偏移量后获得基础ROM地址
end
end
reg [5:0]addr_to_ROM;//实际输入到ROM的地址
reg out_flag=1'd0;//输出波形正负极性标志位
always @(posedge data_out_clk or negedge sys_rst_n)//将0~255的基础地址映射为0~63实际输入到ROM的地址
begin
if(sys_rst_n == 1'b0)
begin
addr_to_ROM<=6'd0;
out_flag<=1'd0;
end
else
begin
if(rd_addr<8'd64)
begin
addr_to_ROM<=rd_addr;
out_flag<=1'd0;//输出数据为正
end
else if(rd_addr<8'd128)
begin
addr_to_ROM<=8'd127-rd_addr;
out_flag<=1'd0;//输出数据为正
end
else if(rd_addr<8'd192)
begin
addr_to_ROM<=rd_addr-8'd128;
out_flag<=1'd1;//输出数据为负
end
else
begin
addr_to_ROM<=9'd255-rd_addr;
out_flag<=1'd1;//输出数据为负
end
end
end
data_clock u_data_clock
(
// Clock out ports
.clk_out1(data_out_clk),
// Status and control signals
.reset (~sys_rst_n),
.locked (),
// Clock in ports
.clk_in1 (sys_clk)
);
wire [7:0]ROM_data_out;//ROM输出原始数据
assign data_out=ROM_data_out*(out_flag?-1:1);//添加极性后获得实际输出波形
//ROM存储波形
cos_64 u_cos_64(
.addra (addr_to_ROM),
.clka (data_out_clk),
.douta (ROM_data_out)
);
endmodule
MATLAB脚本更新为:
clear,clc;
N = 64 ;%数据深度
y = zeros(N , 1) ;%生成100行*1列的矩阵
y_integer = zeros(N , 1) ;%生成100行*1列的矩阵
y_hex = zeros(N , 1) ;%生成100行*1列的矩阵,十六进制
for i = 1:1:N %循环1~N,累加1
x = i-1 ;
y(i,1) = ceil( 127*sin(x*2*pi/256) ) ;%ceil为四舍五入函数,输出范围为-127~127的正弦波数据
end
subplot(211);
plot(y);%画图预览
title("原始波形");
axis([-10,260,-130,130]);
fid = fopen('cos_64point_new.coe','wt'); %创建一个名为cos_100point.coe的文件
%- COE 文件前置格式
fprintf( fid, 'MEMORY_INITIALIZATION_RADIX = 16;\n'); %coe文件数据为16进制
fprintf( fid, 'MEMORY_INITIALIZATION_VECTOR =\n');
%- 写数据
y_integer=y+127;
y_hex= dec2hex(y_integer);
subplot(212);
plot(y_integer);
title("存入数据");
axis([-10,260,-10,260]);
for i = 1:1:N
if(i == N)
%最后一个点时,标点为分号,其余时候为逗号
fprintf(fid,'%c%c;',y_hex(i,1),y_hex(i,2)); %输出16进制数据
else
fprintf(fid,'%c%c,\n',y_hex(i,1),y_hex(i,2)); %输出16进制数据
end
end
fclose(fid);%关闭文件
此外其他部分代码与优化原理参考原文:基于FPGA的QPSK调制(VIVADO)-CSDN博客
优化后的完整工程:https://download.csdn.net/download/glassca/89632853?spm=1001.2014.3001.5501