4810|4

26

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

mini risc mcu源码 [复制链接]

源码来自risc-v中文社区的这个帖子,本mini risc mcu学习源代码有二个对应的文件,一个是chisel源码文件,另一个是对应的verilog源文件,其中chisel源文件进行了行注释,相信不懂chisel的也能明白很多东西:
chisel源码:
import chisel3._
import chisel3.util._
class Risc extends Module{
  val io = IO(new Bundle {
    val isWr Input(Bool())
    val wrAddr Input(UInt(8.W))
    val wrData Input(UInt(32.W))
    val boot Input(Bool())
    val valid Output(Bool())
    val out Output(UInt(32.W))
  })
  val file Mem(256,UInt(32.W)) //Mem的构造参数,第一个是数量,第二个是chisel类型 file表示二进制码文件.bin内容
  val code Mem(256,UInt(32.W)) //指令代码区
  val pc RegInit(0.U(8.W)) //当前指令地址指针
  val add_op :: imm_op :: Nil = Enum(2//操作符
  val inst code(pc//根据pc值在代码区取指令值
  val op inst(31,24//32位指令码中高8位
  val rci inst(23,16//32位指令码中次高8位
  val rai inst(15,8//32位指令码中中8位 //相对偏移地址
  val rbi inst(7,0//32位指令码中低8位 //相对偏移地址
  val ra Mux(rai === 0.U,0.U,file(rai)) //根据指令码中中8位地址从.bin文件中取对应偏移地址所对应的值
  val rb Mux(rbi === 0.U,0.U,file(rbi)) //根据指令码中低8位地址从.bin文件中取对应偏移地址所对应的值
  val rc = Wire(UInt(32.W)) //指令操作的结果
  io.valid := false.B //默认值 因为io.valid在逻辑判断过程中是有条件改变值,所以根据语法需要,output类型需要赋初值,否则会报错
  io.out := 0.U
  rc := 0.U

  when(io.isWr) { //写
    code(io.wrAddr) := io.wrData  //将数据写到代码区
  } .elsewhen(io.boot) { //boot 上电启动时
    pc := 0.U  //当前指令地址要复位
  } .otherwise { //从代码区取指执行
    switch(op) { //根据指令码的高8位区分指令
      is(add_op) {  //add操作 间接寻址
        rc := ra rb //最终io.out输出结果为指令码中低8位与中8位对应的.bin二进制文件中偏址内容结果之和
      }
      is(imm_op) { //imm操作 直接寻址
        rc := (rai << 8.U).asUInt() | rbi  //指令码中中8位作高8位,指令码中低8位作低8位,这样的16位作为最终输出
      }
    }
    io.out := rc
    when(rci === 255.U) { //指令码中次高8位全为1
      io.valid := true.B
    } .otherwise {
      file(rci) := rc
    }
    pc := pc 1.U //指令地址指针加1
  }
}


verilog代码:
module Risc(
  input         clock,
  input         reset,
  input         io_isWr,
  input  [7:0]  io_wrAddr,
  input  [31:0] io_wrData,
  input         io_boot,
  output        io_valid,
  output [31:0] io_out
);
  reg [31:0] file [0:255]; // @[Risc.scala 14:17]
  reg [31:0] _RAND_0;
  wire [31:0] file__T_1_data; // @[Risc.scala 14:17]
  wire [7:0] file__T_1_addr; // @[Risc.scala 14:17]
  wire [31:0] file__T_3_data; // @[Risc.scala 14:17]
  wire [7:0] file__T_3_addr; // @[Risc.scala 14:17]
  wire [31:0] file__T_12_data; // @[Risc.scala 14:17]
  wire [7:0] file__T_12_addr; // @[Risc.scala 14:17]
  wire  file__T_12_mask; // @[Risc.scala 14:17]
  wire  file__T_12_en; // @[Risc.scala 14:17]
  reg [31:0] code [0:255]; // @[Risc.scala 15:17]
  reg [31:0] _RAND_1;
  wire [31:0] code_inst_data; // @[Risc.scala 15:17]
  wire [7:0] code_inst_addr; // @[Risc.scala 15:17]
  wire [31:0] code__T_4_data; // @[Risc.scala 15:17]
  wire [7:0] code__T_4_addr; // @[Risc.scala 15:17]
  wire  code__T_4_mask; // @[Risc.scala 15:17]
  wire  code__T_4_en; // @[Risc.scala 15:17]
  reg [7:0] pc; // @[Risc.scala 16:19]
  reg [31:0] _RAND_2;
  wire [7:0] op = code_inst_data[31:24]; // @[Risc.scala 19:16]
  wire [7:0] rci = code_inst_data[23:16]; // @[Risc.scala 20:17]
  wire [7:0] rai = code_inst_data[15:8]; // @[Risc.scala 21:17]
  wire [7:0] rbi = code_inst_data[7:0]; // @[Risc.scala 22:17]
  wire  _T = rai == 8'h0; // @[Risc.scala 23:20]
  wire [31:0] ra = _T ? 32'h0 : file__T_1_data; // @[Risc.scala 23:15]
  wire  _T_2 = rbi == 8'h0; // @[Risc.scala 24:20]
  wire [31:0] rb = _T_2 ? 32'h0 : file__T_3_data; // @[Risc.scala 24:15]
  wire  _T_5 = 8'h0 == op; // @[Conditional.scala 37:30]
  wire [31:0] _T_7 = ra + rb; // @[Risc.scala 37:18]
  wire  _T_8 = 8'h1 == op; // @[Conditional.scala 37:30]
  wire [15:0] _GEN_31 = {rai, 8'h0}; // @[Risc.scala 40:20]
  wire [22:0] _T_9 = {{7'd0}, _GEN_31}; // @[Risc.scala 40:20]
  wire [22:0] _GEN_32 = {{15'd0}, rbi}; // @[Risc.scala 40:37]
  wire [22:0] _T_10 = _T_9 | _GEN_32; // @[Risc.scala 40:37]
  wire [22:0] _GEN_0 = _T_8 ? _T_10 : 23'h0; // @[Conditional.scala 39:67]
  wire [31:0] _GEN_1 = _T_5 ? _T_7 : {{9'd0}, _GEN_0}; // @[Conditional.scala 40:58]
  wire  _T_11 = rci == 8'hff; // @[Risc.scala 44:14]
  wire  _GEN_5 = _T_11 ? 1'h0 : 1'h1; // @[Risc.scala 44:25]
  wire [31:0] _GEN_9 = io_boot ? 32'h0 : _GEN_1; // @[Risc.scala 32:24]
  wire [31:0] rc = io_isWr ? 32'h0 : _GEN_9; // @[Risc.scala 30:17]
  wire [7:0] _T_14 = pc + 8'h1; // @[Risc.scala 49:14]
  wire [31:0] _GEN_10 = io_boot ? 32'h0 : rc; // @[Risc.scala 32:24]
  wire  _GEN_11 = io_boot ? 1'h0 : _T_11; // @[Risc.scala 32:24]
  wire  _GEN_14 = io_boot ? 1'h0 : _GEN_5; // @[Risc.scala 32:24]
  assign file__T_1_addr = code_inst_data[15:8];
  assign file__T_1_data = file[file__T_1_addr]; // @[Risc.scala 14:17]
  assign file__T_3_addr = code_inst_data[7:0];
  assign file__T_3_data = file[file__T_3_addr]; // @[Risc.scala 14:17]
  assign file__T_12_data = io_isWr ? 32'h0 : _GEN_9;
  assign file__T_12_addr = code_inst_data[23:16];
  assign file__T_12_mask = 1'h1;
  assign file__T_12_en = io_isWr ? 1'h0 : _GEN_14;
  assign code_inst_addr = pc;
  assign code_inst_data = code[code_inst_addr]; // @[Risc.scala 15:17]
  assign code__T_4_data = io_wrData;
  assign code__T_4_addr = io_wrAddr;
  assign code__T_4_mask = 1'h1;
  assign code__T_4_en = io_isWr;
  assign io_valid = io_isWr ? 1'h0 : _GEN_11; // @[Risc.scala 26:12 Risc.scala 45:16]
  assign io_out = io_isWr ? 32'h0 : _GEN_10; // @[Risc.scala 27:10 Risc.scala 43:12]
`ifdef RANDOMIZE_GARBAGE_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_INVALID_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_REG_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_MEM_INIT
`define RANDOMIZE
`endif
`ifndef RANDOM
`define RANDOM $random
`endif
`ifdef RANDOMIZE_MEM_INIT
  integer initvar;
`endif
`ifndef SYNTHESIS
initial begin
  `ifdef RANDOMIZE
    `ifdef INIT_RANDOM
      `INIT_RANDOM
    `endif
    `ifndef VERILATOR
      `ifdef RANDOMIZE_DELAY
        #`RANDOMIZE_DELAY begin end
      `else
        #0.002 begin end
      `endif
    `endif
  _RAND_0 = {1{`RANDOM}};
  `ifdef RANDOMIZE_MEM_INIT
  for (initvar = 0; initvar < 256; initvar = initvar+1)
    file[initvar] = _RAND_0[31:0];
  `endif // RANDOMIZE_MEM_INIT
  _RAND_1 = {1{`RANDOM}};
  `ifdef RANDOMIZE_MEM_INIT
  for (initvar = 0; initvar < 256; initvar = initvar+1)
    code[initvar] = _RAND_1[31:0];
  `endif // RANDOMIZE_MEM_INIT
  `ifdef RANDOMIZE_REG_INIT
  _RAND_2 = {1{`RANDOM}};
  pc = _RAND_2[7:0];
  `endif // RANDOMIZE_REG_INIT
  `endif // RANDOMIZE
end // initial
`endif // SYNTHESIS
  always @(posedge clock) begin
    if(file__T_12_en & file__T_12_mask) begin
      file[file__T_12_addr] <= file__T_12_data; // @[Risc.scala 14:17]
    end
    if(code__T_4_en & code__T_4_mask) begin
      code[code__T_4_addr] <= code__T_4_data; // @[Risc.scala 15:17]
    end
    if (reset) begin
      pc <= 8'h0;
    end else if (!(io_isWr)) begin
      if (io_boot) begin
        pc <= 8'h0;
      end else begin
        pc <= _T_14;
      end
    end
  end
endmodule

最新回复

有注释的就是赞,还在学习Chisel的很多语法。  详情 回复 发表于 2023-5-23 09:57
点赞 关注
个人签名

risc-v org cn欢迎您加入risc

 

回复
举报

6802

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

看后,相信不懂chisel的也能明白很多东西

详细,是这样的

 
 

回复

53

帖子

0

TA的资源

一粒金砂(中级)

板凳
 

这也太好了, 正是需要的东西, 找了半天,感谢楼主分享。

 
 
 

回复

15

帖子

0

TA的资源

一粒金砂(中级)

4
 

正是好东西了, 这也太需要的, 找了半天,厉害,代码大牛,

 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

5
 
有注释的就是赞,还在学习Chisel的很多语法。
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
推荐帖子
快速增强路由器安全的十个小技巧

  要不是思科最新发布的安全警告的提醒,很多网络管理员还没有认识到他们的路由器能够成为攻击的热点。路由器操作系统同 ...

IC名词解释

1、什么是MRAM?MARM(Magnetic Random Access Memory) 是一种非挥发性的磁性随机存储器。它拥有静态随机存储器(SRAM)的高速读取 ...

一个老电子工程师的建议

本帖最后由 paulhyde 于 2014-9-15 03:08 编辑 咱当电子工程师也是十余年了,不算有出息,环顾四周,也没有看见几个有出息的! ...

【原创】LPC1752读取AT24C08C的原理与实现

本帖最后由 rain_noise 于 2015-3-30 20:08 编辑 1 简介1.1 LPC1752及AT24C08C简介LPC1752是NXP推出的一款Cortex M3的芯片, ...

MAX31865怎么转换

本帖最后由 sky999 于 2020-9-12 19:34 编辑 MAX31865默认是400R电阻,转换如下表,但是没有400R电阻,所以用了430电阻,请问 ...

【树莓派Pico测评】——by fxyc87

@fxyc87 【树莓派Pico测评】-开箱+下载 【树莓派Pico测评】- 开始写程序 【树莓派Pico测评】- 开始编译程序2 ...

TM1668数据手册

最近拆了个蓝牙音箱 看到里面的数码管驱动芯片型号是TM1668 想在网上下载份规格书来看看 发现搜索结果挺少的,应该是比 ...

测评汇总:免费申请|ST NUCLEO-U575ZI-Q

活动详情:【免费申请|ST NUCLEO-U575ZI-Q】更新至 2023-02-07测评报告汇总:@流行科技 之ADC多通道常规转换方式ThreadX体验 简 ...

【STM32MP135F-DK】6-Linux驱动开发--led的 platform驱动框架

本帖最后由 qiao--- 于 2023-12-12 22:12 编辑 最近在看一些大佬写的程序时候发现有的地方看不懂了,于是这次回来复习一下pla ...

【Follow me第二季第1期】任务提交贴

本帖最后由 Alohaq 于 2024-11-4 13:04 编辑 一、前言 Follow me第二季第1期的用的主板为Adafruit Circuit Playground Exp ...

关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表