基于FPGA的QPSK调制(VIVADO)(2024.8.12优化工程)

原文:基于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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

睿智の男孩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值