verilog基本功能性电路设计

一、除法器

基于减法和移位的除法器的算法:
        对于32的无符号除法,被除数a除以除数b,他们的商和余数一定不会超过32位。首先将a转换成高32位为0,低32位为a的temp_a。把b转换成高32位为b,低32位为0的temp_b。在每个周期开始时,先将temp_a左移一位,末尾补0,然后与b比较,是否大于b,是则temp_a减去temp_b将且加上1,否则继续往下执行。上面的移位、比较和减法(视具体情况而定)要执行32次,执行结束后temp_a的高32位即为余数,低32位即为商。

verilog代码:
module divide(
input [31:0] a,
input [31:0] b,

output [31:0] quotient ,
output [31:0] remainder, )

reg [31:0] tempa;
reg [31:0] tempb;
reg [63:0] temp_a;
reg [63:0] temp_b;

integer i;

always@(a or b) begin
    tmepa <= a;
    tempb <= b;
end
always@(tempa or tempb) begin
    temp_a <= {32'h00000000,tempa};
    temp_b <= {tempb,32'h00000000};
    for (i=0;i<32;i=i+1) begin
        temp_a <= {temp_a[62:0],1'b0};
        if(temp_a[63:32]>=tempb)
            temp_a <= temp_a - temp_b + 1'b1;
        else
            temp_a <= temp_a;
    end

    quotient <= temp_a[31:0];
    remainder<= temp_b[63:0];
end



改进:1.将组合逻辑改为时序逻辑

           2.计算数据改为动态位宽,加入使能,异步复位等控制逻辑 

parameter state_init = 4'b0000;
parameter state_idle = 4'b0001;
parameter state_cal1 = 4'b0010;
parameter state_cal2 = 4'b0011;
parameter state_done = 4'b0100;

module divider(clk, rst_n, A,B,C,D,ov);
input clk;
input rst_n;
input [15:0]A;
input [15:0]B;
output [15:0]C;
output [15:0]D;
output ov;
/*寄存器需要初始化*/
reg output_valid = 0;

    reg [31:0] temp_a = 32'b0 ,temp_b = 32'b0;
reg [15:0] bufa = 16'b0,bufb = 16'b0;
reg [15:0] TMPA = 16'b0,TMPB = 16'b0;
reg [4:0]  state = state_idle;
reg [3:0]  cnt = 4'b0000;

assign ov = output_valid;
assign C = temp_a[15:0]  & {16{output_valid}};
assign D = temp_a[31:16] & {16{output_valid}};
    
always@(A or B)
begin
    bufa <= A;
    bufb <= B;
end

always@(posedge clk)
begin
if(rst_n)
begin
    case(state)
    state_idle:
    begin
      if(bufa===TMPA&&bufb===TMPB)
      begin
        state <= state_idle;
      end
      else
      begin
        TMPA <= bufa;
        TMPB <= bufb;
        state <= state_init;
        output_valid <= 0;
      end
    end
    state_init:
    begin
       temp_a[15:0] <= bufa;
       temp_b[31:16] <= bufb;
       state <= state_cal1;
       cnt <= 4'b0;
    end
    state_cal1:
    begin
        temp_a <= temp_a<<1;
        state <= state_cal2;
    end
    
    state_cal2:
    begin
        if(temp_a[31:16]>=temp_b[31:16])
        begin
            temp_a <= temp_a - temp_b + 1;
        end
        if(cnt === 4'b1111)
        begin
            state <= state_done;
        end
        else
        begin
            cnt <= cnt + 1;
            state <= state_cal1;
        end
    end
    state_done:
    begin
        output_valid <= 1;
    end
    default: state <= state_idle;
    endcase
end
else
    output_valid <= 0;
end
endmodule

2.乘法器

首先来回顾一下乘法是如何在计算机中实现的。
假设现在有两个32位带符号定点整数x和y,我们现在要让x和y相乘,然后把乘积存放在z中,大家知道,两个32位数相乘,结果不会超过64位,因此z的长度应该为64位。
z = x * y中,x是被乘数,在Verilog代码中 multiplicand表示,y是乘数,在代码中用multiplier表示。因为x和y都是带符号数,所以应该是用补码乘法,但是如果对x和y求绝对值,让两个绝对值相乘,然后再判断正负,效果和补码乘法是相同。后面给出的Verilog代码就是基于这种思路编写的。两个32位整数相乘,实际上是进行了32次加法操作。下面以两个4位二进制数相乘来说明乘法实现的过程。

从上图中可以看到,被乘数x为1000,乘数y为1001,上面的乘法过程是手工运算的一个步骤,而计算机在做乘法时就是模拟上述手工运算的执行过程。因为是两个4位数相乘,所以结果应该是四个数加和得到的。先判断y的最低位是0还是1,如果是1,则需要把x加到部分积上,若为0,则需要把0加到部分积上(实际上加0的这个过程计算机并不执行,因为加0对部分积没有任何影响),x左移一位,之后再让y右移一位,若y为0,则循环结束,否则继续此循环过程。流程图如下。

流程图中,x因为需要左移,所以32位长度的x应该用一个64位寄存器来存储,这样才能保证x左移后不会发生高位丧失。

代码实现与分析

multiply.v文件如下:

`timescale 1ns / 1ps
//*************************************************************************
//   > 文件名: multiply.v
//   > 描述  :乘法器模块,低效率的迭代乘法算法,使用两个乘数绝对值参与运算
//   > 作者  : LOONGSON
//   > 日期  : 2016-04-14
//*************************************************************************
module multiply(              // 乘法器
    input         clk,        // 时钟
    input         mult_begin, // 乘法开始信号
    input  [31:0] mult_op1,   // 乘法源操作数1
    input  [31:0] mult_op2,   // 乘法源操作数2
    output [63:0] product,    // 乘积
    output        mult_end   // 乘法结束信号
);
    //乘法正在运算信号和结束信号
    reg mult_valid;
    assign mult_end = mult_valid & ~(|multiplier); //乘法结束信号:乘数全0
    always @(posedge clk)   //①
    begin
        if (!mult_begin || mult_end)    //如果没有开始或者已经结束了
        begin
            mult_valid <= 1'b0;     //mult_valid 赋值成0,说明现在没有进行有效的乘法运算
        end
        else
        begin
            mult_valid <= 1'b1;
       //     test <= 1'b1;
        end
    end

    //两个源操作取绝对值,正数的绝对值为其本身,负数的绝对值为取反加1
    wire        op1_sign;      //操作数1的符号位
    wire        op2_sign;      //操作数2的符号位
    wire [31:0] op1_absolute;  //操作数1的绝对值
    wire [31:0] op2_absolute;  //操作数2的绝对值
    assign op1_sign = mult_op1[31];
    assign op2_sign = mult_op2[31];
    assign op1_absolute = op1_sign ? (~mult_op1+1) : mult_op1;
    assign op2_absolute = op2_sign ? (~mult_op2+1) : mult_op2;
    //加载被乘数,运算时每次左移一位
    reg  [63:0] multiplicand;
    always @ (posedge clk)  //②
    begin
        if (mult_valid)
        begin    // 如果正在进行乘法,则被乘数每时钟左移一位
            multiplicand <= {multiplicand[62:0],1'b0};  //被乘数x每次左移一位。
        end
        else if (mult_begin) 
        begin   // 乘法开始,加载被乘数,为乘数1的绝对值
            multiplicand <= {32'd0,op1_absolute};
        end
    end

    //加载乘数,运算时每次右移一位,相当于y
    reg  [31:0] multiplier;
    
    always @ (posedge clk)  //③
    begin
    if(mult_valid)
    begin       //如果正在进行乘法,则乘数每时钟右移一位
         multiplier <= {1'b0,multiplier[31:1]}; //相当于乘数y右移一位
    end
    else if(mult_begin)
    begin   //乘法开始,加载乘数,为乘数2的绝对值
        multiplier <= op2_absolute;
        end
    end
    // 部分积:乘数末位为1,由被乘数左移得到;乘数末位为0,部分积为0
    wire [63:0] partial_product;
    assign partial_product = multiplier[0] ? multiplicand:64'd0;        //若此时y的最低位为1,则把x赋值给部分积partial_product,否则把0赋值给partial_product
    
    //累加器
    reg [63:0] product_temp;		//临时结果
    always @ (posedge clk)  //④//clk信号从0变为1时,激发此段语句的执行,但语句的执行需要时间
    begin
        if (mult_valid)
        begin
            product_temp <= product_temp + partial_product;
        end      
        else if (mult_begin)
        begin
        product_temp <= 64'd0;
        end
     end
     
    //乘法结果的符号位和乘法结果
    reg product_sign;	//乘积结果的符号
    always @ (posedge clk)  // 乘积⑤
    begin
        if (mult_valid)
        begin
              product_sign <= op1_sign ^ op2_sign;
        end
    end 
    //若乘法结果为负数,则需要对结果取反+1
    
    assign product = product_sign ? (~product_temp+1) : product_temp;
endmodule

负整数,32位,全部按位取反,末尾加一,不需要将符号位单独提取出来 

3.状态机

 “硬件设计很讲究并行设计思想,虽然用Verilog描述的电路大都是并行实现的,但是对于实际的工程应用,往往需要让硬件来实现一些具有一定顺序的工作,这就要用到状态机思想。什么是状态机呢?简单的说,就是通过不同的状态迁移来完成一些特定的顺序逻辑。硬件的并行性决定了用Verilog描述的硬件实现(臂如不同的always语句)都是并行执行的,那么如果希望分多个时间完成一个任务,怎么办?也许可以用多个使能信号来衔接多个不同的模块,但是这样做多少显得繁琐。状态机的提出会大大简化这一工作。”

——特权同学《深入浅出玩转FPGA》

  一、状态机分类:

  1.Moore型:状态机的状态变化仅和当前状态有关(特权同学《深入浅出玩转FPGA》);时序逻辑电路的输出只取决于当前状态(夏宇闻《Verilog数字系统设计》)。设计高速电路时常用此类状态机,把状态变化直接用作输出。

  2.Mealy型:状态机的状态变化不仅与当前的状态有关,还取决于当前的输入条件(特权同学《深入浅出玩转FPGA》);时序逻辑的输出不但取决于状态还取决于输入(夏宇闻《Verilog数字系统设计》)。平常使用较多的是此类状态机。

  “其实这几种状态机之间,只要做一些改变,便可以从一种形式转变为另一种形式。把状态机精确的分为这类或那类,其实并不重要,重要的是设计者如何把握输出的结构能满足设计的整体目标,包括定时的准确性和灵活性。”

——夏宇闻《Verilog数字系统设计》

  二、状态机编码:

   状态机的参数定义采用的都是独热码,和格雷码相比,虽然独热码多用了触发器,但所用组合电路可以省一些,因而使电路的速度和可靠性有显著提高,而总的单元数并无显著增加。采用独热编码后有了多余的状态,就有一些不可达到的状态。为此在case语句的最后需要增加default分支向。这可以用默认项表示该项,也可以用确定项表示,以确保回到初始状态。一般综合器都可以通过综合指令的控制来合理地处理默认项。

    三、状态机编写

状态机分好多写法,可以有一段式、二段式和三段式,在目前,我一般会使用三段式,即将状态定义,状态转移,状态执行三部分分开,好看一点,当然这主要针对的是Mealy型。在写之前,画出状态转移图最好。

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/02/10 09:55:53
// Design Name: panweihao
// Module Name: rffe_apb_master
// Project Name: 
// Target Devices: apb_read_write_mipi
// Tool Versions: 0.1
// Description: 
// 
// Dependencies: apb读mipi的模块,并支持回读,spi指令16+8,24位的最高位为1时是spi回读
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

module rffe_apb_master(
input  wire                i_clk             ,
input  wire                i_rst_n           ,
input  wire                i_irq             ,
output wire [8:0]          o_apb_addr        ,
output wire [31:0]         o_apb_wdata       ,
input  wire [31:0]         i_apb_rdata       ,
output wire                o_apb_sel         ,
output wire                o_apb_enable      ,
output wire                o_apb_write       ,
input  wire                i_apb_ready       ,
input  wire                i_apb_err         ,

input  wire                spi_wr_valid      ,
input  wire [7:0]          spi_wr_data       ,
output wire                spi_rd_valid      ,
output wire [31:0]         spi_rd_data

    );  
localparam          RESET  = 4'b0000     ;   
localparam          IDLE   = 4'b0001     ;   
localparam          READY  = 4'b0010     ;      
localparam          READ   = 4'b0100     ;
localparam          WRITE  = 4'b1000     ;
wire[3:0]          cur_state            ;
reg [3:0]          next_state           ;   
     
reg [8:0]          o_apb_mst_addr       ;    
reg [31:0]         o_apb_mst_wdata      ;    
reg [31:0]         i_apb_mst_rdata      ;    
reg                o_apb_mst_sel        ;    
reg                o_apb_mst_enable     ;    
reg                o_apb_mst_write      ;    
reg                i_apb_slv_ready      ;    
reg                i_apb_slv_err        ;                                            
reg                rd_valid             ;    
reg [31:0]         rd_data              ;  
reg                wr_valid             ;
reg [7:0]          wr_data              ;

reg [15:0]         i_rst_n_p            ;     
wire               i_rst_n_end          ; 
reg [1:0]          i_irq_p              ;
wire               i_irq_begin          ;
reg                rst_done             ;
reg [2:0]          read_back            ;
assign  o_apb_addr     = o_apb_mst_addr      ;
assign  o_apb_wdata    = o_apb_mst_wdata     ;
assign  o_apb_sel      = o_apb_mst_sel       ;
assign  o_apb_enable   = o_apb_mst_enable    ;
assign  o_apb_write    = o_apb_mst_write     ;
assign  spi_rd_valid   = rd_valid            ;
assign  spi_rd_data    = rd_data             ;
/// output latch ///       
always@ (posedge i_clk) begin
    i_apb_mst_rdata <=  i_apb_rdata  ; 
    wr_data         <=  spi_wr_data  ;
    wr_valid        <=  spi_wr_valid ;
    i_apb_slv_ready <=  i_apb_ready  ;
    i_apb_slv_err   <=  i_apb_err    ;
end    
/ begin signal/
assign i_rst_n_end = (!i_rst_n_p[15])&(&i_rst_n_p[14:0])  ;            
                                                            
always@(posedge i_clk or negedge i_rst_n) begin             
    if(~i_rst_n) begin                                      
        i_rst_n_p <= 16'd0;                                    
    end else begin                                      
        i_rst_n_p[15:0] <= { i_rst_n_p[14:0],i_rst_n }    ;                                                                        
    end                                                 
end                                                                                                 
assign i_irq_begin = i_irq_p[0]&(~i_irq_p[1])  ;

always@(posedge i_clk or negedge i_rst_n) begin   
    if(~i_rst_n) begin                            
        i_irq_p <= 2'd0;                       
    end else begin                                
        i_irq_p[0] <= i_irq     ;  
        i_irq_p[1]<= i_irq_p[0] ;               
    end                                           
end                                                     
//
//always@(posedge i_clk or negedge i_rst_n) begin
//    if(~i_rst_n) begin
//        cur_state <= RESET;
//    end else begin
//        cur_state <= next_state;
//    end 
//end          
assign cur_state = next_state            ;
状态转换
always@(posedge i_clk or negedge i_rst_n) begin      
     if(~i_rst_n) begin             
         next_state <= RESET ;         
     end else case(cur_state)  
         RESET:begin if(rst_done)
             next_state  <= IDLE ; 
             else next_state  <= RESET ; 
         end 
         IDLE:begin
             if(i_irq_begin)begin  
                 next_state  <= READY ;
             end else begin
                 next_state  <= IDLE ; 
             end  
         end
         READY:begin     //获取008的状态,是00000040就正常,否则报错
             if(i_apb_ready)begin
                 next_state  <= READ ; 
             end else if(i_apb_slv_err)begin
                 next_state  <= IDLE ; 
             end else 
                 next_state  <= READY ;
         end
         READ:begin  ///读100寄存器的值
             if(i_apb_ready)begin
                 next_state  <= WRITE ; 
             end else if(i_apb_slv_err)begin
                 next_state  <= IDLE ; 
             end else begin
                 next_state  <= READ ;   
             end     
         end
         WRITE:begin
             if(i_apb_ready & o_apb_mst_addr[3])begin              
                 next_state  <= IDLE ;            
             end else if(i_apb_slv_err)begin       
                 next_state  <= IDLE ;             
             end else begin                        
                 next_state  <= WRITE ;             
             end                                   
         end
         default:begin 
             next_state  <= IDLE ; 
         end
     endcase     
end 


状态执行/
always@(posedge i_clk or negedge i_rst_n) begin
    if(~i_rst_n) begin  
        o_apb_mst_addr      <= 9'd0 ;
        o_apb_mst_wdata     <= 32'd0; 
        o_apb_mst_sel       <= 1'b0 ;
        o_apb_mst_enable    <= 1'b0 ;
        o_apb_mst_write     <= 1'b0 ;               
        rd_valid            <= 1'b0 ;
        rd_data             <= 32'd0;
        rst_done            <= 1'b0 ;
        read_back           <= 3'b000 ; 
    end else case(cur_state)
    RESET:begin
        if(i_rst_n_end)begin
            o_apb_mst_addr      <= 9'h000      ;             
            o_apb_mst_wdata     <= 32'h21e04002;             
            o_apb_mst_sel       <= 1'b1        ;             
            o_apb_mst_enable    <= 1'b1        ;             
            o_apb_mst_write     <= 1'b1        ;             
        end else if(i_apb_ready & (!o_apb_mst_addr[2]) )begin
             o_apb_mst_addr      <= 9'h004      ;   
             o_apb_mst_wdata     <= 32'h0000ffff;   
             o_apb_mst_sel       <= 1'b1        ;   
             o_apb_mst_enable    <= 1'b1        ;   
             o_apb_mst_write     <= 1'b1        ;                   
        end else if(i_apb_ready & o_apb_mst_addr[2] )begin
             o_apb_mst_addr      <= 9'h000      ;   
             o_apb_mst_wdata     <= 32'h00000000;   
             o_apb_mst_sel       <= 1'b0        ;   
             o_apb_mst_enable    <= 1'b0        ;   
             o_apb_mst_write     <= 1'b0        ;   
             rst_done            <= 1'b1        ;                        
        end    
    end
    IDLE:begin
         o_apb_mst_addr      <= 9'h000      ; 
         o_apb_mst_wdata     <= 32'h00000000; 
         o_apb_mst_sel       <= 1'd0        ; 
         o_apb_mst_enable    <= 1'd0        ; 
         o_apb_mst_write     <= 1'd0        ; 
         rd_valid            <= 1'd0        ; 
         rd_data             <= 32'h00000000;
         rst_done            <= 1'b0        ; 
         read_back           <= 3'b000 ;  
     end 
     READY:begin
         if(i_apb_ready)begin
             o_apb_mst_addr      <= 9'h000      ; 
             o_apb_mst_wdata     <= 32'h00000000; 
             o_apb_mst_sel       <= 1'd0        ; 
             o_apb_mst_enable    <= 1'd0        ; 
             o_apb_mst_write     <= 1'd0        ;  
         end else begin             
             o_apb_mst_addr      <= 9'h008      ;         
             o_apb_mst_wdata     <= 32'h00000000;         
             o_apb_mst_sel       <= 1'd1        ;         
             o_apb_mst_enable    <= 1'd1        ;         
             o_apb_mst_write     <= 1'd0        ;         
             rd_valid            <= 1'd0        ;         
             rd_data             <= 32'h00000000; 
         end
     end
     READ:begin     
          if(i_apb_ready)begin                      
              o_apb_mst_addr      <= 9'h000      ;  
              o_apb_mst_wdata     <= 32'h00000000;  
              o_apb_mst_sel       <= 1'd0        ;  
              o_apb_mst_enable    <= 1'd0        ;  
              o_apb_mst_write     <= 1'd0        ; 
              rd_valid            <= i_apb_ready & i_apb_rdata[24];     
              rd_data             <= i_apb_rdata ;           
          end else begin                            
              o_apb_mst_addr      <= 9'h100      ;     
              o_apb_mst_wdata     <= 32'h00000000;     
              o_apb_mst_sel       <= 1'd1        ;     
              o_apb_mst_enable    <= 1'd1        ;     
              o_apb_mst_write     <= 1'd0        ;                 
          end                                          
     end   
     WRITE:begin 
         rd_valid                <= 1'd0        ;
         rd_data                 <= 32'h00000000;
         if((!i_apb_mst_rdata[24]))begin
             if(i_apb_ready)begin
                 o_apb_mst_addr      <= 9'h000      ;    
                 o_apb_mst_wdata     <= 32'h00000000;    
                 o_apb_mst_sel       <= 1'd0        ;    
                 o_apb_mst_enable    <= 1'd0        ;    
                 o_apb_mst_write     <= 1'd0        ; 
             end else begin
                 o_apb_mst_addr      <= 9'h008      ; 
                 o_apb_mst_wdata     <= 32'h0000ffff; 
                 o_apb_mst_sel       <= 1'd1        ; 
                 o_apb_mst_enable    <= 1'd1        ; 
                 o_apb_mst_write     <= 1'd1        ;
             end                  
         end else if(i_apb_mst_rdata[24])begin
              if(i_apb_ready)begin                      
                  o_apb_mst_addr      <= 9'h000      ;  
                  o_apb_mst_wdata     <= 32'h00000000;  
                  o_apb_mst_sel       <= 1'd0        ;  
                  o_apb_mst_enable    <= 1'd0        ;  
                  o_apb_mst_write     <= 1'd0        ; 
                  read_back           <= 3'b001      ;
              end else if(wr_valid) begin 
                 o_apb_mst_addr      <= 9'h100            ;     
                 o_apb_mst_wdata     <= {24'h0000,wr_data};  
                 o_apb_mst_sel       <= 1'd1              ;  
                 o_apb_mst_enable    <= 1'd1              ;  
                 o_apb_mst_write     <= 1'd1              ;  
             end else if(read_back == 3'b001)begin
                 o_apb_mst_addr      <= 9'h008      ;   
                 o_apb_mst_wdata     <= 32'h0000ffff;   
                 o_apb_mst_sel       <= 1'd1        ;   
                 o_apb_mst_enable    <= 1'd1        ;   
                 o_apb_mst_write     <= 1'd1        ;   
             end
         end
     end
         default:begin
             o_apb_mst_addr      <= 9'h000      ;
             o_apb_mst_wdata     <= 32'h00000000;
             o_apb_mst_sel       <= 1'd0        ;
             o_apb_mst_enable    <= 1'd0        ;
             o_apb_mst_write     <= 1'd0        ;
             rd_valid            <= 1'd0        ;
             rd_data             <= 32'h00000000;
         end
     endcase   
end
endmodule

4.移位操作

Verilog中的移位操作有两类:逻辑移位和算术移位。

逻辑右移(>>):1个操作数向右移位,产生的空位用0填充;x>>1,x左移一位

逻辑左移(<<):1个操作数向左移位,产生的空位用0填充;

算术右移(>>>):1个操作数向右移位。如果是无符号数,则产生的空位用0填充;有符号数则用其符号位填充;

算数左移(<<<):1个操作数向左移位,产生的空位用0填充;

算术右移符号位要一起移动,并且在左边补上符号位,也就是如果符号位是1就补1符号位是0就补0。比如:11100算术右移一位为11110(符号位1跟着一起移动并且左边补了1)对于二进制的数值来说右移n位等于原来的数值除以2的n次方。比如10110100十进制是76(需要先将这个补码转换成原码之后再转换成十进制),右移两位后是11101101转成十进制是19恰好是76的4倍。

​ps:这种倍数关系只适用于右移后被舍弃的低位不含1的情况,否则每舍一次1则代表余数被舍去,保留整数部分。

还可以用这种方法:

reg [31:0] a,b;  ~~~b <={a[30:0],1'b0};或者~~~b<={1'b0,a[31:1]};

5.反压操作

当入口流量大于出口流量,这时候就需要反压,或者,当后级未准备好时,如果本级进行数据传递,那么它就需要反压前级,所以此时前级需要将数据保持不动,直到握手成功才能更新数据。而反压在多级流水线中就变得稍显复杂,原因在于,比如我们采用三级流水设计,如果我们收到后级反压信号,我们理所当然想反压本级输出信号的寄存器,但是如果只反压最后一级寄存器,那么会面临一个问题,就是最后一级寄存器数据会被前两级流水冲毁,导致数据丢失,引出数据安全问题,所以我们此时需要考虑反压设计。

分类:三种,不带存储体的反7.压,带存储体的逐级反压,带存储体的跨级反压

在途,水线waterline

6.异步处理

打拍,握手,FIFO

 7.基本运算

 多看书,多写代码

8.低功耗理解

能量是功耗在时间上的累计

动态(开关)功耗:是设备运行时或者说信号改变时所消耗的功耗(翻转功耗+短路功耗)

静态(内部)功耗:是设备上电但是信号没有改变时所消耗的功耗;

简化后,Switching power,Pdyn = Ceff(p_trans·Cl)··VDD2·fclock

 

RTL级低功耗设计可以看一下这个: 数字芯片设计之RTL级低功耗设计 - 知乎 (zhihu.com)

静态:多阈值工艺,电源门控,体偏置

动态:多电压域,预计算,门控时钟(毛刺问题)

9.ECO电路修改方法

ECO:engineering change order 工程改变命令,手动修改集成电路(netlist)

搁置

10.资源与面积评估

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值