了解简单的循环仲裁器Verilog代码

时间:2019-03-06 03:57:36

标签: verilog fpga round-robin

看看下面的arbiter.v代码:

有人告诉我想起rr_arbiter,它是一个简化的ripple-borrow circuit,可以环绕。

  

'base'是一个热信号,指示第一个请求应该是   考虑获得赠款。

是吗?你们了解如何生成“基本”输入信号吗?

  

注意减法。借位逻辑使它进行搜索以找到   下一个设置的位。

为什么〜(double_req-base)?

module arbiter (
    req, grant, base
);

parameter WIDTH = 16;

input [WIDTH-1:0] req;
output [WIDTH-1:0] grant;
input [WIDTH-1:0] base;

wire [2*WIDTH-1:0] double_req = {req,req};
wire [2*WIDTH-1:0] double_grant = double_req & ~(double_req-base);
assign grant = double_grant[WIDTH-1:0] | double_grant[2*WIDTH-1:WIDTH];

endmodule

2 个答案:

答案 0 :(得分:2)

编辑:正如有人指出的那样,我最初仅指出了如何设置输入信号,并给出了两种特殊情况作为示例。让我尝试解释它是如何工作的。一个好的开始是您的问题:

  

为什么〜(double_req-base)?

正如某人向您指出的那样,这是基于ripple borrow subtractor的原理。当您从另一个数字中减去一个数字时,无论您使用的是什么数字系统,都将从最低顺序开始,然后尝试从相同顺序中减去两个数字。在一个二进制示例中,它看起来像这样:

1011     =    11
0010 -   =     2 -
──────        ────
1001     =     9

如您所见,1 - 1有效且产生0。但是,如果不可能的话,您可以从更高的订单号借用This image显示了一个简单的示例,显示了十进制系统的外观。十进制系统中的一个示例可能是:

1001     =     01(10)1     =    9
0010 -   =     00  1 0 -   =    2 - 
──────         ─────────        ───
0111     =     01  1 1     =    7

由于0 - 1在第二位置不可能,所以我们从第四位置取1,将第三位置设置为1,然后将第二位置设置为10(因此,在十进制系统中为2)。这与example in the decimal system I posted before非常相似。

对于仲裁者很重要:从req的位置看,原始数字(base)的下一个1将被设置为零。基本位置和该0之间的所有数字都将设置为1。在将减法结果取反之后,从底数看,只有该位置为1

但是,使用此技术,比底数低的数字仍然可以1。因此,我们将原始数字与您计算出的数字(double_req & ~(double_req-base)结合在一起。这样可以确保排除在{strong>低于 1的位置的base

最后,将其加倍的事实确保了它不会用完要借的头寸。如果需要从这些“第二”加倍块中借用,则析取符(double_grant[WIDTH-1:0] | double_grant[2*WIDTH-1:WIDTH])确保返回正确的索引。我在下面的示例中添加了一个示例。

原始帖子

您可以将base解释为req中的起始索引。这是代码将考虑仲裁的第一位。您应该将此值设置为last_arbitrated_position + 1

看看我在下面创建的4位(伪代码)示例。让我们取一些任意数字:

req  = 4'b1101 // Your vector from which one position should be arbitrated
base = 4'b0010 // The second position is the first position to consider

现在,来自arbiter.v的内容如下:

double_req   = 1101 1101
double_grant = 1101 1101 & ~(1101 1011) = 1101 1101 & 0010 0100 = 0000 0100

在最后步骤中,arbiter.v然后实际分配应授予的职位:

grant = 0100 | 0000 = 0100

这是正确的,因为我们将第二个位置设置为基准,而下一个有效位置是第三个位置。另一个示例,其中基准是在req中也有效的头寸,是:

req  = 4'b1111
base = 4'b0010
double_req   = 1111 1111
double_grant = 1111 1111 & ~(1111 1101) = 1111 1111 & 0000 0010 = 0000 0010
grant = 0010 | 0000

这又是正确的,因为在这种情况下,我们定义了可以仲裁的第一个位置是第二个位置,并且这个位置确实有效。

您发布的代码示例还负责包装最重要的位。这意味着,如果您设置了一个基准,但是没有比该基准大的有效位置,它将环绕并从最低有效位开始仲裁。这种情况的一个示例是:

req  = 4'b0010
base = 4'b0100
double_req   = 0010 0010
double_grant = 0010 0010 & ~(1110 0001) = 0010 0010 & 0001 1110 = 0010 0000
grant = 0000 | 0010

答案 1 :(得分:1)

仲裁程序的目的是找出要授予的请求,并避免重复将其授予同一源。

现在假设我们设置了几个req位和base,这是先前授予的请求向左移1的状态。

因此,您的任务是在基本位(或其附近)的左侧找到第一个 set 位,以授予请求。减法运算将翻转所有剩余的位 基本位,以第一个 set 位结束,例如

 1100 << req
-0010 << base
 ====
 1010
 -^^-
  ^

req[2]位是我们要授予请求的位。它被翻转为“ 0”。它的所有左位和基础位的右位均未更改。我们需要获取最后更改为“ 0”的位。

做到这一点的方法是将求和的值与减法结果取反。更改的位将始终具有单个模式:最左边的位将为“ 0”,其余的位将为“ 1”。该最左边将完全位于请求中包含“ 1”的位置。因此,取反将使其变为“ 1”,并将左右所有未更改的位取反。将它与原始请求进行AND操作将有效地去除未更改的位,并保证将保留我们新发现的'1'。

 1010 << result of subtraction
~0101 << ~(req-base)
&1100 << req
=0100

现在,如果我们要溢出,就会出现问题:

 0010
-1000
 ====
 1010
~0101
&1010
=0000 << oops

但是我们要从请求中获取bit [1]。 解决该问题的方法是在该req的前面加上另一个 0010 0010 -0000 1000 ==== 0001 1010 ~1110 0101 &0010 0010 =0010 0000 副本,然后继续减法以达到最低位。 部分:

0010 | 0000 = 0010

现在我们只需要在上下部分之间进行选择即可

from flask import Flask
from flask_bcrypt import Bcrypt
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
db = SQLAlchemy(app)

db.create_all()
# Create our database modl
class User(db.Model):
    """ User Model for storing user related details """
    __tablename__ = "users"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(255), unique=True, nullable=False)
    python_object = db.Column(db.PickleType(), nullable=True)


    def __init__(self, name):
        self.name = name

    # create funciton to add python object
    def add_python_object(self, object_to_store):
        persistent_python_object = db.Column() # <-- would like to add python object here
        self.persistent_python_object = object_to_store

# Define our object we would like to store
class ExampleObject(object):

    def __init__(self, val_1, val_2):
        self.val_1 = val_1
        self.val_2  = val_2

    def does_something_from_storage(self):
        return self.val_1 + self.val_2

# Create user
adder = User('Adder')
adder.add_python_object(ExampleObject(3,4))

# Add to database
db.session.add(adder)
db.session.commit()

# Retrieve python object
user = User.query.filter_by(name='Adder').first()
result = user.persistent_python_object.does_something_from_storage()

您在这里,您就得到了结果。