1、word完整版)FPGA查找表法sin函数的实现 实验一 Sin(x)函数的计算 一、实验要求 1、系统可以根据输入的角度(或弧度)x,显示相应的sin(x)数值,保证角度精度≤0。1度。 2、编辑测试激励文件,进行相关测试,注意测试的完备性。 3、根据DE2板资源,设计下载测试方案,并且完成硬件下载测试。 二、实验方案 本实验要求用FPGA实现角度(0度~360度)的Sin函数的计算,角度的分辨率小于等于0.1度。考虑到实现的简便性,本实验采用查表法实现Sin函数的计算。首先我们用Matlab计算出Sin函数值,然后生成.mif文件.用M
2、atlab生成的.mif文件在Quartus中配置FPGA的Rom。跟具输入的角度值得到其Sin函数值存储的Rom地址,然后根据地址取出Rom中存储的Sin函数值,最后显示在数码管上,从而实现Sin函数的计算。 三、实验过程及代码 1. Matlab中.mif文件的生成 由于输入的角度值为0度~360度,所以计算出的Sin函数值至少有3600个,但由于Sin函数值的对称性,所以实际上存储在FPGA的Rom中的值只需要900个。因此在Matlab中我们设置depth=1024,在这里我们对Sin函数值做了扩大10000倍后四舍五入取整的处理,以便于在Rom中存储,所以在这里我们设置widt
3、h=14。Matlab中的程序如下: clear all; close all; clc; t=[0:0。1:90]; %角度 x=pi*t/180; %弧度数 sin_val=sin(x); %sin函数值 fid=fopen(’sine。mif’,'wt'); %以wt格式打开文件sine。mif fprintf(fid,'width=14;\r\n'); %设置width=14 fprintf(fid,'depth=1024;\n'); %设置depth=1024 fprintf(fid,’address_radix=uns;\n'
4、 fprintf(fid,’data_radix=dec;\n’); fprintf(fid,'content begin\n'); for j=1:901 i=j-1; fprintf(fid,’%d:% d;\n’,i,round(sin_val(j)*10000)); end fprintf(fid,'end;\n’); fclose(fid); 然后利用宏功能模块编制LPM_ROM存放上面的数据,取名sin_rom。v,用上面编写的sine。mif初始化这个模块,自动生成的Verilog代码。 2、顶层模块 顶层模块采用Verilog
5、HDL语言编写,保存为sinx.v。输入信号包括一个时钟信号clk,一个复位信号rst_n,一个9位的输入角度的整数部分a,一个4位的输入角度的小数部分b,输出信号包括6个7位的数码管显示信号。由于在Rom中只存储了900个Sin函数值,所以需要对输入的角度进行转换,然后根据转换后的地址对Rom寻址,得在其函数值,在顶层模块中对得到的函数值进行为的的分离,得到函数值的每一位,用于数码管的显示。代码如下: module sinx(clk,rst_n,a,b,hex0,hex1,hex2,hex3,hex4,hex5); input clk,rst_n; input [8:0] a; in
6、put [3:0] b; output [6:0] hex0,hex1,hex2,hex3,hex4,hex5; reg [3:0] data1,data2,data3,data4,data5; wire [3:0] data0; wire [13:0] q; wire [9:0] addr; reg [13:0] qr; jiaodu U( .clk(clk), .a(a), 。b(b), .addr(addr), .fh(data0) ); sin_rom sin_rom_inst ( 。ad
7、dress ( addr ), .clock ( clk ), 。q ( q ) ); reg [2:0] num; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin num <=3’d0; qr <=14'd0; end else begin qr <= q; num 〈= num+1’b1; case(num) 3'd1 : data1 <=qr%4’d10; 3
8、’d2 : data2 <=(qr/4’d10)%4’d10; 3'd3 : data3 <=(qr/8'd100)%4'd10; 3'd4 : data4 〈=(qr/10'd1000)%4'd10; 3'd5 : data5 <=(qr/10’d10000); default : ; endcase if(num ==3'd6) num <=3'd0; end end led led0(rst_n,data0,hex0); led led1(rst_n,data1,hex1); led led2(rst_n,da
9、ta2,hex2); led led3(rst_n,data3,hex3); led led4(rst_n,data4,hex4); led led5(rst_n,data5,hex5); endmodule 3、输入角度的转换 由于在Rom中只存储了900个Sin函数值,所以需要对输入的角度根据其所在的象限得到其Sin函数值的Rom地址,同时给出Sin函数值的符号。在这里输入的角度值分为整数和小数部分,整数部分从0~360共360个值,所以在这里输入的整数部分a定义9位,用9个开关输入。小数部分从0~9共10个值,在这里输入的小数部分b定义4位,用4个开关输入。程序中ad
10、dr是Sin函数值2的储存地址,fh代表的函数值的符号。 module jiaodu(clk,a,b,addr,fh); input clk; input [8:0] a; input [3:0] b; output [9:0] addr; output [3:0] fh; reg [3:0] fh; reg [9:0] addr; reg [12:0] c; always @(posedge clk ) begin c <= a*4'd10+b; if (2700< c 〈=3600) begin add
11、r 〈= 3600-c; fh <=4'ha; end else if(1800< c 〈=2700) begin addr <= c—1800; fh <=4’ha; end else if (900< c 〈=1800) begin addr <=1800-c; fh 〈=4’hb; end else begin addr 〈=c; fh 〈=4’hb;
12、 end end endmodule 4、数码管显示 根据输入的data_in的值别对sm_db赋值用于数码管的显示。 module led( rst_n,data_in,sm_db); input rst_n; input[3:0] data_in; output[6:0] sm_db; reg[6:0] sm_db; always @ (data_in or rst_n) begin if(!rst_n) sm_db <= 7’b1000000; else begin case (data_in)
13、 4’h0: sm_db <= 7’b1000000; 4'h1: sm_db <= 7’b1111001; 4’h2: sm_db <= 7'b0100100; 4’h3: sm_db <= 7’b0110000; 4’h4: sm_db <= 7'b0011001; 4’h5: sm_db 〈= 7’b0010010; 4'h6: sm_db 〈= 7’b0000010; 4'h7: sm_db <= 7'b1111000; 4'h8: sm_db <= 7'b0000000; 4’h9: sm_db 〈= 7’b0011000; 4’ha: sm_db 〈= 7'b0111111; 4'hb: sm_db 〈= 7’b1111111; default: ; endcase end end endmodule 四、实验体会 通过此次实验,我系统的了解了FPGA系统设计的全过程.学会了用verilog语言描述电路,学会了利用宏功能模块编制LPM_ROM存放数据,并用编写的.mif文件初始化这个模块。在这过程中我遇到了一些问题,但通过努力解决了。这让我明白了我们要有随时面对突发问题的心理准备。






