110,Verilog-2005标准篇:转换函数(Conversion functions)

注意!转换系统函数可用于常量表达式,因此其不仅可用在仿真中,实际板级verilog代码也能使用,但其函数输入只能是常量。

以下函数能处理实数值:

-$rtoi:通过截断实数值,将实数值转换为整数

-$itor:将整数转换为实数

-$realtobits:将实数转换为实数的 64 位表示(向量)。

-$bitstoreal:与$realtobits相反,将位模式转换为实数。

这些函数接受或生成的实数应符合IEEE 754实数表示法,转换结果应四舍五入到最接近的有效表示形式。下面的示例展示了$realtobits$bitstoreal函数在端口连接中的使用方法:

点赞加关注博主(ID:FPGA小飞)的博文,咱们一起系统学习verilog最终标准IEEE Std 1364-2005吧!

module TOP( input wire clk_50M , input wire rst_n , output wire ad_clk , input wire [7:0]ad_data , output wire [7:0]da_data , output wire da_clk ); wire lock ; wire clk_125M ; wire clk_35M ; wire clk_10M ; assign da_clk = clk_50M ; assign ad_clk = clk_50M ; ad_clock_125m u_pll ( .clkin1(clk_50M), // input .lock(lock), // output .clkout0(clk_125M) , // output .clkout1(clk_35M), // output .clkout2(clk_10M) // output // output ); wire wr_en_from_ad; wire [7:0] wr_data; ad_in u_ad( .ad_clk(ad_clk), .rst_n(rst_n), .ad_data(ad_data), .wr_en(wr_en_from_ad), .wr_data(wr_data) ); // // ---------- Parameters for address width ---------- // localparam ADDR_W = 10; // localparam PTR_W = ADDR_W + 1; // extra MSB for full/empty detection // localparam DEPTH = (1 << ADDR_W); // // ---------- write-side pointers (in ad_clk domain) ---------- // reg [PTR_W-1:0] wr_ptr_bin; // reg [PTR_W-1:0] wr_ptr_gray; // // synced read pointer sampled into write domain // reg [PTR_W-1:0] rd_ptr_gray_sync1_wr, rd_ptr_gray_sync2_wr; // // ---------- read-side pointers (in da_clk domain) ---------- // reg [PTR_W-1:0] rd_ptr_bin; // reg [PTR_W-1:0] rd_ptr_gray; // // synced write pointer sampled into read domain // reg [PTR_W-1:0] wr_ptr_gray_sync1_rd, wr_ptr_gray_sync2_rd; // // outputs from sync // wire full; // wire empty; // // ---------- utility functions ---------- // function [PTR_W-1:0] bin2gray; // input [PTR_W-1:0] b; // begin // bin2gray = (b >> 1) ^ b; // end // endfunction // // (optional) gray2bin for debug - not used in synthesizable empty/full logic // function [PTR_W-1:0] gray2bin; // input [PTR_W-1:0] g; // integer i; // reg [PTR_W-1:0] b; // begin // b = g; // for (i = PTR_W-2; i >= 0; i = i - 1) // b[i] = b[i] ^ b[i+1]; // gray2bin = b; // end // endfunction // // ---------- write-side logic (ad_clk domain) ---------- // wire wr_en_gated; // assign wr_en_gated = wr_en_from_ad & ~full; // // increment write pointer when write happens // always @(posedge ad_clk or negedge rst_n) begin // if (!rst_n) begin // wr_ptr_bin <= {PTR_W{1'b0}}; // wr_ptr_gray <= {PTR_W{1'b0}}; // rd_ptr_gray_sync1_wr <= {PTR_W{1'b0}}; // rd_ptr_gray_sync2_wr <= {PTR_W{1'b0}}; // end else begin // // sync read pointer into write domain (two-stage) // rd_ptr_gray_sync1_wr <= rd_ptr_gray; // rd_ptr_gray_sync2_wr <= rd_ptr_gray_sync1_wr; // if (wr_en_gated) begin // wr_ptr_bin <= wr_ptr_bin + 1'b1; // wr_ptr_gray <= bin2gray(wr_ptr_bin + 1'b1); // end // end // end // // ---------- read-side logic (da_clk domain) ---------- // wire rd_en_gated; // used to read from RAM and feed DAC // assign rd_en_gated = (~empty); // continuous read when data available (you can gate by DAC ready) // always @(posedge da_clk or negedge rst_n) begin // if (!rst_n) begin // rd_ptr_bin <= {PTR_W{1'b0}}; // rd_ptr_gray <= {PTR_W{1'b0}}; // wr_ptr_gray_sync1_rd <= {PTR_W{1'b0}}; // wr_ptr_gray_sync2_rd <= {PTR_W{1'b0}}; // end else begin // // sync write pointer into read domain (two-stage) // wr_ptr_gray_sync1_rd <= wr_ptr_gray; // wr_ptr_gray_sync2_rd <= wr_ptr_gray_sync1_rd; // if (rd_en_gated) begin // rd_ptr_bin <= rd_ptr_bin + 1'b1; // rd_ptr_gray <= bin2gray(rd_ptr_bin + 1'b1); // end // end // end // // ---------- full / empty detection ---------- // // full: when next write pointer equals read pointer with MSBs inverted (classic) // wire [PTR_W-1:0] wr_ptr_gray_next; // assign wr_ptr_gray_next = bin2gray(wr_ptr_bin + 1'b1); // // full compare uses synchronized read pointer inside write domain // assign full = (wr_ptr_gray_next == {~rd_ptr_gray_sync2_wr[PTR_W-1:PTR_W-2], rd_ptr_gray_sync2_wr[PTR_W-3:0]}); // // empty: read pointer equals synchronized write pointer inside read domain // assign empty = (rd_ptr_gray == wr_ptr_gray_sync2_rd); // // ---------- connect addresses to ram (lower ADDR_W bits) ---------- // wire [ADDR_W-1:0] wr_addr; // wire [ADDR_W-1:0] rd_addr; // assign wr_addr = wr_ptr_bin[ADDR_W-1:0]; // assign rd_addr = rd_ptr_bin[ADDR_W-1:0]; // // ---------- ram instance (your existing IP) ---------- // wire [7:0] rd_data; // wire wr_clk = ad_clk; // wire rd_clk = da_clk; // ---------------- parameters ---------------- localparam ADDR_W = 10; localparam PTR_W = ADDR_W + 1; // one extra MSB localparam DEPTH = (1 << ADDR_W); localparam integer SAFE_GUARD = 4; // read must be at least SAFE_GUARD behind write // ---------------- write-side pointers (ad_clk domain) ---------------- reg [PTR_W-1:0] wr_ptr_bin; reg [PTR_W-1:0] wr_ptr_gray; // synchronized read pointer sampled into write domain (two-stage) reg [PTR_W-1:0] rd_ptr_gray_sync1_wr, rd_ptr_gray_sync2_wr; // ---------------- read-side pointers (da_clk domain) ---------------- reg [PTR_W-1:0] rd_ptr_bin; reg [PTR_W-1:0] rd_ptr_gray; // synchronized write pointer sampled into read domain (two-stage) reg [PTR_W-1:0] wr_ptr_gray_sync1_rd, wr_ptr_gray_sync2_rd; // after sync, convert gray->bin in read domain reg [PTR_W-1:0] wr_ptr_bin_sync_rd; // full / empty signals (derived) wire full; wire empty; // ---------------- functions ---------------- function [PTR_W-1:0] bin2gray; input [PTR_W-1:0] b; begin bin2gray = (b >> 1) ^ b; end endfunction function [PTR_W-1:0] gray2bin_f; input [PTR_W-1:0] g; integer i; reg [PTR_W-1:0] b; begin // MSB passes through b[PTR_W-1] = g[PTR_W-1]; for (i = PTR_W-2; i >= 0; i = i - 1) b[i] = b[i+1] ^ g[i]; gray2bin_f = b; end endfunction // ---------------- write-side logic (ad_clk domain) ---------------- wire wr_en_gated; assign wr_en_gated = wr_en_from_ad & ~full; always @(posedge ad_clk or negedge rst_n) begin if (!rst_n) begin wr_ptr_bin <= {PTR_W{1'b0}}; wr_ptr_gray <= {PTR_W{1'b0}}; rd_ptr_gray_sync1_wr <= {PTR_W{1'b0}}; rd_ptr_gray_sync2_wr <= {PTR_W{1'b0}}; end else begin // sync read pointer into write domain rd_ptr_gray_sync1_wr <= rd_ptr_gray; rd_ptr_gray_sync2_wr <= rd_ptr_gray_sync1_wr; if (wr_en_gated) begin wr_ptr_bin <= wr_ptr_bin + 1'b1; wr_ptr_gray <= bin2gray(wr_ptr_bin + 1'b1); end end end // ---------------- read-side logic (da_clk domain) ---------------- // rd_en gating will use occupancy calculation reg rd_en_gated; wire [PTR_W-1:0] occupancy; // unsigned diff always @(posedge da_clk or negedge rst_n) begin if (!rst_n) begin rd_ptr_bin <= {PTR_W{1'b0}}; rd_ptr_gray <= {PTR_W{1'b0}}; wr_ptr_gray_sync1_rd <= {PTR_W{1'b0}}; wr_ptr_gray_sync2_rd <= {PTR_W{1'b0}}; wr_ptr_bin_sync_rd <= {PTR_W{1'b0}}; rd_en_gated <= 1'b0; end else begin // sync write pointer into read domain (two-stage) wr_ptr_gray_sync1_rd <= wr_ptr_gray; wr_ptr_gray_sync2_rd <= wr_ptr_gray_sync1_rd; // convert synchronized gray pointer to binary (registered conversion) wr_ptr_bin_sync_rd <= gray2bin_f(wr_ptr_gray_sync2_rd); // compute occupancy (unsigned arithmetic) // since both are PTR_W width, subtraction yields modulo behavior // occupancy = wr_ptr_bin_sync_rd - rd_ptr_bin // we compute occupancy combinationally in next always (but hold in reg here) // gating read: only when occupancy > SAFE_GUARD and not empty if ( ((wr_ptr_bin_sync_rd - rd_ptr_bin) > SAFE_GUARD) && (rd_ptr_gray != wr_ptr_gray_sync2_rd) ) begin // safe to read and not empty rd_en_gated <= 1'b1; rd_ptr_bin <= rd_ptr_bin + 1'b1; rd_ptr_gray <= bin2gray(rd_ptr_bin + 1'b1); end else begin rd_en_gated <= 1'b0; end end end // occupancy wire for observation/debug (optional) assign occupancy = (wr_ptr_bin_sync_rd - rd_ptr_bin); // ---------------- full / empty detection ---------------- // compute next write gray (for full detection) wire [PTR_W-1:0] wr_ptr_gray_next; assign wr_ptr_gray_next = bin2gray(wr_ptr_bin + 1'b1); // full: compare next write gray with read gray (synchronized into write domain) // MSB inversion trick for full detection assign full = (wr_ptr_gray_next == {~rd_ptr_gray_sync2_wr[PTR_W-1:PTR_W-2], rd_ptr_gray_sync2_wr[PTR_W-3:0]}); // empty: when read gray equals synchronized write gray in read domain assign empty = (rd_ptr_gray == wr_ptr_gray_sync2_rd); // ---------------- connect addresses to ram (lower ADDR_W bits) ---------------- wire [ADDR_W-1:0] wr_addr = wr_ptr_bin[ADDR_W-1:0]; wire [ADDR_W-1:0] rd_addr = rd_ptr_bin[ADDR_W-1:0]; // ---------------- ram instance (your existing IP) ---------------- wire [7:0] rd_data; ram_8_10 u_ram( .wr_data(wr_data), .wr_addr(wr_addr), .wr_en(wr_en_gated), .wr_clk(ad_clk), .wr_rst(!rst_n), .rd_data(rd_data), .rd_addr(rd_addr), .rd_clk(da_clk), .rd_rst(!rst_n) ); //ad out da_out u_da( .da_clk(da_clk), //i .rst_n(rst_n), //i .re_in(rd_data), //i .din_valid(rd_en_gated), //i .da_data(da_data) //o ); endmodule
最新发布
10-28
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值