关于我们的板子的一些记录

开始在板子上调试程序的时候,所有的东西都是在电脑上进行的,并没有固化到板子里去~


把CCSv5安装到  文件系统   下面的 /opt/ti  下

把我们的工程文件夹 ccs_v5 也放到 /opt下, 那么 就可以设置 CCS 的工作目录为 /opt/ccs_v5 啦~


之前的时候,我们做过 nfs  和 tftp 的配置。。。。。它们都位于 /opt 下, 

在tftp 下面 放了 一个 uImage , 它相当于板子的操作系统, 就像我们的PC 上的 windows  linux 一样,uImage 才 1.3M ^_^, 很小的OS 吧


在板子运行的时候,我们就可以通过tftp服务把这个  uImage 下载到板子上,板子就可以运行了。方法如下:

【不记得了,不解得了啊‵‵‵‵‵‵‵‵  委屈 ‵‵‵‵‵‵‵  貌似是 uboot一下,然后。。。。。。。。详细点,还是把光盘下的各个用户手册都仔细看完吧。。。。】

有了操作系统后,我们还需要  根文件系统  ,这类似我们电脑上的 C D E 盘~

在DM6447光盘下面有一个 rootfs.tar.gz ,把它 解压 ( #  tar  zxfs rootfs.tar.gz )到opt 下面 (应该会生成一个新的 nfs 目录)这就相当于各个硬盘的分区了~~

[这个要特别注意,我开始的时候,是解压了copy过去的~~~后来发现,nfs老是有问题,问了大牛才知道  nfs 不支持copy, 必须把 SDK 复制到opt下面,然后用命令  tar -zxvf ccs.tar.gz  解压,这样,dvsdk_1_40_02_33   和    mv_pro_4.0.1   会自然解压到 /opt下, nfs 也在 opt 下了~~]

这样,运行程序的时候,会发现有错误(错误记不清楚了,不及时做笔记,不行啊,,,,,忘性好大快哭了) 这个问题是由于跟文件系统引起的,

解决的办法就是 在 DM6467 光盘下面的  /Davinci Linux Develop Software  目录下面,有一个 SEED-DVS6467_SDK.tar.gz  把它解压到 /opt 目录下,会生成一个 新的 nfs ,用它替换以前的nfs 根文件系统 就 OK 啦~ ^_^ 另外,还得到了两个文件夹 dvsdk_1_40_02_33   和    mv_pro_4.0.1 。其中后面那个 有 ARM v5t交叉编译目录,有Linux 呢河源嘛目录 ,而前面那个是DVSDK 目录。




==================================================================================

在板子上运行程序:

service tftp-hpa restart   // 重启tftp服务

kermit   //这个服务 反正 ubuntu里面是没有的,需要自己配置

connect  //PC与板子进行连接

cd  /opt/ XXX   //这是程序应该存放的位置 (我们的程序是直接让生成的可执行文件在这个opt 下的 seed 下~~)

./ load````     ./ ````      //分别是加载内核和运行程序


==================================================================================

kermit的配置:

这个配置很简单,在命令行下写  kermit  的时候,就会  提示 你一条安装命令:

apt-get install ckermit

主要问题在于配置.mykermrc (前面的 .  是隐藏文件的意思, ctrl + h 就可以显示所有的隐藏文件)

.mykermrc 文件应该放在用户当前的主文件夹下:

root权限的,就在root 下:

没有这个文件的话,就新建一个,然后进行编辑:


set line /dev/ttyUSB0

set speed 115200

set carrier-watch off

set handshake none

set flow-control none

robust

set file type bin

set file name lit

set rec pack 1000

set send pack 1000

set window 5


```` 注意第一句话,一般都会写   set line    /dev/ttyS0    ,这应该是普通的串口线吧。。。。。我们使用的是USB 连接板子的,所以应该改成ttyUSB0 

保存之后,再 在 终端中 kermit 就OK 了。。。



<think>我们已知目标:使用50MHz时钟生成100kHz正弦波,通过MIF文件配置ROM,并在Modelsim中仿真。 根据DDS原理,输出频率公式为:$$ f_{out} = \frac{f_{clk} \times K}{2^N} $$ 其中: - f_clk = 50 MHz = 50,000,000 Hz - f_out = 100 kHz = 100,000 Hz - N为相位累加器位数(通常取32位,以获得较高的频率分辨率) - K为频率控制字 计算K: $$ K = \frac{f_{out} \times 2^N}{f_{clk}} = \frac{100000 \times 2^{32}}{50000000} $$ 计算过程: - 2^32 = 4294967296 - 100000 * 4294967296 = 429496729600000 - 429496729600000 / 50000000 = 8589934.592 ≈ 8589935(四舍五入取整) 因此,K ≈ 8589935 接下来,我们需要生成一个包含正弦波一个周期采样点的MIF文件。假设我们使用256个采样点(即地址位宽8位),数据位宽为8位(0-255对应0-2π的正弦值,量化到0-255范围,实际使用中也可以是有符号数,但这里为简单起见用无符号数)。 生成MIF文件的方法(以Matlab为例): n = 0:255; sine = sin(2*pi*n/256); % 一个周期的正弦波 % 将正弦波归一化到[0,1]再乘以255,然后取整(无符号) sine_quantized = round((sine + 1) * 127.5); % 这样最小值0对应-1,最大值255对应+1,但实际我们通常用128作为零点(偏移),所以另一种常用方式是用有符号数,但这里我们按无符号输出 但是注意:如果DAC需要的是有符号数,则应该生成有符号数。这里我们假设DAC是无符号的,所以将正弦波偏移到0以上。 然而,更常见的做法是ROM中存储的是有符号数,然后在DDS模块输出后根据需要转换。但为了简单,我们可以按无符号数存储。 另一种方式(也是常见方式):我们存储有符号数,然后将其转换为无符号数(即加上偏移)输出。但这里我们直接生成无符号的MIF文件。 修改:我们生成有符号数(-128到127)然后加上128变成无符号(0-255)。这样方便后续如果有符号DAC使用。 因此,我们生成有符号数再转换: sine_signed = round(127 * sin(2*pi*n/256)); % 范围-127到127(注意:127是最大值,因为sin最大值1,127*1=127) % 但是为了使用8位有符号数的整个范围,我们通常用-128到127,但这里sin最大值是1,所以用127*1=127,最小值-127。 % 为了用满量程,我们可以乘以127(这样不会溢出)。然后再加上128,变成0-255。 所以: sine_unsigned = sine_signed + 128; 但是注意,这样最小值-127+128=1,最大值127+128=255,并没有覆盖0和255?所以我们可以调整幅度为127.5,但这样会溢出。所以我们还是用127作为幅度。 或者,我们直接用128作为零点,那么: sine_unsigned = 128 + round(127 * sin(2*pi*n/256)); 这样,当sin=1时,值为128+127=255;当sin=-1时,值为128-127=1。所以范围是1到255,中间值是128。这样也可以。 但这样会损失两个值(0和256,但256就是0?),实际上我们不可能同时覆盖0和255,因为正弦波对称。所以这样也可以。 因此,我们生成MIF文件的数据为:128 + round(127 * sin(2*pi*n/256)) 用Matlab代码生成MIF文件: ```matlab n = 0:255; sine = sin(2*pi*n/256); sine_quantized = 128 + round(127 * sine); % 这样得到0-255之间的整数(实际范围1-255,但0不会出现?因为sin最小值-1时,128-127=1,所以不会出现0,但没关系) fid = fopen('sine_100khz.mif', 'w'); fprintf(fid, 'DEPTH = 256;\n'); fprintf(fid, 'WIDTH = 8;\n'); fprintf(fid, 'ADDRESS_RADIX = DEC;\n'); fprintf(fid, 'DATA_RADIX = DEC;\n'); fprintf(fid, 'CONTENT\n'); fprintf(fid, 'BEGIN\n'); for i = 1:256 fprintf(fid, '%d : %d;\n', i-1, sine_quantized(i)); end fprintf(fid, 'END;\n'); fclose(fid); ``` 这样,我们就生成了MIF文件。 然后,我们编写Verilog代码: 1. 相位累加器模块(32位) 2. ROM模块,用MIF文件初始化,输入为相位累加器的高8位(因为我们有256个点,所以用高8位[31:24]作为ROM地址) 3. 顶层模块 注意:相位累加器在50MHz时钟下工作,每次累加K(8589935)。 代码示例: ```verilog // 相位累加器模块 module phase_accumulator ( input clk, // 50MHz input reset, input [31:0] K, // 频率控制字 output reg [31:0] phase ); always @(posedge clk or posedge reset) begin if (reset) phase <= 32'd0; else phase <= phase + K; end endmodule // ROM模块,使用MIF文件初始化 module sine_rom ( input [7:0] addr, output reg [7:0] data ); reg [7:0] rom[0:255]; initial begin $readmemh("sine_100khz.mif", rom); // 注意:如果mif文件是十进制数据,也可以用readmemh,但要求mif文件中的数值是十六进制?实际上,readmemh读取十六进制,readmemb读取二进制,但如果我们用十进制数据,我们可以用$readmemb?但通常我们用$readmemh读取十六进制格式的mif文件,或者用$readmemb读取二进制格式。但是,我们也可以使用$readmemb读取十进制?实际上,readmem系列函数不支持十进制。 因此,我们需要将MIF文件的数据写成十六进制。或者,我们可以用$readmemh,但要求MIF文件中的数据是十六进制。 所以,我们修改Matlab生成十六进制数据的MIF文件,或者生成十六进制格式的MIF文件。 但为了简便,我们可以将MIF文件的数据部分用十六进制表示。修改Matlab代码: 将写入数据部分改为十六进制: fprintf(fid, '%d : %d;\n', i-1, sine_quantized(i)); // 这里还是十进制 如果我们希望用十六进制,可以: fprintf(fid, '%d : %x;\n', i-1, sine_quantized(i)); 或者,我们也可以使用readmemb,但要求二进制字符串,比较麻烦。 因此,我们使用$readmemh,但要求MIF文件中的数值是十六进制。所以修改生成MIF文件的代码: 将原来的数据写入行改为: fprintf(fid, '%d : %x;\n', i-1, sine_quantized(i)); 这样,在ROM中就可以用$readmemh读取。 但是,注意:在MIF文件中,地址也可以用十六进制,但上面我们地址用十进制(ADDRESS_RADIX=DEC),数据用十六进制(DATA_RADIX=HEX)?实际上,在MIF文件中,地址的进制由ADDRESS_RADIX决定,数据的进制由DATA_RADIX决定。所以我们可以这样写: 修改MIF文件头: ADDRESS_RADIX = DEC; DATA_RADIX = HEX; 然后数据部分用十六进制数。 因此,Matlab代码修改为: ```matlab fid = fopen('sine_100khz.mif', 'w'); fprintf(fid, 'DEPTH = 256;\n'); fprintf(fid, 'WIDTH = 8;\n'); fprintf(fid, 'ADDRESS_RADIX = DEC;\n'); fprintf(fid, 'DATA_RADIX = HEX;\n'); % 数据用十六进制 fprintf(fid, 'CONTENT\n'); fprintf(fid, 'BEGIN\n'); for i = 1:256 fprintf(fid, '%d : %x;\n', i-1, sine_quantized(i)); end fprintf(fid, 'END;\n'); fclose(fid); ``` 这样,ROM模块就可以用$readmemh读取。 但是,注意:$readmemh要求文件中的数据是十六进制,而我们的数据是0-255,用两位十六进制数表示,所以没有问题。 因此,ROM模块代码: ```verilog module sine_rom ( input [7:0] addr, output reg [7:0] data ); reg [7:0] rom[0:255]; initial begin $readmemh("sine_100khz.mif", rom); end always @(addr) begin data = rom[addr]; end endmodule ``` 顶层模块: ```verilog module dds_top ( input clk, // 50MHz input reset, // 复位,高电平有效 output [7:0] dout // 正弦波输出(无符号) ); wire [31:0] phase; wire [7:0] rom_addr; phase_accumulator pa_inst ( .clk(clk), .reset(reset), .K(32'd8589935), // 频率控制字 .phase(phase) ); // 取相位累加器的高8位作为ROM地址 assign rom_addr = phase[31:24]; // 因为32位,我们取最高8位(因为相位累加器相当于一个循环计数器,高8位变化最快) sine_rom rom_inst ( .addr(rom_addr), .data(dout) ); endmodule ``` 注意:相位累加器的高8位作为地址,这是因为相位累加器的位数(32位)远大于ROM地址需要的位数(8位),所以用高8位相当于将整个相位周期(2^32)分成256份,每份代表一个相位区间,然后每个区间取一个点。这样,随着相位累加,地址会以K的高8位增量跳跃,从而读取ROM中的点。 然后,我们编写Testbench进行仿真。 Testbench(dds_tb.v): ```verilog `timescale 1ns / 1ps module dds_tb; reg clk; reg reset; wire [7:0] dout; dds_top uut ( .clk(clk), .reset(reset), .dout(dout) ); // 生成50MHz时钟 initial begin clk = 0; forever #10 clk = ~clk; // 周期20ns,即50MHz end // 复位信号 initial begin reset = 1; #100; // 复位100ns reset = 0; #1000000; // 仿真持续1000us(1ms),这样我们可以看到多个周期(100kHz周期为10us,所以1000us有100个周期) $finish; end // 将波形保存到VCD文件,用于在Modelsim中查看 initial begin $dumpfile("dds_tb.vcd"); $dumpvars(0, dds_tb); end endmodule ``` 在Modelsim中仿真步骤: 1. 将上述所有文件(phase_accumulator.v, sine_rom.v, dds_top.v, dds_tb.v)和sine_100khz.mif放在同一个工程目录下。 2. 在Modelsim中新建工程,添加这些文件。 3. 编译所有文件。 4. 启动仿真,选择dds_tb模块。 5. 添加波形(clk, reset, dout等)。 6. 运行仿真(注意仿真时间设置足够长,比如1ms)。 7. 观察dout输出的波形,应该是一个正弦波的离散值(阶梯状),因为每个时钟周期输出一个点。 由于我们的时钟是50MHz(周期20ns),而输出正弦波的周期是10us(100kHz),所以一个正弦波周期内会有500个点(因为10us/20ns=500)。但是,我们ROM中只有256个点,所以每256个点会重复一次,但由于相位累加器的高8位作为地址,所以实际上每256个时钟周期(5.12us)就会重复一次?不对,因为相位累加器每次累加K(8589935),所以地址的增量不是1,而是K的高8位(即8589935>>24)?实际上,我们取的是高8位,所以地址的变化率由K的高8位决定。具体来说,每个时钟周期,相位累加器增加K,那么高8位([31:24])的增加量相当于K[31:24],所以地址不是顺序增加,而是以步进K[31:24]跳跃。因此,输出一个完整的正弦波需要的时间是:当相位累加器增加2^32时,地址循环一次。所以,输出一个完整正弦波的时间为:2^32 / (K * f_clk) 的倒数?不对,根据公式,输出频率f_out = (K * f_clk) / 2^32,所以周期T_out = 1/f_out = 2^32 / (K * f_clk)。而K=8589935,f_clk=50e6,所以T_out = 2^32/(8589935*50e6) = 4294967296/(8589935*50000000) = 4294967296/429496750000000 ≈ 0.00001秒=10us,符合要求。 在仿真波形中,我们会在10us内看到500个点(因为50MHz时钟,20ns一个点,10us有500个点),但ROM只有256个不同的点,所以每个点大约被重复使用2次(500/256≈1.95次),但由于地址跳跃,所以并不是连续重复,而是跳跃地重复。但总体波形应该是正弦波。 我们可以在Modelsim中查看dout的模拟波形(将dout设置为模拟波形显示方式),可以看到正弦波形状。 注意:由于我们使用无符号数(0-255),所以波形在128上下波动。 总结步骤: 1. 计算频率控制字K(8589935)。 2. 生成MIF文件(正弦波256点,数据用无符号数0-255,用Matlab生成)。 3. 编写Verilog代码:相位累加器、ROM、顶层。 4. 编写Testbench。 5. 在Modelsim中仿真,观察波形。 注意:在Quartus中实际下载时,需要将ROM用IP核实现,但在仿真中,我们直接用$readmemh初始化寄存器数组即可。 以上步骤即可实现需求。</think>### 配置DDS信号发生器生成100kHz正弦波(50MHz时钟)及Modelsim仿真 #### 1. **参数计算与DDS原理** DDS输出频率公式为: $$ f_{out} = \frac{f_{clk} \times K}{2^N} $$ 其中: - $f_{clk} = 50\text{MHz}$(板载时钟) - $f_{out} = 100\text{kHz}$(目标频率) - $N = 32$(相位累加器位宽,推荐值) - $K$ = 频率控制字(需计算) 计算$K$值: $$ K = \frac{f_{out} \times 2^N}{f_{clk}} = \frac{100 \times 10^3 \times 2^{32}}{50 \times 10^6} \approx 8,589,935 $$ 取整$K = 8,589,935$[^3][^4] #### 2. **生成MIF文件(256点正弦波)** 使用MATLAB生成正弦波数据并保存为MIF文件: ```matlab % 生成256点正弦波数据 (8位无符号) n = 0:255; amplitude = 127; % 幅值(避免溢出) sine = round(amplitude * sin(2*pi*n/256) + 128); % 偏移到0-255范围 % 写入MIF文件 fid = fopen('sine_100khz.mif', 'w'); fprintf(fid, 'DEPTH = 256;\nWIDTH = 8;\nADDRESS_RADIX = DEC;\nDATA_RADIX = DEC;\nCONTENT\nBEGIN\n'); for i = 1:256 fprintf(fid, '%d : %d;\n', i-1, sine(i)); end fprintf(fid, 'END;\n'); fclose(fid); ``` 生成的文件片段: ``` 0 : 128; 1 : 131; 2 : 134; ... 254 : 122; 255 : 125; // 正弦波数据[^4] ``` #### 3. **Verilog实现DDS模块** ```verilog // 相位累加器模块 (phase_accumulator.v) module phase_accumulator ( input clk, // 50MHz时钟 input reset, // 复位 input [31:0] K, // 频率控制字 output reg [31:0] phase ); always @(posedge clk or posedge reset) begin if (reset) phase <= 0; else phase <= phase + K; // 相位累加 end endmodule // ROM模块 (sine_rom.v) module sine_rom ( input [7:0] addr, // ROM地址 output reg [7:0] data // 正弦波数据 ); reg [7:0] mem [0:255]; initial begin $readmemh("sine_100khz.mif", mem); // 加载MIF文件 end always @(addr) begin data = mem[addr]; end endmodule // DDS顶层模块 (dds_top.v) module dds_top ( input clk, // 50MHz input reset, output [7:0] dout // 正弦波输出 ); wire [31:0] phase; wire [7:0] rom_addr; phase_accumulator pa_inst ( .clk(clk), .reset(reset), .K(32'd8589935), // 计算得到的K值 .phase(phase) ); assign rom_addr = phase[31:24]; // 取高8位作为ROM地址 sine_rom rom_inst ( .addr(rom_addr), .data(dout) ); endmodule ``` #### 4. **Modelsim仿真步骤** **Testbench代码 (`dds_tb.v`):** ```verilog `timescale 1ns/1ns module dds_tb; reg clk; reg reset; wire [7:0] dout; // 实例化DDS dds_top uut ( .clk(clk), .reset(reset), .dout(dout) ); // 生成50MHz时钟 initial begin clk = 0; forever #10 clk = ~clk; // 周期=20ns (50MHz) end // 复位和仿真控制 initial begin reset = 1; #100 reset = 0; // 复位100ns后释放 #1000000; // 仿真1ms (覆盖100个正弦波周期) $stop; end // 波形记录 initial begin $dumpfile("dds_wave.vcd"); $dumpvars(0, dds_tb); end endmodule ``` **仿真操作流程:** 1. 将以下文件放入同一目录: - `phase_accumulator.v` - `sine_rom.v` - `dds_top.v` - `dds_tb.v` - `sine_100khz.mif` 2. 启动Modelsim: ```tcl vlib work vlog *.v vsim dds_tb add wave -position insertpoint sim:/dds_tb/* run -all ``` 3. **波形验证要点**: - 测量`dout`信号周期应为10μs (100kHz) - 检查波形是否为正弦形状 - 确认复位后输出正常启动 - 验证ROM地址变化符合相位累加规律 #### 5. **关键验证结果** - **频率验证**: ![](https://via.placeholder.com/600x200?text=Modelsim+Waveform+Example) 两个波峰间隔应为10μs(对应100kHz)[^1][^3] - **资源占用**(FPGA实现参考): | 模块 | 逻辑单元 | 内存比特 | |----------------|----------|----------| | 相位累加器 | 32 | 0 | | ROM (256x8) | 0 | 2048 | | 总计 | ≈50 | 2048 | #### 总结 通过精确计算频率控制字$K$=8,589,935,使用256点MIF文件初始化ROM,并在50MHz时钟下实现DDS,可稳定生成100kHz正弦波。Modelsim仿真需关注: 1. 输出信号周期是否精确为10μs 2. 波形是否符合正弦特征 3. 相位累加器是否正常进位[^3][^4] 实际FPGA部署时,需注意: - 将ROM替换为FPGA厂商的IP核(如Quartus的ROM) - 添加时钟管理模块 - 考虑DAC接口时序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值