-

参考链接

FPGA实验课8:ROM(IP核)使用实例_fpga的rom的ip如何调用-CSDN博客

Kimi人工智能

1. FPGA中位宽和深度的概念

  1. 位宽(Bit Width)
    • 想象一下,你有一条高速公路,这条高速公路有多个车道。位宽就是指这些车道的数量。比如,一个32位宽的寄存器就像是有32个车道的高速公路,可以同时让32辆车并排行驶。在FPGA中,位宽越大,意味着可以同时处理更多的数据,从而提高计算速度。
  2. 深度(Depth)
    • 现在,想象你有一座多层的停车场。深度就是指这座停车场有多少层。比如,一个深度为1024的存储器就像是有1024层的停车场,每一层都可以停放一辆车。在FPGA中,深度越大,意味着可以存储更多的数据。

总结一下:

  • 位宽:一次操作可以处理的数据量。位宽越大,数据处理能力越强。
  • 深度:可以存储的数据总量。深度越大,存储容量越大。

2. ROM IP核的使用方法

2.1 仿真结果

rom_ip.v
module ROM_IP( input sys_clk, input sys_rst_n, // TLC5620的引脚 output wire da_clk , // 时钟信号 output wire da_data , // 数据信号 output wire da_ldac , // LDAC信号 output wire da_load , // LOAD信号 output wire [7:0] wave ); // rom地址控制模块 reg [12:0] addr; always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) addr <= 13'd0; else if(addr == 13'd4095) addr <= 13'd0; else addr <= addr + 1'd1; end // 实例化ROM IP核 rom rom_inst ( .address ( addr ), .clock ( sys_clk ), .q ( wave ) ); // 实例化tlc5620驱动模块 tlc_5620 tlc_5620_inst ( .CLOCK_50(sys_clk), // 系统时钟 .RST_N(sys_rst_n), // 复位信号 .da_enable(1'b1), // 使能信号,始终使能 .da_range(1'b0), // 输出范围选择,根据需要设置 .da0_data(wave), // 将dac_data连接到DA0通道 .da1_data(8'b0), // 其他通道暂时不使用,置为0 .da2_data(8'b0), // 其他通道暂时不使用,置为0 .da3_data(8'b0), // 其他通道暂时不使用,置为0 .SCK(da_clk), // 连接到外部引脚 .SDI(da_data), // 连接到外部引脚 .LOAD(da_load) // 连接到外部引脚 ); // TLC5620的LDAC信号通常需要保持低电平以更新输出电压 assign da_ldac = 1'b0; endmodule
tlc5620.v
module tlc_5620 ( input CLOCK_50, input RST_N, // input da_enable, input da_range, // 0, 1倍参考电压; 1, 2倍参考电压 input [7:0] da0_data, // 0~255 input [7:0] da1_data, // 0~255 input [7:0] da2_data, // 0~255 input [7:0] da3_data, // 0~255 // output reg SCK, output reg SDI, output reg LOAD ); function integer log2(input integer n); integer i; for(i=0; 2**i <=n; i=i+1) log2=i+1; endfunction /************************************** * 生成140ns的tick时钟 **************************************/ reg [log2(7):1]cnt_140ns; always@(posedge CLOCK_50, negedge RST_N) if(!RST_N) cnt_140ns <= 0; else begin if(cnt_140ns < 6) cnt_140ns <= cnt_140ns + 1'b1; else cnt_140ns <= 0; end wire tick_140ns = (cnt_140ns == 6) ? 1 : 0; /************************************** * 根据tick时钟生成da基准计数器 **************************************/ reg [log2(48):1] da_ref_cnt; // [0,47] always@(posedge CLOCK_50, negedge RST_N) if(!RST_N) da_ref_cnt <= 0; else begin if(!da_enable) da_ref_cnt <= 0; else begin if(tick_140ns) begin if(da_ref_cnt < 47) da_ref_cnt <= da_ref_cnt + 1'b1; else da_ref_cnt <= 0; end end end wire tick_6720ns = (da_ref_cnt == 47) ? 1 : 0; reg [1:0] da_sel_cnt; always@(posedge CLOCK_50, negedge RST_N) if(!RST_N) da_sel_cnt <= 2'b0; else if (tick_6720ns) begin if(da_sel_cnt < 3) da_sel_cnt <= da_sel_cnt + 1'b1; else da_sel_cnt <= 2'b0; end /************************************** * 根据基准计数器生成串行信号 **************************************/ reg [7:0] da_data; always@(posedge CLOCK_50, negedge RST_N) if(!RST_N) da_data <= 8'b0; else begin case(da_sel_cnt) 2'b00: da_data <= da0_data; 2'b01: da_data <= da1_data; 2'b10: da_data <= da2_data; 2'b11: da_data <= da3_data; endcase end always@(posedge CLOCK_50, negedge RST_N) if(!RST_N) begin SCK <= 0; SDI <= 0; LOAD <= 0; end else begin if(tick_140ns) begin // 生成SCK信号 case(da_ref_cnt) 2,6,10,14,18,22,26,30,34,38,42: SCK <= 1; 4,8,12,16,20,24,28,32,36,40,44: SCK <= 0; default : ; // 缺省不操作 endcase // 生成LOAD信号 case(da_ref_cnt) 0: LOAD <= 1; 46: LOAD <= 0; default : ; // 缺省不操作 endcase // 送入串型数据 case(da_ref_cnt) 3,4: SDI <= da_sel_cnt[1]; 7,8: SDI <= da_sel_cnt[0]; 11,12: SDI <= da_range; 15,16: SDI <= da_data[7]; 19,20: SDI <= da_data[6]; 23,24: SDI <= da_data[5]; 27,28: SDI <= da_data[4]; 31,32: SDI <= da_data[3]; 35,36: SDI <= da_data[2]; 39,40: SDI <= da_data[1]; 43,44: SDI <= da_data[0]; default : SDI <= 1'b1; endcase end end endmodule

本站由 John Doe 使用 Stellar 1.28.1 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本"页面"访问 次 | 👀总访问 次 | 🥷总访客