0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

數(shù)字設(shè)計(jì)筆試Verilog手撕代碼—累加器

冬至子 ? 來源:FPGA and ICer ? 作者:Vuko ? 2023-06-02 16:35 ? 次閱讀

已知一個(gè)加法器IP,其功能是計(jì)算兩個(gè)數(shù)的和,但這個(gè)和延遲兩個(gè)周期才會(huì)輸出?,F(xiàn)在有一串連續(xù)的數(shù)據(jù)輸入,每個(gè)周期都不間斷,試問最少需要例化幾個(gè)上述的加法器IP,才可以實(shí)現(xiàn)累加的功能。

設(shè)計(jì)分析

實(shí)現(xiàn)累加器的加法器例化的個(gè)數(shù)。按照原文大佬的設(shè)計(jì)方法,因?yàn)閿?shù)據(jù)連續(xù)且加法器的延遲周期是2,使用使用一個(gè)實(shí)現(xiàn)累加,會(huì)有一半的數(shù)據(jù)丟失。那這樣設(shè)計(jì)他就將奇數(shù)偶數(shù)的數(shù)據(jù)進(jìn)行了分開做一級(jí)累加,然后第二級(jí)將奇數(shù)偶數(shù)的累加結(jié)果再累加。這樣做共需消耗3個(gè)加法器。

這樣設(shè)計(jì)當(dāng)然沒問題,但是這樣設(shè)計(jì)是否是最少呢?我先拋出我的思考,我認(rèn)為在允許少量邏輯設(shè)計(jì)的情況下,最少需要例化兩個(gè)上述的加法器IP可以實(shí)現(xiàn)累加。

如果比較極限的情況下,一個(gè)都可以,先把一串?dāng)?shù)據(jù)使用寄存器緩存,然后一個(gè)一個(gè)取出來慢慢算即可,但這樣是不太可取的,首先,數(shù)據(jù)是連續(xù)的并沒有給出數(shù)據(jù)的極限長度,也就是說不論用任何涉及存儲(chǔ)結(jié)構(gòu)進(jìn)行緩存,都沒法確保該次數(shù)據(jù)能完全被存儲(chǔ)。如果題目改成一串連續(xù)數(shù)據(jù)輸入,長度最大為10,那我認(rèn)為用寄存器緩存這樣的設(shè)計(jì)是合理的。

設(shè)計(jì)架構(gòu)

回到設(shè)計(jì)思路:用兩個(gè)加法器的結(jié)構(gòu)如圖示。

圖片

設(shè)計(jì)實(shí)現(xiàn)

加法器設(shè)計(jì)

假設(shè)兩個(gè)時(shí)鐘周期延時(shí)加法器代碼如下,通過例化加法器進(jìn)行構(gòu)建累加器。

//加法器IP
module adder
#(parameter DATA_WIDTH = 8)(
    input clk,
    input rst_n,
    input [DATA_WIDTH-1:0] a_in,
    input [DATA_WIDTH-1:0] b_in,
    output reg [DATA_WIDTH-1:0] out
  );
  reg [DATA_WIDTH-1:0] sum;
  always @(posedge clk or negedge rst_n)begin
    if(rst_n == 'd0)begin
      sum <= 'd0;
      out <= 'd0;
    end
    else begin
      sum <= a_in + b_in;
      out <= sum;
    end
  end
endmodule

累加器設(shè)計(jì)

//累加器實(shí)現(xiàn)
module adder_for_acc
  #(parameter DATA_WIDTH = 8)
   (
     input                        clk,
     input                      rst_n,
     input       [DATA_WIDTH-1:0] din,
     input                  din_valid,
     output reg            dout_valid,
     output reg [DATA_WIDTH-1:0] dout
   );

  reg [DATA_WIDTH-1:0]din_r0;

  //打一拍
  always @(posedge clk or negedge rst_n)begin
    if(rst_n == 'd0)begin
      din_r0 <= 'd0;
    end
    else if(din_valid==1'B1)begin
      din_r0<= din;
    end
    else begin
      din_r0<='d0;
    end
  end

  //adder0_valid信號(hào)
  reg adder0_valid;
  always @(posedge clk or negedge rst_n)begin
    if(rst_n == 'd0)begin
      adder0_valid <= 'd0;
    end
    else if(din_valid==1'B1)begin
      adder0_valid<=!adder0_valid;
    end
    else begin
      adder0_valid<='d0;
    end
  end

  wire[DATA_WIDTH-1:0] a_in = (adder0_valid && din_valid)?din:0;
  wire[DATA_WIDTH-1:0] b_in = (adder0_valid)?din_r0:0;
  wire[DATA_WIDTH-1:0] ab_sum;

  adder adder0_dut (
    .clk  (clk   ),
    .rst_n(rst_n ),
    .a_in (a_in  ),
    .b_in (b_in  ),
    .out  (ab_sum)
  );
  //第一級(jí)加法器輸出有效信號(hào)
  reg [1:0]adder0_valid_dly;
  wire ab_sum_valid = adder0_valid_dly[1];
  always @(posedge clk ) begin
      adder0_valid_dly<={adder0_valid_dly[0],adder0_valid};
  end

  wire [DATA_WIDTH-1:0] sum_in;
  wire [DATA_WIDTH-1:0] ab_sum_in = (ab_sum_valid)?ab_sum:0;
  wire [DATA_WIDTH-1:0] accsum_in = (ab_sum_valid)?sum_in:dout;

  adder adder1_dut (
    .clk  (clk      ),
    .rst_n(rst_n    ),
    .a_in (ab_sum_in),
    .b_in (accsum_in),
    .out  (sum_in   )
  );
  
  //第二級(jí)加法器輸出有效信號(hào)
  reg [3:0]din_valid_r0;
  reg [1:0]adder1_valid_dly;
  wire adder1_outvld = adder1_valid_dly[1];
  always @(posedge clk ) begin
    adder1_valid_dly<={adder1_valid_dly[0],ab_sum_valid};
  end
  //輸出
  always @(posedge clk ) begin
    din_valid_r0<={din_valid_r0[2:0],(din_valid || adder0_valid)};
  end
  always @(posedge clk or negedge rst_n) begin
    if(rst_n == 'd0)begin
      dout <= 'd0;
      dout_valid <= 'd0;
    end
    else if(adder1_outvld == 1 && (din_valid_r0[3]==1 && din_valid_r0[2]==0))begin
      dout <= sum_in ;
      dout_valid <= 'd1;
    end
    else begin
      dout <= dout ;
      dout_valid <= 'd0;
    end
  end

endmodule

代碼架構(gòu)設(shè)計(jì)

  1. 打拍:先對(duì)數(shù)據(jù)用寄存器緩存一拍,輸入數(shù)據(jù)暫時(shí)用in[i]表示,緩存。
  2. 第一級(jí)加法器輸入選擇valid:因?yàn)榍凹?jí)積累一拍的數(shù)據(jù),設(shè)計(jì)valid用于指示加法器的輸入數(shù)據(jù)。
  3. 第一級(jí)加法器信號(hào)輸入:根據(jù)valid信號(hào)進(jìn)行選擇數(shù)據(jù)輸入。
  4. 調(diào)用第一級(jí)加法器,同時(shí)對(duì)輸入valid信號(hào)進(jìn)行打兩拍處理,指示有效的輸出數(shù)據(jù)。
  5. 第二級(jí)加法器信號(hào)輸入:根據(jù)valid信號(hào)進(jìn)行選擇數(shù)據(jù)輸入。
  6. 調(diào)用第二級(jí)加法器,同時(shí)對(duì)輸入valid信號(hào)進(jìn)行打兩拍處理,指示有效的輸出數(shù)據(jù)。
  7. 輸出結(jié)果和valid信號(hào)。

經(jīng)過分析,目前設(shè)計(jì)延時(shí)是4拍,也即兩級(jí),這里dout和valid使用的是時(shí)序邏輯輸出,所以在輸入valid拉低后的第五個(gè)時(shí)鐘周期輸出正確的結(jié)果。

仿真測試

設(shè)計(jì)仿真測試代碼對(duì)代碼進(jìn)行測試,這里使用了遞增數(shù)測試代碼可用性,在實(shí)際測試時(shí),可通過改變DATA_LEN的大小測試單次遞增累加后的結(jié)果,后續(xù)結(jié)果依次遞增為第一次的N倍。

`timescale 1ns/1ps
module adder_for_acc_tb;

  // Parameters
  localparam  DATA_WIDTH = 8;
  localparam  DATA_LEN = 5;
  // Ports
  reg clk = 1;
  reg rst_n = 0;
  reg [DATA_WIDTH-1:0] din;
  reg din_valid = 0;
  wire  dout_valid;
  wire [DATA_WIDTH-1:0] dout;

  adder_for_acc 
  #(
    .DATA_WIDTH (
        DATA_WIDTH )
  )
  adder_for_acc_dut (
    .clk (clk ),
    .rst_n (rst_n ),
    .din (din ),
    .din_valid (din_valid ),
    .dout_valid (dout_valid ),
    .dout  ( dout)
  );
  always @(posedge clk or negedge rst_n)begin
    if(rst_n == 'd0)begin
            din <= 'd0;
      din_valid <= 'd0;
    end
    else if(dout_valid == 1)begin
      din <= 'd0;
      din_valid <= 'd1;
    end
    else if(din == DATA_LEN)begin
      din <= din;
      din_valid <= 'd0;
    end
    else if(din != DATA_LEN)begin
      din <= din + 1;
      din_valid <= 'd1;
    end
    else begin
      din <= din;
      din_valid <= 'd0;
    end
  end

  always #5  clk = ! clk ;
  initial begin
    begin
      #100;
      rst_n = 1;
      #1000;
      $finish;
    end
  end

 
endmodule

仿真截圖

圖片

仿真分析

在圖示仿真可知,累加器功能正常,在din_valid信號(hào)拉低后第五拍可得到輸出結(jié)果,功能正常。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5275

    瀏覽量

    119693
  • Verilog
    +關(guān)注

    關(guān)注

    28

    文章

    1339

    瀏覽量

    109889
  • 加法器
    +關(guān)注

    關(guān)注

    6

    文章

    183

    瀏覽量

    30046
  • 累加器
    +關(guān)注

    關(guān)注

    0

    文章

    50

    瀏覽量

    9434
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    基于相位累加器的任意分頻原理解析

    在大部分的教科書中,都會(huì)提到如何分頻,包括奇數(shù)分頻,偶數(shù)分頻,小數(shù)分頻等。 1、DDS相位累加器 (1)DDS合成流程 首先講述DSS(直接頻率合成法)的原理。 DDS是重要的頻率合成方法,在波形
    的頭像 發(fā)表于 11-29 10:19 ?4844次閱讀

    累加器verilog語言編程問題

    剛剛接觸FPGA,編程方面也不是很擅長。今天做了一個(gè)累加器verilog編程,仿真波形圖一直出錯(cuò),想請(qǐng)大神指教一下錯(cuò)誤的原因,十分感謝!我要實(shí)現(xiàn)的累加器功能是:連續(xù)輸入幾百個(gè)gary_value
    發(fā)表于 05-23 20:09

    FPGA實(shí)現(xiàn)NCO中相位累加器的輸出和查找表地址什么關(guān)系?

    ,這么理解是否正確,怎樣實(shí)現(xiàn)?Q3: NCO的性能與相位累加器的位數(shù)有關(guān),但與正弦表的精確程度有什么關(guān)系,能否采用更小的正弦表。相位累加器和查找表的地址的關(guān)系希望有人寫出來,或者寫成偽代碼更好,最好能按上面這個(gè)例子來解釋。本人新
    發(fā)表于 03-10 20:10

    控制累加器

    怎么由布爾控件控制開始和停止累加器的運(yùn)行
    發(fā)表于 06-04 22:09

    累加器的簡單使用和自定義累加器

    累加器使用的注意點(diǎn)及自定義累加器
    發(fā)表于 04-02 09:31

    計(jì)算機(jī)累加器有加法器功能嗎,累加器是什么_累加器的作用及原理介紹 精選資料推薦

    累加器的概念在中央處理中,累加器(accumulator)是一種寄存,用來儲(chǔ)存計(jì)算產(chǎn)生的中間結(jié)果。如果沒有像累加器這樣的寄存
    發(fā)表于 08-30 08:57

    TMS320F24X 指令集累加器、算術(shù)與邏輯指令附件

    TMS320F24X 指令集累加器、算術(shù)與邏輯指令附件 TMS320F24X 指令集累加器、算術(shù)與邏輯指令 助記
    發(fā)表于 10-17 22:41 ?1156次閱讀

    相位累加器原理

    相位累加器一個(gè)正弦波,雖然它的幅度不是線性的,但是它的相位卻是線性增加的。DDS 正是利用了這一特點(diǎn)來產(chǎn)生正弦信號(hào)。如圖 2,根據(jù)
    發(fā)表于 09-03 08:43 ?8030次閱讀
    相位<b class='flag-5'>累加器</b>原理

    累加器是什么_累加器的作用及原理介紹

    本文開始介紹了累加器的概念和相位累加器原理,其次介紹了累加器的作用,最后介紹了流水線相位累加器的設(shè)計(jì)與累加定時(shí)器在PLC控制程序中的應(yīng)用。
    發(fā)表于 04-11 11:40 ?7.3w次閱讀
    <b class='flag-5'>累加器</b>是什么_<b class='flag-5'>累加器</b>的作用及原理介紹

    單片機(jī)累加器作用_單片機(jī)復(fù)位電路的作用

    本文開始介紹了單片機(jī)的概念和工作原理,其次介紹了單片機(jī)累加器作用和單片機(jī)累加器A與ACC區(qū)別,最后闡述了單片機(jī)復(fù)位電路原理及單片機(jī)復(fù)位電路的作用。
    發(fā)表于 04-11 12:40 ?1.2w次閱讀
    單片機(jī)<b class='flag-5'>累加器</b>作用_單片機(jī)復(fù)位電路的作用

    累加器是寄存嗎_寄存累加器、暫存有什么區(qū)別

    本文首先對(duì)寄存、累加器、暫存做個(gè)哥介紹,其次解答了累加器是不是寄存,最后闡述了寄存、
    發(fā)表于 04-11 16:31 ?9439次閱讀

    累加器A的主要作用是什么_一文解析累加器a和acc的區(qū)別

    在中央處理中,累加器(accumulator) 是一種寄存,用來儲(chǔ)存計(jì)算產(chǎn)生的中間結(jié)果。如果沒有像累加器這樣的寄存,那么在每次計(jì)算 (
    發(fā)表于 04-11 16:46 ?2.3w次閱讀

    32位數(shù)字相位累加器的程序和工程文件免費(fèi)下載

    累加器 (accumulator) 是一種寄存,用來儲(chǔ)存計(jì)算產(chǎn)生的中間結(jié)果。如果沒有像累加器這樣的寄存,那么在每次計(jì)算 (加法,乘法,移位等等) 后就必須要把結(jié)果寫回到 內(nèi)存,也許
    發(fā)表于 10-14 16:00 ?8次下載
    32位<b class='flag-5'>數(shù)字</b>相位<b class='flag-5'>累加器</b>的程序和工程文件免費(fèi)下載

    Arduino的累加器實(shí)驗(yàn)程序和工程文件免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是Arduino的累加器實(shí)驗(yàn)程序和工程文件免費(fèi)下載。
    發(fā)表于 01-13 17:24 ?5次下載

    51單片機(jī)中累加器A與ACC的區(qū)別

    累加器A與ACC區(qū)別累加器寫成A或ACC在51匯編語言指令中是有區(qū)別的。ACC在匯編后的機(jī)器碼必有一個(gè)字節(jié)的操作數(shù),即累加器的字節(jié)地址E0H,A在匯編后則隱含在指令操作碼中。所以在指令中A不能
    發(fā)表于 11-23 09:06 ?105次下載
    51單片機(jī)中<b class='flag-5'>累加器</b>A與ACC的區(qū)別