首页
游戏
影视
直播
广播
听书
音乐
图片
更多
看书
微视
主播
统计
友链
留言
关于
论坛
邮件
推荐
我的硬盘
我的搜索
我的记录
我的文件
我的图书
我的笔记
我的书签
我的微博
Search
1
在IC617中进行xa+vcs数模混仿
81 阅读
2
科普:Memory Compiler生成的Register file和SRAM有何区别?
73 阅读
3
virtuoso和empyrean alps模拟仿真和混仿教程
73 阅读
4
后仿中$setup,$hold与$setuphold
44 阅读
5
文档内容搜索哪家强? 15款文件搜索软件横向评测
35 阅读
默认分类
芯片市场
数字电路
芯片后端
模拟电路
芯片验证
原型与样片验证
算法与架构
DFX与量产封装
PC&Server OS设置
移动OS设置
软件方案
新浪备份
有道备份
登录
Search
标签搜索
python
Docker
vscode
linux
systemverilog
vcs
STM32
PyQT
EDA
FPGA
gvim
cadence
Alist
xilinx
UVM
uos
macos
package
MCU
risc-v
bennyhe
累计撰写
378
篇文章
累计收到
31
条评论
首页
栏目
默认分类
芯片市场
数字电路
芯片后端
模拟电路
芯片验证
原型与样片验证
算法与架构
DFX与量产封装
PC&Server OS设置
移动OS设置
软件方案
新浪备份
有道备份
页面
游戏
影视
直播
广播
听书
音乐
图片
看书
微视
主播
统计
友链
留言
关于
论坛
邮件
推荐
我的硬盘
我的搜索
我的记录
我的文件
我的图书
我的笔记
我的书签
我的微博
搜索到
40
篇与
的结果
2026-01-07
IPYXACT:Python 中的 IEEE-1685 (IP-XACT) 处理工具
IPYXACT:Python 中的 IEEE-1685 (IP-XACT) 处理工具项目介绍IPYXACT 是一个基于 Python 的库,旨在简化对 IEEE-1685 标准(通常称为 IP-XACT)的支持。这一标准定义了用于描述集成电路知识产权(IP核)元数据的 XML 方式。IPYXACT 提供了解析、操作及生成 IP-XACT 描述文件的能力,对于那些需要处理或创建 SoC 设计中IP组件描述的软件开发人员和硬件工程师来说非常有用。项目快速启动要快速开始使用 IPYXACT,首先确保你的环境中已经安装了 Python 3.6 或更高版本。然后,通过以下命令将项目添加到你的环境:pip install ipyxactbash接下来,尝试简单的示例来体验其基本功能: from ipyxact.ipyxact import Component # 创建一个新的组件实例 comp = Component() compvendor = comp.component_vendor compvendor.name = "Example Vendor" compvendor.description = "A demonstration component" # 保存这个组件到XML文件 with open("example.xml", "wb") as f: comp.write_xml(f) code here...这段代码创建了一个最简化的 IP-XACT 元数据结构并保存到了一个 XML 文件中。应用案例和最佳实践在设计复杂的SoC时,IPYXACT可以极大地帮助管理IP核的元数据。例如,当你需要自动化生成IP核的配置界面时,可以通过解析已有IP-XACT描述文件,自动生成对应的配置UI,或者在进行IP复用过程中,验证IP的合规性和一致性。示例:自动构建IP配置界面假设已有一个IP-XACT描述文件,你可以读取该文件来获取IP的信息,然后利用这些信息动态地创建GUI元素。 component = Component.from_file("your_ip.xact") for memory_map in component.memory_maps: for register in memory_map.register_list: # 假设这里会根据register的信息生成GUI控件 print(f"Register: {register.name} at {register.address_offset}") code here...典型生态项目虽然直接相关的“典型生态项目”特定于 IPYXACT 的提及不多,但在嵌入式系统和SoC设计领域,结合使用 IPYXACT 的项目通常与硬件描述语言(如Verilog、SystemVerilog)、EDA工具(如Vivado、Quartus)以及芯片自动化流片流程紧密相关。开发者可能会集成IPYXACT到他们的工作流程中,以自动化生成或验证与IP核相关的文档、配置界面或是用于构建系统的脚本,从而提高整个设计周期的效率和准确性。对于进一步的集成案例和技术堆栈的探索,建议参考 FPGA 开发、ASIC设计社区以及电子设计自动化领域的其他开源和商业解决方案。开发者可以在设计流程的不同阶段利用IPYXACT的标准化信息,促进IP核的重用和管理————————————————版权声明:本文为CSDN博主「申梦珏Efrain」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/gitblog_00259/article/details/141456709
2026年01月07日
2 阅读
0 评论
0 点赞
2026-01-06
spi master接口的fpga实现
https://www.cnblogs.com/kingstacker/p/7490002.html前言当你器件的引脚贼少的时候,需要主机和从机通信,spi就派上了用场,它可以一对多,但只是片选到的从机能和主机通信,其他的挂机。spi:serial peripheral interface 串行外围接口大致了解:spi是个同步协议,数据在master和slaver间交换通过时钟sck,由于它是同步协议,时钟速率就可以各种变换。sck:主机提供,从机不能操控,从器件由主机产生的时钟控制。数据只有在sck来了的上升沿或者下降沿才传输。高级一点的spi芯片有配置寄存器,高级一点的工作有四种模式,采样相位和sck空闲电平可配置。当然在这里我们主要实现简单的spi协议:sck是系统时钟的四分频,wr请求信号有效时,主机开始工作,数据位8bit,sck空闲时低电平,工作时第一个沿数据传输。只有一个从机,cs低电平片选。看下结构:接口定义:编码实现:(版权所有,请勿用于商业用途,仅供学习使用)//************************************************ // Filename : spi_ms_test1.v // Author : Kingstacker // Company : School // Email : kingstacker_work@163.com // Device : Altera cyclone4 ep4ce6f17c8 // Description : spi master module;data 8bit;sck is 4 div of the clk; //************************************************ module spi_ms #(parameter WIDTH = 8)( //input; input wire clk, input wire rst_n, input wire wr, //send request; input wire [WIDTH-1:0] master_din, //the data you want send; input wire miso, //the data form slave; //output; output reg cs, //slave select; output reg sck, //data exchange clock; output reg mosi, //master out; output reg [WIDTH-1:0] master_dout //the data you received; ); localparam CLK_HZ = 50_000_000; //clk frequency; localparam SCK_HZ = 12_500_000; //sck frequency; localparam DIV_NUMBER = CLK_HZ / SCK_HZ; localparam CNT_MAX = (DIV_NUMBER >>1) - 1'b1; localparam DATA_CNT_MAX = 5'd31; localparam MOSI_CNT_MAX = 3'd7; localparam IDEL = 2'b00; localparam SEND = 2'b01; localparam FINISH = 2'b10; reg cnt; //sck cnt; reg sck_en; //enable sck; reg data_cnt_en; reg sck_reg1; reg sck_reg2; wire sck_p; //posedge sck; wire sck_n; //negedge sck; wire send_over; reg [1:0] cstate; reg [4:0] data_cnt; //cnt the send data; reg [2:0] mosi_cnt; reg [WIDTH-1:0] master_din_reg; reg [WIDTH-1:0] master_dout_reg; //produce sck; always @(posedge clk or negedge rst_n) begin if (~rst_n) begin cnt <= 0; sck <= 1'b0; end //if else begin if (sck_en == 1'b1) begin if (cnt == CNT_MAX) begin cnt <= 0; sck <= ~sck; end else begin cnt <= cnt + 1'b1; sck <= sck; end end else begin cnt <= 0; sck <= 1'b0; end end //else end //always //produce sck_p and sck_n; always @(posedge clk or negedge rst_n) begin if (~rst_n) begin sck_reg1 <= 1'b0; sck_reg2 <= 1'b0; end //if else begin sck_reg1 <= sck; sck_reg2 <= sck_reg1; end //else end //always assign sck_p = (sck_reg1 & (~sck_reg2)); //sck posedge; assign sck_n = ((~sck_reg1) & sck_reg2); //sck negedge; //fsm;hot code; always @(posedge clk or negedge rst_n) begin if (~rst_n) begin cstate <= IDEL; end else begin case (cstate) IDEL: cstate <= (wr)? SEND : IDEL; SEND: cstate <= (send_over) ? FINISH : SEND; FINISH: cstate <= IDEL; default: cstate <= IDEL; endcase //case end end always @(posedge clk or negedge rst_n) begin if (~rst_n) begin cs <= 1'b1; data_cnt_en <= 1'b0; sck_en <= 1'b0; master_din_reg <= 0; master_dout <= 0; end else begin case (cstate) IDEL: begin data_cnt_en <= 1'b0; master_din_reg <= (wr) ? master_din : master_din_reg; //load the data you want send to slaver; end SEND: begin data_cnt_en <= 1'b1; cs <= 1'b0; sck_en <= 1'b1; master_dout <= (send_over) ? master_dout_reg : master_dout; //master receiverd data; end FINISH: begin //send and load ok; sck_en <= 1'b0; cs <= 1'b1; data_cnt_en <= 1'b0; end default: begin cs <= 1'b1; sck_en <= 1'b0; data_cnt_en <= 1'b0; end endcase //case end end always @(posedge clk or negedge rst_n) begin if (~rst_n) begin data_cnt <= 0; end else begin data_cnt <= (data_cnt_en) ? (data_cnt + 1'b1) : 5'd0; //4 div * 8bit = 32 cnt; end end assign send_over = (data_cnt == DATA_CNT_MAX) ? 1'b1 : 1'b0; //rising edge miso; always @(posedge clk or negedge rst_n) begin if (~rst_n) begin master_dout_reg <= 0; end else begin master_dout_reg <= (sck_p) ? {master_dout_reg[6:0],miso} : master_dout_reg; end end //mosi; always @(posedge clk or negedge rst_n) begin if (~rst_n) begin mosi_cnt <= 0; end else begin if (sck_n) begin if (mosi_cnt == MOSI_CNT_MAX) begin mosi_cnt <= 0; end else begin mosi_cnt <= mosi_cnt + 1'b1; end end else begin mosi_cnt <= mosi_cnt; end end end always @(posedge clk or negedge rst_n) begin if (~rst_n) begin mosi <= 1'b0; end else begin mosi <= (sck_n) ? master_din_reg[MOSI_CNT_MAX-mosi_cnt] : mosi; end end endmodule仿真:综合资源使用:Fmax:
2026年01月06日
1 阅读
0 评论
0 点赞
2026-01-04
systemverilog interface
systemverilog interface普通的模块使用法:注意我们这里只实现了部分功能。。。。不是完全的读写模块。。。。module mem_core( input logic wen, input logic ren, output logic mrdy=1, input logic [7:0] addr, input logic [7:0] mem_din, //写进mem output logic [7:0] mem_dout, //从mem读出 output logic status, input logic clk);logic[7:0] mem [7:0]; //初始化一个meminitial $readmemh("d:/init.txt",mem); //d:/init.txt 文件中是 @01 10 。//或者 assign mem [2'h01]=8'b00000111; 注意这里一定要用 initial 或者assign等语句,不能直接=task reply_read(input logic [7:0] data, integer delay); #delay; @(negedge clk) mrdy=1'b0; mem_dout=data; //从图中可看出这两句话几乎同时执行。 @(negedge clk) mrdy=1'b1;endtaskalways@(negedge ren) reply_read(mem[addr],10);endmodulemodule cpu_core( output logic wen=1, output logic ren=1, input logic mrdy, output logic [7:0] addr=0, input logic [7:0] cpu_din, output logic [7:0] cpu_dout, output logic status=0, input logic clk);task read_memory(input logic [7:0] raddr, output logic [7:0] data); @(posedge clk); ren=1'b0; addr=raddr; @(negedge mrdy); @(posedge clk); data=cpu_din; ren=1'b1; endtaskinitial beginlogic[7:0] read_data; read_memory(2'h01, read_data); $display("Read Result", $time,read_data);endendmodulemodule top; logic mrdy,wen,ren; logic[7:0] addr,d1,d2; wor status; logic clk=0;mem_core mem(., .mem_din(d1), .mem_dout(d2)); //采用对同名的信号做默认连接 cpu_core cpu(.*, .cpu_din(d2), .cpu_dout(d1));initial for(int i=0;i<=255;i++) #1 clk=!clk;endmoduleSystemverilog interface另外,SystemVerilog引入一个重要的数据类型:interface。其主要作用有两个:一是简化模块之间的连接;二是实现类和模块之间的通信;随着复杂度的提高,模块间互联变得复杂,SV引入接口,代表一捆连线的结构,具有智能同步和连接功能的代码;接口(interface)为硬件模块的端口提供了一个标准化的封装方式。用interface来封装接口的信号和功能。interface的定义是独立于模块的,通过关键字interface和endinterface包起来。此外,interface里面还可以带时钟、断言、方法等定义。 一个interface 也可以有input,output或是inout端口。当interface例化时,只有当变量或是线网声明在一个interface的端口列表中才能通过名字或是位置来互连.一种新加的和interface有关系的构造体是Modport 。它提供了module的interface端口和在特定的module中控制task和function使用的方向性信息。这些端口的方向可以在module中可以看到。接口使用无信号的连接方式。Modport将接口中信号分组并指定方向。就像下图中的黑色矩形块里面一样,黑盒,我们从外面看并不关心Modport的定义,只需要考虑clk。Systemverilog interfaceinterface membus(input logic clk, output wor status); logic mrdy; logic wen; logic ren; logic [7:0] addr; logic [7:0] c2m_data; logic [7:0] m2c_data;task reply_read(input logic [7:0] data, integer delay); #delay; @(negedge clk) mrdy=1'b0; m2c_data=data; @(negedge clk) mrdy=1'b1;endtask//Task和function可以定义在interface中,从而允许构造更抽象级的模型task read_memory(input logic [7:0] raddr, output logic [7:0] data); @(posedge clk); ren=1'b0; addr=raddr; @(negedge mrdy); @(posedge clk); data=m2c_data; ren=1'b1; endtaskmodport master(output wen, ren, addr, c2m_data, input mrdy, m2c_data, status, read_memory);modport slave(input wen, ren, addr, c2m_data, output mrdy, m2c_data, status, reply_read);//控制task和function使用的方向性信息,以便在下面的module中使用endinterfacemodule mem_core(membus.slave mb); //modport只需在模块首部指明(或者在()中),在模块例化时不需要指明使用接口时在模块和程序块之外声明接口变量;//接口信号必须采用非阻塞值赋值来驱动。 logic[7:0] mem [7:0]; assign mem [2'h01]=8'b00000111; assign mb.status=0; always@(negedge mb.ren) mb.reply_read(mem[mb.addr],100); //module可使用interface端口endmodulemodule cpu_core(membus.master mb); assign mb.status=0; initial beginlogic[7:0] read_data; mb.read_memory(2'h01, read_data); $display("Read Result", $time,read_data);endendmodulemodule top; wor status; logic clk=0; membus mb(clk,status); mem_core mem(.mb(mb.slave)); cpu_core cpu(.mb(mb.master));initial for(int i=0;i<=255;i++) #1 clk=!clk;endmoduleSystem verilog把测试平台的代码放在一个程序块中,包含代码和变量,我总结了几步使用interface的方法1、 首先定义一个interface interface arb_if(input bit clk); logic [1:0] grant, request; logic reset; clocking cb @(posedge clk); //在其中定义一个时钟块。供下面的测试program使用。测试program中所有使用到的信号都应该定义在其中 output request; //注意这里的方向是测试program中所需要的方向,一般跟DUT 中的相反 input grant; endclockingmodport TEST (clocking cb, // 使用modport,将信号分组 output reset); modport DUT (input request, reset, clk, output grant); modport MONITOR (input request, grant, reset, clk);endinterface2、定义一个基于interface参数的设计模块modulemodule arb (arb_if.DUT arbif); //该interface参数要实例化 reg last_winner; reg winner; reg [1:0] next_grant; reg [1:0] state, nxState; always @(posedge arbif.clk or posedge arbif.reset) begin 。。。 endendmodule 3、定义一个基于interface参数的测试程序program program automatic test (arb_if.TEST arbif); //该interface参数也要实例化task reset_test();begin$display("Task reset_test: asserting and checking reset"); arbif.reset <= 0; #100 arbif.reset <= 1; //测试program中所有使用到的信号都应该调用在interface中的时钟块里定义的信号 arbif.cb.request <= 0; repeat (2) @arbif.cb; arbif.reset <= 0; @arbif.cb; //测试program中是这样等待时钟边沿的。 a0: assert (arbif.cb.grant == 2'b00); 。。。 end endtask task request_grant_test();begin 。。。 end endtask //注意program中不允许使用always块。 initial begin repeat (10) @arbif.cb; reset_test(); request_grant_test(); repeat (10) @arbif.cb; $finish; endendprogram4、‘最后使用一个顶层模块将它们组合起来module top; bit clk; always #5 clk = !clk; arb_if arbif(clk); //实例化一个interface arb a1 (arbif); //实例化一个module,参数调用上面实例化的interface test t1(arbif); //实例化一个测试program,参数调用上面实例化的interfaceendmodule当然也可以隐式端口连接,值使用.*即可。module top; bit clk; always #5 clk = !clk; arb_if arbif(.*); arb a1 (.*); test t1(.*); endmodule虚接口:虚接口是物理接口的句柄interface 和 module是一样的, 都是静态的变量, 也就是在程序开始时, 内存中就有了其实例.但是在class里使用virtual interface时之前有两部必须提前完成:l 定义是将接口作为一个类进行定义。l 实例化:在RTL级的顶层中对接口进行实例化。先定义一个接口。interface Rx_if (input logic clk);logic [7:0] data; logic soc, en, clav, rclk; clocking cb @(posedge clk); output data, soc, clav; input en; endclocking : cb modport DUT (output en, rclk, input data, soc, clav); modport TB (clocking cb);endinterface : Rx_if例如网络交换机中DUT 的每一个通道都有一个接口。,一个Driver类可能会连接到很多接口。我们可以在Driver类中使用一个虚接口作为参数。 class Driver;virtual Rx_if.TB Rx; //想一想,如果不是虚接口,而是一个普通接口,就像一个普通模块一样,是一个静态变量。比如我们在顶层模块例化了这个接口 Rx, 那么下面所有的 实例化的 drv[i]都是对这同一个接口 Rx进行操作,这显然不是我们想要的。如果定义了virtual,则每个实例独立。......endclass然后在测试program中 创建一组虚接口program automatic test(Rx_if.TB Rx[4], Tx_if.TB Tx[4], output logic rst); ........Driver drv[4]; //实例化了4个 Driver 对象,每个 Driver对象带有1个实例化的虚接口 .........initial beginvirtual Rx_if.TB vRx_t=Rx; //创建一组虚接口,由于这里定义了virtual,所以实例化的时候可以有Rx[]. for (int i=0; i<4; i++) begin drv[i] = new(...., vRx[i]); end rst <= 1; repeat (10) @Rx[0].cb; rst <= 0; for (int i=0; i<4; i++) begin drv[i].run(5, driver_done); //发送....... end..........endprogram : test最后在顶层:module top; logic clk, rst;Rx_if Rx[4] (clk); ,,,, atm_router a1 (Rx[0], Rx[1], Rx[2], Rx[3], Tx[0], Tx[1], Tx[2], Tx[3], clk, rst);test t1 (Rx, Tx, rst);initial beginclk = 0; forever #20 clk = !clk; end endmodule : top定义一个interface,且实例化多个后,如果没有定义virtual,则在任何一个实例中修改了某个信号值,在其他实例中都会受到影响。如果定义了virtual,则每个实例独立。如果该interface只有一个实例,可用可不用virtual,有多个实例,需要virtual。再举个例子:8位计数器`timescale 1ns/1nsinterface X_if (input logic clk);logic [7:0] din, dout; logic reset_l, load; clocking cb @(posedge clk); output din, load; input dout; endclocking always @cb //接口里面也可以带子程序,断言,initial,always块等代码。 $strobe("@ : %m: dout= , din= , load= , reset= ", $time, dout, din, load, reset_l); modport DUT (input clk, din, reset_l, load, output dout); modport TB (clocking cb, output reset_l);endinterface// Simple 8-bit counter with load and active-low reset`timescale 1ns/1nsmodule DUT(X_if.DUT xi); logic [7:0] count; assign xi.dout = count; //们想要输出的结果就是计数器always @(posedge xi.clk or negedge xi.reset_l)begin if (!xi.reset_l) count = 0; else if (xi.load) count = xi.din; else count++; end endmodule////////////////////////////////`timescale 1ns/1nsprogram automatic test();parameter NUM_XI = 2; // Number of interface instancestypedef virtual X_if.TB vXi_t; vXi_t vxi[NUM_XI]; //虚接口数组 class Driver; //在测试程序中定义类 vXi_t xi; int id; function new(vXi_t xi, int id); this.xi = xi; this.id = id; endfunction task reset; fork begin $display("@ : %m: Start reset [ ]", $time, id); // Reset the device xi.reset_l <= 1; xi.cb.load <= 0; xi.cb.din <= 0; @(xi.cb) xi.reset_l <= 0; @(xi.cb) xi.reset_l <= 1; $display("@ : %m: End reset [ ]", $time, id); end join_none endtask task load; fork begin $display("@ : %m: Start load [ ]", $time, id); xi.cb.load <= 1; xi.cb.din <= id + 10; xi.cb.load <= 0; repeat (5) @(xi.cb); $display("@ : %m: End load [ ]", $time, id); end join_none endtask endclass Driver driver[]; initial begin // Connect the local virtual interfaces to the top $display("Test.v: There are NUM_XI = interfaces", NUM_XI); if (NUM_XI <= 0) $finish; driver = new[NUM_XI]; //创建driver, 每个DUT 要对应一个driver vxi = top.xi; //XMR跨模块连接。这种是推荐做法,就不用带参数了program automatic test(X_if xi[NUM_XI]); 了。//注意这里其实是把top模块中生成的xi[]数组的句柄传过来的for (int i=0; i《NUM_XI; i++) begin driver[i] = new(vxi[i], i); driver[i].reset; end foreach (driver[i]) driver[i].load; repeat (10) @(vxi[0].cb); $display("@ : Test completed", $time); $finish; end endprogram////////////////////////////////////////////////////////`timescale 1ns/1nsparameter NUM_XI = 2; // Number of interface instancesmodule top; // Clock generator bit clk; initial forever #20 clk = !clk;X_if xi [NUM_XI] (clk); // Instantiate N Xi interfaces// Generate N DUT instances generate for (genvar i=0; i《NUM_XI; i++)begin : dut DUT d (xi[i]); endendgenerate// Instantiate the testbench, overriding the parameter with number of instances test tb();endmodule : top
2026年01月04日
2 阅读
0 评论
0 点赞
2025-12-31
emmc和ufs的区别_ufs和emmc使用差别
什么是eMMC和UFS? 日常选机大家往往关注64GB、128GB等存储空间,却很少像选笔记本关注SSD一样关注手机闪存规格。首先手机储存容量、固态硬盘(SSD)、U盘和SD卡等使用的都是一种叫做NAND的储存介质,NAND闪存是一种非易失性存储技术,即断电后仍能保存数据。它的发展目标就是降低每比特存储成本、提高存储容量。 无论是eMMC还是UFS都是在NAND存储芯片的基础上,再加上了控制芯片,接入标准接口,进行标准封装,形成一个高度集成的储存模块。 手机闪存的设计概念,就是为了简化手机内存储器的使用,将NAND Flash芯片和控制芯片设计成1颗MCP芯片,手机客户只需要采购芯片,不需要处理其它繁琐的NAND Flash兼容性和管理问题。 eMMC和UFS都是面向移动端闪存的标准,其中eMMC全称为“embedded Multi Media Card”,即嵌入式的多媒体存储卡,eMMC从eMMC4.3一路发展到4.4、4.5直到现在的5.0、5.1,传输速度也从50MB/s一路狂飙到200MB/s直到现在eMMC5.1的600MB/s,不过实际使用中读取速率都会低于低于理论值,比如搭载eMMC5.1的手机一般读取速度在250MB/s。 不过对于eMMC来说600MB/s已经是极限,通过并行接口提升接口速率越发困难,接口串行提供了更高速率的可能,这就是后来的UFS标准。UFS使用高速串行接口替代了并行接口,改用了全双工方式,收发数据可以同时进行。 相比eMMC,JEDEC发布了全新的USF 2.0标准在接口速率上提升不少,全新的USF 2.0有两个版本,其中UFS 2.0 HS-G2的理论带宽为5.8Gbps,大约740MB/s,更快速的UFS 2.1 HS-G3的理论带宽更是达到了11.6Gbps,约1.5GB/s。 emmc和ufs的区别_ufs和emmc使用差别 上面这张图很好的反映出了eMMC和UFS两种规格之间的速率差异,而关于手机闪存带宽的提升并没有停止,根据路线图,明年我们有望在手机上UFS3.0的身影,其带宽峰值将超过2.4GB/s。 截至目前,大多数手机会采用eMMC存储接口,但是我们看到eMMC本身存在速率瓶颈,比如不能同时读写,也就是我们在连接电脑导图片的时候,并没有办法同时往手机拷贝数据,另外在传一些大体积的数据时,往往带宽的限制会很慢。 emmc和ufs的区别_ufs和emmc使用差别 而UFS2.X接口无论在性能和速率上都更胜一筹,并真正在改善移动设备的操作体验。如果用一个词来UFS接口带来改善,那就是更快的响应能力。 最新的Android系统已经根据UFS2.0的多线程读取能力进行了优化,一个最直观的变化是我们的手机在读取文件上花费的时间会更少,另外打开应用程序的时间也变短,一旦软件开发人员优化各自的App,充分利用UFS,这种移动体验就会持续得到改善。总而言之UFS2.0的存在让我们的手机看起来反应更快。 实测体验ufs和emmc哪个好? 前面我们提到UFS比eMMC可以提升文件读写速度,应用到实际使用中主要表现为手机解压大型游戏和加载大型游戏的时间会变短。除了这些,使用会更快的UFS接口的手机要比eMMC在实际表现的差异还是比较明显的,下面这段视频可以很清晰的表现出两种规格的差异。 多任务执行响应速度更快 拥有UFS2.0接口手机,LVDS(低压差分信号)有专门串行接口,读写操作同时进行; CQ(命令)队列动态调配任务,无需等待上一进程结束。相反eMMC接口的手机读写必须分开执行,指令也是打包的,在速度上就已经是略逊一筹,在执行多任务时eMMC自然要慢一步。 低延迟,UFS响应速度快3倍 在读取大型游戏以及大体积文件时,UFS2.0所需时间更短,载入一款游戏所需要的时间为eMMC5.0的1/3,相应在体验游戏时UFS2.0的手机延迟更低,画面更流畅。 连续快拍的照片写入更快 UFS和eMMC体验上的区别还在连续拍照上,连续拍照时UFS让照片写入更快,从下面的对比可以看出,不同接口标准的手机在连续拍照时,因为写入速度的限制eMMC拍摄时从按下快门到存储一张照片花费的时间更长,而UFS缩短了存储时间从而可以让我们可以在同一时间内抓拍到更多照片。 相册图片缩略图载入时间更短 这一点相信大家深有体会,很多人的手机装满了几百张甚至上千张照片,当你打开相册的图片缩略图很明显的看到加载的过程,这就是手机在读取闪存中的照片时更不上刷新的速度造成的。优秀的手机屏幕时画面会随着滑动流畅载入,而差一点的手机就会明显体会到加载时的卡顿。 UFS缩略图载入速度更快 速度快了 功耗也更低 UFS接口在提升了速率之后,也就意味着在相同的任务面前它所花费的时间更短,更高的效率意味着更低的功耗。在同时工作的时候UFS的功耗要比eMMC低出10%,日常工作中大约能省35%的功耗,这对于目前的智能手机续航无疑是更好的选择。 总结:移动设备闪存使用UFS接口标准无论性能、功耗各方面都要优于eMMC,协同处理器让我们的手机在应对更多场景时不会卡顿,购买移动设备时选择UFS闪存的产品在未来5G数据狂潮的年代,显然更有价值。
2025年12月31日
1 阅读
0 评论
0 点赞
2025-12-31
Vscode自动生成verilog例化
前言veirlog模块例化的时候,辣么多的信号端子,手动例化又慢又容易出错,葵花妈妈开课啦,孩子手残老犯错怎么办?当然是脚本一劳永逸,妈妈再也不担心手残党。流程(1)在vscode中安装如下插件。(2)在电脑中安装python3以上的环境。下载地址:https://www.python.org/downloads/release/python-373/安装记得一定要勾选添加路径,记得管理员安装。重启你的电脑。在cmd窗口输入python即可验证是否安装成功!(3)安装chardet。为确保插件可用,这个需要安装。参考链接:https://blog.csdn.net/sinat_28631741/article/details/80483064方式一 源码按照:第一步:下载压缩文件,例如: 'chardet-3.0.4.tar.gz'; 第二步:解压文件到python安装位置下的‘site-packages’目录下,例如:‘D:\python2.7\Lib\site-packages’; 第三步:打开终端命令窗口,进入解压的‘chardet’目录下,执行命令:python setup.py install (4)修改插件的原始py文件,觉得开发者的py有瑕疵,让帅气的同事重新整了个,把以下代码替换进原始py文件即可。在打开v文件的vscode下按ctrl+p,输入instance可出现下述界面。替换此py文件的代码即可。 #! /usr/bin/env python ''' vTbgenerator.py -- generate verilog module Testbench generated bench file like this: fifo_sc #( .DATA_WIDTH ( 8 ), .ADDR_WIDTH ( 8 ) ) u_fifo_sc ( .CLK ( CLK ), .RST_N ( RST_N ), .RD_EN ( RD_EN ), .WR_EN ( WR_EN ), .DIN ( DIN [DATA_WIDTH-1 :0] ), .DOUT ( DOUT [DATA_WIDTH-1 :0] ), .EMPTY ( EMPTY ), .FULL ( FULL ) ); Usage: python vTbgenerator.py ModuleFileName.v ''' import random import re import sys from queue import Queue import chardet def delComment(Text): """ removed comment """ single_line_comment = re.compile(r"//(.*)$", re.MULTILINE) multi_line_comment = re.compile(r"/\*(.*?)\*/", re.DOTALL) Text = multi_line_comment.sub('\n', Text) Text = single_line_comment.sub('\n', Text) return Text def delBlock(Text): """ removed task and function block """ Text = re.sub(r'\Wtask\W[\W\w]*?\Wendtask\W', '\n', Text) Text = re.sub(r'\Wfunction\W[\W\w]*?\Wendfunction\W', '\n', Text) return Text def findName(inText): """ find module name and port list""" p = re.search(r'([a-zA-Z_][a-zA-Z_0-9]*)\s*', inText) mo_Name = p.group(0).strip() return mo_Name def paraDeclare(inText, portArr): """ find parameter declare """ pat = r'\s' + portArr + r'\s[\w\W]*?[;,)]' ParaList = re.findall(pat, inText) return ParaList def portDeclare(inText, portArr): """find port declare, Syntax: input [ net_type ] [ signed ] [ range ] list_of_port_identifiers return list as : (port, [range]) """ port_definition = re.compile( r'\b' + portArr + r''' (\s+(wire|reg)\s+)* (\s*signed\s+)* (\s*\[.*?:.*?\]\s*)* (?P<port_list>.*?) (?= \binput\b | \boutput\b | \binout\b | ; | \) ) ''', re.VERBOSE | re.MULTILINE | re.DOTALL ) pList = port_definition.findall(inText) t = [] for ls in pList: if len(ls) >= 2: t = t + portDic(ls[-2:]) return t def portDic(port): """delet as : input a =c &d; return list as : (port, [range]) """ pRe = re.compile(r'(.*?)\s*=.*', re.DOTALL) pRange = port[0] pList = port[1].split(',') pList = [i.strip() for i in pList if i.strip() != ''] pList = [(pRe.sub(r'\1', p), pRange.strip()) for p in pList] return pList def formatPort(AllPortList, isPortRange=1): PortList = AllPortList str = '' if PortList != []: l1 = max([len(i[0]) for i in PortList])+2 l3 = max(18, l1) strList = [] str = ',\n'.join([' ' * 4 + '.' + i[0].ljust(l3) + '(' + (i[0]) + ')' for i in AllPortList]) strList = strList + [str] str = ',\n\n'.join(strList) return str def formatDeclare(PortList, portArr, initial=""): str = '' if PortList != []: str = '\n'.join([portArr.ljust(4) + ' '+(i[1]+min(len(i[1]), 1)*' ' + i[0]) + ';' for i in PortList]) return str def formatPara(ParaList): paraDec = '' paraDef = '' if ParaList != []: s = '\n'.join(ParaList) pat = r'([a-zA-Z_][a-zA-Z_0-9]*)\s*=\s*([\w\W]*?)\s*[;,)]' p = re.findall(pat, s) l1 = max([len(i[0]) for i in p]) l2 = max([len(i[1]) for i in p]) paraDec = '\n'.join(['parameter %s = %s;' % (i[0].ljust(l1 + 1), i[1].ljust(l2)) for i in p]) paraDef = '#(\n' + ',\n'.join([' .' + i[0].ljust(l1 + 1) + '( ' + i[1].ljust(l2)+' )' for i in p]) + ')\n' return paraDec, paraDef def portT(inText, ioPadAttr): x = {} count_list = [] order_list = [] for i in ioPadAttr: p = port_index_list(inText, i) for j in p: count_list.append(j) x[j] = i count_list = quick_sort(count_list, 0, len(count_list)-1) for c in count_list: order_list.append(x.get(c)) return order_list def quick_sort(myList, start, end): if start < end: i, j = start, end base = myList[i] while i < j: while (i < j) and (myList[j] >= base): j = j - 1 myList[i] = myList[j] while (i < j) and (myList[i] <= base): i = i + 1 myList[j] = myList[i] myList[i] = base quick_sort(myList, start, i - 1) quick_sort(myList, j + 1, end) return myList def formatPort_order(padAttr, orderList): for p in padAttr: q = Queue() for i in padAttr.get(p): q.put(i) padAttr[p] = q AllPortList = [] for o in orderList: AllPortList.append(padAttr.get(o).get()) return AllPortList def port_index_list(intext, text): l = [] t = intext index = t.find(text) while index > -1: t = t.replace(text, random_str(len(text)), 1) l.append(index) index = t.find(text) return l def random_str(size): s = '' for i in range(size): s += str(random.randint(0, 9)) return s def getPortMap(AllPortList, ioPadAttr): if len(AllPortList) != len(ioPadAttr): return p_map = {} for i in range(len(AllPortList)): p_map[ioPadAttr[i]] = AllPortList[i] return p_map def writeTestBench(input_file): """ write testbench to file """ with open(input_file, 'rb') as f: f_info = chardet.detect(f.read()) f_encoding = f_info['encoding'] with open(input_file, encoding=f_encoding) as inFile: inText = inFile.read() # removed comment,task,function inText = delComment(inText) inText = delBlock(inText) # moduel ... endmodule # moPos_begin = re.search(r'(\b|^)module\b', inText).end() moPos_end = re.search(r'\bendmodule\b', inText).start() inText = inText[moPos_begin:moPos_end] name = findName(inText) paraList = paraDeclare(inText, 'parameter') paraDec, paraDef = formatPara(paraList) ioPadAttr = ['input', 'output', 'inout'] orlder = portT(inText, ioPadAttr) input = portDeclare(inText, ioPadAttr[0]) output = portDeclare(inText, ioPadAttr[1]) inout = portDeclare(inText, ioPadAttr[2]) portList = formatPort(formatPort_order( getPortMap([input, output, inout], ioPadAttr), orlder)) input = formatDeclare(input, 'reg') output = formatDeclare(output, 'wire') inout = formatDeclare(inout, 'wire') # write Instance # module_parameter_port_list if(paraDec != ''): print("// %s Parameters\n%s\n" % (name, paraDec)) # list_of_port_declarations #print("// %s Inputs\n%s\n" % (name, input)) #print("// %s Outputs\n%s\n" % (name, output)) #if(inout != ''): # print("// %s Bidirs\n%s\n" % (name, inout)) print("\n") # UUT print("%s %s inst_%s (\n%s\n);" % (name, paraDef, name, portList)) if __name__ == '__main__': writeTestBench(sys.argv[1]) (5)享受一下吧。比如我们有如下代码:crtl+p,输入instance,按回车即可。 复制粘贴大发好。以上。转载于:https://www.cnblogs.com/kingstacker/p/9944259.html
2025年12月31日
3 阅读
0 评论
0 点赞
1
2
3
...
8