目录
-
- 一、MCDF功能描述[^1]
-
- MCDF结构
- slave端口时序
- formater端口时序
- 寄存器时序
- 二、代码分析
-
- 时间单位
- 信号
- 例化
- 产生时钟
- 产生复位
- 发送激励
- 三、Questasim的Makefile[^2]
- 四、波形
一、MCDF功能描述1
MCDF结构
多通道的数据经fifo流入arbiter,arbiter对通道进行选择,将数据打包发送出去
slave端口时序
valid为高表示有发送数据的请求,同时发送数据,ready为高表示数据写书成功
formater端口时序
chid数据通道,length数据长度(持续到数据结束,多两个cycle),req为高(持续两个cycle)表示有发送数据请求,三个信号同时发送;一个cycle后,grant(持续两个cycle)同意发送数据;一个cycle后开始发送数据。
数据准备好,一个cycle后,进入fifo,发送数据发送请求;
一个cycle后,formater说好的我收到了,你开始发数据吧;
一个cycle后,这边知道了,我马上发
寄存器时序
- 写地址,写命令和写数据在同一个时钟上升沿发送
- 读地址,读命令在时钟上升沿发送,读出数据在下一个时钟上升沿得到
- IDLE,为什么要等一拍,不懂
二、代码分析
时间单位
信号
reg为寄存器变量,用于过程赋值
wire为线,用于连续赋值
输出数据用reg,输入数据用wire
reg clk;
reg rstn;
reg [31:0] ch0_data;//输出数据到DUT
reg ch0_valid;//输出有效信号到DUT
wire ch0_ready;//DUT输入ready
wire [ 5:0] ch0_margin;//DUT输入fifo余量
reg [31:0] ch1_data;
reg ch1_valid;
wire ch1_ready;
wire [ 5:0] ch1_margin;
reg [31:0] ch2_data;
reg ch2_valid;
wire ch2_ready;
wire [ 5:0] ch2_margin;
wire [31:0] mcdt_data;//DUT输出当前输出的数据
wire mcdt_val; //DUT输出当前输出的有效信号
wire [ 1:0] mcdt_id; //DUT输出当前输出的通道号
例化
将tb的信号与dut的端口相连
mcdt dut(
.clk_i(clk)
,.rstn_i(rstn)
,.ch0_data_i(ch0_data)
,.ch0_valid_i(ch0_valid)
,.ch0_ready_o(ch0_ready)
,.ch0_margin_o(ch0_margin)
,.ch1_data_i(ch1_data)
,.ch1_valid_i(ch1_valid)
,.ch1_ready_o(ch1_ready)
,.ch1_margin_o(ch1_margin)
,.ch2_data_i(ch2_data)
,.ch2_valid_i(ch2_valid)
,.ch2_ready_o(ch2_ready)
,.ch2_margin_o(ch2_margin)
,.mcdt_data_o(mcdt_data)
,.mcdt_val_o(mcdt_val)
,.mcdt_id_o(mcdt_id)
);
产生时钟
周期为10,5s翻转一次
initial begin
clk <= 0;
forever begin
#5 clk <= !clk;
end
end
产生复位
仿真开始,等待10ns复位
再等待10个上升沿,10ns+5ns+90ns
initial begin
#10 rstn <= 0;
repeat(10) @(posedge clk);
rstn <= 1;
end
发送激励
等待复位信号105ns:clk↑,rstn↑再等clk↑为下一个时钟
等待五次上升沿:105+50=155ns
三个通道依次发送数据:等待一个clk再发送数据:165ns
initial begin
@(posedge rstn);
repeat(5) @(posedge clk);
// channel 0 test
chnl_write(0, 'h00C0_0000);
chnl_write(0, 'h00C0_0001);
// channel 1 test
chnl_write(1, 'h00C1_0000);
chnl_write(1, 'h00C1_0001);
// channel 2 test
chnl_write(2, 'h00C2_0000);
chnl_write(2, 'h00C2_0001);
end
发送有效数据间隔一个时钟再次发送有效数据
等待一个clk发送数据
// channel write task
task chnl_write(input reg[1:0] id, input reg[31:0] data);
case(id)
0: begin
@(posedge clk);//模仿时序逻辑,等到上升沿后发送数据
ch0_valid <= 1;
ch0_data <= data;
@(posedge clk);//模仿时序逻辑,等到上升沿后发送无效
ch0_valid <= 0;
ch0_data <= 0;
end
1: begin
@(posedge clk);
ch1_valid <= 1;
ch1_data <= data;
@(posedge clk);
ch1_valid <= 0;
ch1_data <= 0;
end
2: begin
@(posedge clk);
ch2_valid <= 1;
ch2_data <= data;
@(posedge clk);
ch2_valid <= 0;
ch2_data <= 0;
end
default: $error("channel id %0d is invalid", id);
endcase
endtask
三、Questasim的Makefile2
- 用户变量:top和要编译的文件,需要修改
环境变量:
-vopt: simulate full optimization;
-novopt: simulate without optimization
-voptargs=+acc: simulate
v10.7用-voptargs=+acc
v10.6用-novopt,不然会默认优化一些没有用到的参数,就无法查看这些参数
其它
-c: command模式,不启动图形界面
-do “xxx”: 执行xxx命令
命令行输入
vsim & 启动questa
restart 重新开始仿真
f 查看全部波形
vlog 编译
run -all
log -r /* 保存信号,-r递归,/*层层循环保存所有信号
#############################
# User variables
#############################
TB = tb1
DFILES = {arbiter.v,slave_fifo.v,mcdt.v}
VFILES = $(TB).v
#############################
# Environment variables
#############################
VLAB = vlib work #创建名为work的lib
VCOMP = vlog -l com.log #vlog编译;-l com.log将日志存放到com.log中
VSTART = vsim -l sim.log #vsim启动questa
VSIMULATE = -voptargs=+acc #simulate
VADDWAVE = add wave -position insertpoint sim:/$(TB)/*#添加top文件的波形
VSAVE = log -r /*#生成波形文件
RUN = run 1us #运行1ns
VQUIT = quit -f #退出
all: create_lib compile simulate #make要执行的顺序
create_lib:
$(VLAB)
compile:
$(VCOMP) $(DFILES) $(VFILES)
simulate:
#$(VSTART) -c $(VSIMULATE) work.$(TB) -do "$(SAVE) $(RUN);$(VQUIT)"
$(VSTART) $(VSIMULATE) work.$(TB) -do "$(VADDWAVE);$(VSAVE);$(RUN)"
clean:
rm -rf work mti_lib transcript modelsim.ini *.log vsim.wlf
四、波形
- https://recclay.blog.csdn.net/article/details/118121495 ↩︎
- https://blog.csdn.net/qq_39794062/article/details/113402057 ↩︎