Verilog
top.v
module top (
input clk,
input rst,
input pause,
output reg [3:0] num0, // 个位
output reg [3:0] num1, // 十位
output reg [6:0] seg0, // 个位 数码管
output reg [6:0] seg1 // 十位 数码管
);
reg [31:0] count;
always @(posedge clk) begin
if(rst) begin count <= 0; num0 <= 4'd0; num1 <= 4'd0;end // 初始化和重置
else if(!pause)begin
count <= (count >= 500000? 32'b0 : count + 1); // 改变时钟的周期
if(count == 32'd0) begin
if(num0 == 4'd9)begin // 个位为9进1
if(num1 == 4'd9)begin num0 <= 4'd0;num1 <= 4'd0; end // 99时重置
else begin
num0 <= 4'd0;
num1 <= num1 + 4'd1;
end
end
else begin num0 <= num0 + 4'd1;end
end
end
end
seg my_seg(
.clk(clk),
.rst(rst),
.num0(num0),
.num1(num1),
.seg0(seg0),
.seg1(seg1)
);
endmodule
别问,问就是疯狂if else 😦。
seg.v
module seg (
input clk,
input rst,
input [3:0] num0,
input [3:0] num1,
output reg [6:0] seg0,
output reg [6:0] seg1
);
wire [6:0] segs [9:0];
assign segs[0] = 7'b0000001; // 0为亮 1为熄
assign segs[1] = 7'b1001111;
assign segs[2] = 7'b0010010;
assign segs[3] = 7'b0000110;
assign segs[4] = 7'b1001100;
assign segs[5] = 7'b0100100;
assign segs[6] = 7'b0100000;
assign segs[7] = 7'b0001111;
assign segs[8] = 7'b0000000;
assign segs[9] = 7'b0001100;
always@(posedge clk)begin
case (num0)
4'd0:seg0 = segs[0];
4'd1:seg0 = segs[1];
4'd2:seg0 = segs[2];
4'd3:seg0 = segs[3];
4'd4:seg0 = segs[4];
4'd5:seg0 = segs[5];
4'd6:seg0 = segs[6];
4'd7:seg0 = segs[7];
4'd8:seg0 = segs[8];
4'd9:seg0 = segs[9];
default: seg0 = segs[0];
endcase
case (num1)
4'd0:seg1 = segs[0];
4'd1:seg1 = segs[1];
4'd2:seg1 = segs[2];
4'd3:seg1 = segs[3];
4'd4:seg1 = segs[4];
4'd5:seg1 = segs[5];
4'd6:seg1 = segs[6];
4'd7:seg1 = segs[7];
4'd8:seg1 = segs[8];
4'd9:seg1 = segs[9];
default: seg1 = segs[0];
endcase
end
endmodule
sim_main.cpp
cpp文件的说明见文章
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<nvboard.h>
#include"Vtop.h"
#include"verilated.h"
#include"verilated_vcd_c.h"
void nvboard_bind_all_pins(Vtop* top);
int main(int argc, char** argv) {
VerilatedContext* contextp = new VerilatedContext;
contextp->traceEverOn(true);
contextp->commandArgs(argc, argv);
Vtop* top = new Vtop{contextp};
nvboard_bind_all_pins(top);
nvboard_init();
VerilatedVcdC* m_trace = new VerilatedVcdC;
top->trace(m_trace, 99);
m_trace->open("wave.vcd");
top->clk = 0;
int n = 3;
top->rst = 1;
m_trace->dump(contextp->time());
//----原reset函数---- 进行信号初始化
while (n -- > 0)
{
contextp->timeInc(1); // 推进仿真时间
top->clk = !top->clk;
top->eval(); // 模型更新
m_trace->dump(contextp->time()); // 记录波形
}
//----原reset函数----
top->rst = 0;
top->pause = 0;
while (!contextp->gotFinish()) {
nvboard_update();
contextp->timeInc(1);
top->clk = !top->clk;
top->eval();
m_trace->dump(contextp->time());
}
m_trace->close();
delete top;
delete contextp;
return 0;
}
引脚绑定
top=top
rst SW0
pause SW1
seg0 (SEG0A, SEG0B, SEG0C, SEG0D, SEG0E, SEG0F, SEG0G)
seg1 (SEG1A, SEG1B, SEG1C, SEG1D, SEG1E, SEG1F, SEG1G)
sw0用于清零重置,sw1用于暂停 。
NVBoard用于查看00-99时,建议关闭波形记录,不然磁盘会爆炸的。
拓展的电子时钟我当初没做,等我更到NPC再回来写吧。