Verilog and RISC hardware organization

Week3:本周学习的知识主要包括:Verilog的基本语法知识以及一个简单的RISC处理器的硬件组成,并使用Verilog描述了各个硬件模块的功能。

内容回顾

Verilog语法的几点回顾

  • 逻辑操作和位宽操作
    • logic operation: a && b、a || b、!c
    • Bit-wise operation: a&b、a|b、~c
  • 逻辑移位和算术移位
    • logic shift: a >> 1, a is unsigned
    • arithmetic shift: a >>> 1, a is signed
  • 位宽划分
    • a[7-:4] = a[7:4] = a[4+:4]
  • signed 补码 、unsigned 原码

由于之前上过Verilog的语法课,因此以上知识点只是整理了我认为比较重要的几处,更多的Verilog语法请参考以下链接

Verilog语法资料
Verilog 有什么奇技淫巧?

一个简单的RISC硬件组成

麻雀虽小,五脏俱全。根据冯诺依曼理论,一个计算机包括存储器、运算器、控制器以及输入输出设备。该节介绍的极简RISC硬件也具有这些,当然不包括输入输出设备。下面将用Verilog去实现这些硬件电路,完成一个简单的RISC处理器。

存储器 (Memory)

  • 寄存器列表(RF)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    module regfile #(
    parameter REG_DATA_WIDTH = 4,
    parameter REG_ADDR_WIDTH = 16,
    parameter REG_NUMBER = 16
    )
    (
    input [REG_ADDR_WIDTH-1:0] rs1_addr,
    input [REG_ADDR_WIDTH-1:0] rs2_addr,
    input [REG_ADDR_WIDTH-1:0] rd_addr,
    input [REG_DATA_WIDTH-1:0] rd_data,
    input RegWEn,
    input clk,rst_n,

    output [REG_DATA_WIDTH-1:0] rs1_data,
    output [REG_DATA_WIDTH-1:0] rs2_data
    );

    reg [REG_DATA_WIDTH-1:0] rf [REG_NUMBER-1:0];

    // reg0 is always equal to zero
    assign rs1_data = rs1_addr == 0? 0:rf[rs1_addr];
    assign rs2_data = rs2_addr == 0? 0:rf[rs2_addr];

    always@ (posedge clk or negedge rst_n) begin
    if (!rst_n) begin: REGFILE
    integer i;
    for (i=0; i<REG_NUMBER; i=i+1) begin
    rf[i] <= 0;
    end
    end
    else if (RegWEn && rd_addr!=0) begin
    rf[rd_addr] <= rd_data;
    end
    end

    endmodule
  • 数据存储器(DCM)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    module dcmen #(
    parameter MEM_ADDR_WIDTH = 5,
    parameter MEM_DATA_WIDTH = 16,
    parameter MEM_NUMBER = 32
    )
    (
    input clk,
    input MemWEn,
    input [MEM_ADDR_WIDTH-1:0] addr,
    input [MEM_DATA_WIDTH-1:0] dataw,

    output [MEM_DATA_WIDTH-1:0] datar
    );

    reg [MEM_DATA_WIDTH-1:0]RAM [MEM_NUMBER-1:0];

    always @(posedge clk) begin
    if (MemWEn) begin
    RAM[addr] <= dataw;
    end
    end

    assign datar = RAM[addr] ;

    endmodule
  • 指令存储器(ICM)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    module icmem #(
    parameter PC_WIDTH = 16,
    parameter ISA_WIDTH = 16,
    parameter MEM_ADDR_WIDTH = 5,
    parameter MEM_DATA_WIDTH = 16,
    parameter MEM_NUMBER = 32
    )
    (
    input clk,
    input rst_n,
    input inst_wen,
    input [ISA_WIDTH-1:0] input_inst,

    output [ISA_WIDTH-1:0] current_inst
    );

    reg [PC_WIDTH-1:0] pc;

    always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
    // reset
    pc <= 0;
    end
    else begin
    pc <= pc + 1;
    end
    end

    dcmen #(
    .MEM_ADDR_WIDTH(MEM_ADDR_WIDTH),
    .MEM_DATA_WIDTH(MEM_DATA_WIDTH),
    .MEM_NUMBER(MEM_NUMBER)
    ) inst_dcmen (
    .clk (clk),
    .MemWEn (inst_wen),
    .addr (pc),
    .dataw (input_inst),
    .datar (current_inst)
    );

    endmodule

运算器 (ALU)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
module MAC_ALU #(
parameter REG_DATA_WIDTH = 16
)
(
input clk,
input funct,
input [REG_DATA_WIDTH-1:0] rs1,rs2,

output [REG_DATA_WIDTH-1:0] rd
);

wire [REG_DATA_WIDTH-1:0] product;
wire [REG_DATA_WIDTH-1:0] addend1,addend2;
reg [REG_DATA_WIDTH-1:0] psum;

assign product = $signed(rs1) * $signed(rs2);
assign addend1 = funct? 0: product;
assign addend2 = funct? rs2: psum;
assign rd = addend1 + addend2;

always @(posedge clk) begin
if (funct) begin
psum <= 0;
end
else begin
psum <= rd;
end
end

endmodule

关于Verilog语法中*的使用,可以参考以下链接

在Verilog中直接调用*实现乘法器,其延迟和占用资源如何?

控制器 (IDU)

1

极简指令集与其硬件组成

opcode 目标Reg 源寄存器/立即数 说明
Load rd rs+imm(5b) 在rst imm地址 -> rd
Store / rs(addr)/rs(data) rs(data) -> Mem index=rs(地址)
MOV rd imm(9b) 赋值 -> rd
MAC rd rs1/funct=1 乘加
MAC rd rs1/funct=1 乘加

注明:不同颜色的数据通路对应其相同颜色的指令

HomeWork

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×