mirror of
https://github.com/olofk/serv.git
synced 2025-06-28 09:13:54 -04:00
boilerplate for external interrupts
Signed-off-by: Alfred Persson Forsberg <cat@catcream.org>
This commit is contained in:
parent
a72c1e8737
commit
41c0d44e5f
34 changed files with 1337 additions and 44 deletions
110
bench/decoder_sim.v
Normal file
110
bench/decoder_sim.v
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
`default_nettype none
|
||||||
|
module decoder_sim
|
||||||
|
(input wire wb_clk,
|
||||||
|
input wire [31:2] wb_rdt,
|
||||||
|
input wire wb_en,
|
||||||
|
output wire ebreak,
|
||||||
|
output wire jal_or_jalr,
|
||||||
|
output wire mret,
|
||||||
|
output wire wfi,
|
||||||
|
output wire sh_right,
|
||||||
|
output wire bne_or_bge,
|
||||||
|
output wire cond_branch,
|
||||||
|
output wire e_op,
|
||||||
|
output wire branch_op,
|
||||||
|
output wire shift_op,
|
||||||
|
output wire slt_or_branch,
|
||||||
|
output wire rd_op,
|
||||||
|
output wire two_stage_op,
|
||||||
|
output wire dbus_en,
|
||||||
|
output wire mdu_op,
|
||||||
|
output wire [2:0] ext_funct3,
|
||||||
|
output wire bufreg_rs1_en,
|
||||||
|
output wire bufreg_imm_en,
|
||||||
|
output wire bufreg_clr_lsb,
|
||||||
|
output wire bufreg_sh_signed,
|
||||||
|
output wire ctrl_utype,
|
||||||
|
output wire ctrl_pc_rel,
|
||||||
|
output wire alu_sub,
|
||||||
|
output wire [1:0] alu_bool_op,
|
||||||
|
output wire alu_cmp_eq,
|
||||||
|
output wire alu_cmp_sig,
|
||||||
|
output wire [2:0] alu_rd_sel,
|
||||||
|
output wire mem_signed,
|
||||||
|
output wire mem_word,
|
||||||
|
output wire mem_half,
|
||||||
|
output wire mem_cmd,
|
||||||
|
output wire csr_en,
|
||||||
|
output wire [1:0] csr_addr,
|
||||||
|
output wire csr_mstatus_en,
|
||||||
|
output wire csr_mie_en,
|
||||||
|
output wire csr_mcause_en,
|
||||||
|
output wire [1:0] csr_source,
|
||||||
|
output wire csr_d_sel,
|
||||||
|
output wire csr_imm_en,
|
||||||
|
output wire mtval_pc,
|
||||||
|
output wire [3:0] immdec_ctrl,
|
||||||
|
output wire [3:0] immdec_en,
|
||||||
|
output wire op_b_source,
|
||||||
|
output wire rd_mem_en,
|
||||||
|
output wire rd_csr_en,
|
||||||
|
output wire rd_alu_en
|
||||||
|
);
|
||||||
|
|
||||||
|
// Instantiate the DUT
|
||||||
|
serv_decode
|
||||||
|
#(.PRE_REGISTER (1),
|
||||||
|
.MDU (0))
|
||||||
|
dut (
|
||||||
|
.clk(wb_clk),
|
||||||
|
.i_wb_rdt(wb_rdt),
|
||||||
|
.i_wb_en(wb_en),
|
||||||
|
// Outputs
|
||||||
|
.o_sh_right(sh_right),
|
||||||
|
.o_bne_or_bge(bne_or_bge),
|
||||||
|
.o_cond_branch(cond_branch),
|
||||||
|
.o_e_op(e_op),
|
||||||
|
.o_ebreak(ebreak),
|
||||||
|
.o_wfi(wfi),
|
||||||
|
.o_branch_op(branch_op),
|
||||||
|
.o_shift_op(shift_op),
|
||||||
|
.o_rd_op(rd_op),
|
||||||
|
.o_two_stage_op(two_stage_op),
|
||||||
|
.o_dbus_en(dbus_en),
|
||||||
|
.o_mdu_op(mdu_op),
|
||||||
|
.o_ext_funct3(ext_funct3),
|
||||||
|
.o_bufreg_rs1_en(bufreg_rs1_en),
|
||||||
|
.o_bufreg_imm_en(bufreg_imm_en),
|
||||||
|
.o_bufreg_clr_lsb(bufreg_clr_lsb),
|
||||||
|
.o_bufreg_sh_signed(bufreg_sh_signed),
|
||||||
|
.o_ctrl_jal_or_jalr(jal_or_jalr),
|
||||||
|
.o_ctrl_utype(ctrl_utype),
|
||||||
|
.o_ctrl_pc_rel(ctrl_pc_rel),
|
||||||
|
.o_ctrl_mret(mret),
|
||||||
|
.o_alu_sub(alu_sub),
|
||||||
|
.o_alu_bool_op(alu_bool_op),
|
||||||
|
.o_alu_cmp_eq(alu_cmp_eq),
|
||||||
|
.o_alu_cmp_sig(alu_cmp_sig),
|
||||||
|
.o_alu_rd_sel(alu_rd_sel),
|
||||||
|
.o_mem_signed(mem_signed),
|
||||||
|
.o_mem_word(mem_word),
|
||||||
|
.o_mem_half(mem_half),
|
||||||
|
.o_mem_cmd(mem_cmd),
|
||||||
|
.o_csr_en(csr_en),
|
||||||
|
.o_csr_addr(csr_addr),
|
||||||
|
.o_csr_mstatus_en(csr_mstatus_en),
|
||||||
|
.o_csr_mie_en(csr_mie_en),
|
||||||
|
.o_csr_mcause_en(csr_mcause_en),
|
||||||
|
.o_csr_source(csr_source),
|
||||||
|
.o_csr_d_sel(csr_d_sel),
|
||||||
|
.o_csr_imm_en(csr_imm_en),
|
||||||
|
.o_mtval_pc(mtval_pc),
|
||||||
|
.o_immdec_ctrl(immdec_ctrl),
|
||||||
|
.o_immdec_en(immdec_en),
|
||||||
|
.o_op_b_source(op_b_source),
|
||||||
|
.o_rd_mem_en(rd_mem_en),
|
||||||
|
.o_rd_csr_en(rd_csr_en),
|
||||||
|
.o_rd_alu_en(rd_alu_en)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
157
bench/decoder_tb.cpp
Normal file
157
bench/decoder_tb.cpp
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <csignal>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <memory>
|
||||||
|
#include <ctime>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "verilated_vcd_c.h"
|
||||||
|
#include "Vdecoder_sim.h"
|
||||||
|
|
||||||
|
void INThandler(int signal) {
|
||||||
|
std::cout << "\nCaught ctrl-c\n";
|
||||||
|
std::exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_instruction(Vdecoder_sim *top, const std::string& instr_name, uint32_t instr);
|
||||||
|
void cycle(Vdecoder_sim *top);
|
||||||
|
|
||||||
|
int main(int argc, char** argv, char** env) {
|
||||||
|
Verilated::commandArgs(argc, argv);
|
||||||
|
|
||||||
|
Vdecoder_sim *top = new Vdecoder_sim;
|
||||||
|
std::signal(SIGINT, INThandler);
|
||||||
|
|
||||||
|
top->wb_clk = 0;
|
||||||
|
top->wb_rdt = 0;
|
||||||
|
top->wb_en = 0;
|
||||||
|
|
||||||
|
std::cout << "Testing decoder\n";
|
||||||
|
test_instruction(top, "jalr", 0x0000006F);
|
||||||
|
test_instruction(top, "mret", 0x30200073);
|
||||||
|
test_instruction(top, "ebreak", 0x00100073);
|
||||||
|
test_instruction(top, "wfi", 0x10500073);
|
||||||
|
test_instruction(top, "add", 0x00000033);
|
||||||
|
test_instruction(top, "addi", 0x00000013);
|
||||||
|
test_instruction(top, "sub", 0x40000033);
|
||||||
|
test_instruction(top, "and", 0x00007033);
|
||||||
|
test_instruction(top, "andi", 0x00007013);
|
||||||
|
test_instruction(top, "or", 0x00006033);
|
||||||
|
test_instruction(top, "ori", 0x00006013);
|
||||||
|
test_instruction(top, "xor", 0x00004033);
|
||||||
|
test_instruction(top, "xori", 0x00004013);
|
||||||
|
test_instruction(top, "sll", 0x00001033);
|
||||||
|
test_instruction(top, "slli", 0x00001013);
|
||||||
|
test_instruction(top, "srl", 0x00005033);
|
||||||
|
test_instruction(top, "srli", 0x00005013);
|
||||||
|
test_instruction(top, "sra", 0x40005033);
|
||||||
|
test_instruction(top, "srai", 0x40005013);
|
||||||
|
test_instruction(top, "lui", 0x00000037);
|
||||||
|
test_instruction(top, "auipc", 0x00000017);
|
||||||
|
test_instruction(top, "lw", 0x00002003);
|
||||||
|
test_instruction(top, "lh", 0x00001003);
|
||||||
|
test_instruction(top, "lhu", 0x00005003);
|
||||||
|
test_instruction(top, "lb", 0x00000003);
|
||||||
|
test_instruction(top, "lbu", 0x00004003);
|
||||||
|
test_instruction(top, "sw", 0x00002023);
|
||||||
|
test_instruction(top, "sh", 0x00001023);
|
||||||
|
test_instruction(top, "sb", 0x00000023);
|
||||||
|
test_instruction(top, "jal", 0x0000006F);
|
||||||
|
test_instruction(top, "jalr", 0x00000067);
|
||||||
|
test_instruction(top, "beq", 0x00000063);
|
||||||
|
test_instruction(top, "bne", 0x00001063);
|
||||||
|
test_instruction(top, "blt", 0x00004063);
|
||||||
|
test_instruction(top, "bge", 0x00005063);
|
||||||
|
test_instruction(top, "bltu", 0x00006063);
|
||||||
|
test_instruction(top, "bgeu", 0x00007063);
|
||||||
|
test_instruction(top, "slt", 0x00002033);
|
||||||
|
test_instruction(top, "slti", 0x00002013);
|
||||||
|
test_instruction(top, "sltu", 0x00003033);
|
||||||
|
test_instruction(top, "sltiu", 0x00003013);
|
||||||
|
test_instruction(top, "ecall", 0x00000073);
|
||||||
|
test_instruction(top, "ebreak", 0x00100073);
|
||||||
|
test_instruction(top, "fence", 0x0000000F);
|
||||||
|
test_instruction(top, "fence.i", 0x0000100F);
|
||||||
|
|
||||||
|
test_instruction(top, "csrrw", 0x00001073);
|
||||||
|
test_instruction(top, "csrrs", 0x00002073);
|
||||||
|
test_instruction(top, "csrrc", 0x00003073);
|
||||||
|
test_instruction(top, "csrrwi", 0x00005073);
|
||||||
|
test_instruction(top, "csrrsi", 0x00006073);
|
||||||
|
test_instruction(top, "csrrci", 0x00007073);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cycle(Vdecoder_sim *top) {
|
||||||
|
top->eval();
|
||||||
|
top->wb_clk = 0;
|
||||||
|
top->eval();
|
||||||
|
top->wb_clk = 1;
|
||||||
|
top->eval();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_instruction(Vdecoder_sim *top, const std::string& instr_name, uint32_t instr) {
|
||||||
|
std::ofstream outfile(instr_name + ".txt");
|
||||||
|
|
||||||
|
std::cout << "Testing " << instr_name << "\n";
|
||||||
|
outfile << "Testing " << instr_name << "\n";
|
||||||
|
|
||||||
|
top->wb_rdt = instr >> 2;
|
||||||
|
top->wb_en = 1;
|
||||||
|
cycle(top);
|
||||||
|
|
||||||
|
outfile << "jal_or_jalr: " << std::to_string(top->jal_or_jalr) << std::endl;
|
||||||
|
outfile << "ebreak: " << std::to_string(top->ebreak) << std::endl;
|
||||||
|
outfile << "mret: " << std::to_string(top->mret) << std::endl;
|
||||||
|
outfile << "wfi: " << std::to_string(top->wfi) << std::endl;
|
||||||
|
outfile << "sh_right: " << std::to_string(top->sh_right) << std::endl;
|
||||||
|
outfile << "bne_or_bge: " << std::to_string(top->bne_or_bge) << std::endl;
|
||||||
|
outfile << "cond_branch: " << std::to_string(top->cond_branch) << std::endl;
|
||||||
|
outfile << "e_op: " << std::to_string(top->e_op) << std::endl;
|
||||||
|
outfile << "branch_op: " << std::to_string(top->branch_op) << std::endl;
|
||||||
|
outfile << "shift_op: " << std::to_string(top->shift_op) << std::endl;
|
||||||
|
outfile << "slt_or_branch: " << std::to_string(top->slt_or_branch) << std::endl;
|
||||||
|
outfile << "rd_op: " << std::to_string(top->rd_op) << std::endl;
|
||||||
|
outfile << "two_stage_op: " << std::to_string(top->two_stage_op) << std::endl;
|
||||||
|
outfile << "dbus_en: " << std::to_string(top->dbus_en) << std::endl;
|
||||||
|
outfile << "mdu_op: " << std::to_string(top->mdu_op) << std::endl;
|
||||||
|
outfile << "ext_funct3: " << std::to_string(top->ext_funct3) << std::endl;
|
||||||
|
outfile << "bufreg_rs1_en: " << std::to_string(top->bufreg_rs1_en) << std::endl;
|
||||||
|
outfile << "bufreg_imm_en: " << std::to_string(top->bufreg_imm_en) << std::endl;
|
||||||
|
outfile << "bufreg_clr_lsb: " << std::to_string(top->bufreg_clr_lsb) << std::endl;
|
||||||
|
outfile << "bufreg_sh_signed: " << std::to_string(top->bufreg_sh_signed) << std::endl;
|
||||||
|
outfile << "ctrl_utype: " << std::to_string(top->ctrl_utype) << std::endl;
|
||||||
|
outfile << "ctrl_pc_rel: " << std::to_string(top->ctrl_pc_rel) << std::endl;
|
||||||
|
outfile << "alu_sub: " << std::to_string(top->alu_sub) << std::endl;
|
||||||
|
outfile << "alu_bool_op: " << std::to_string(top->alu_bool_op) << std::endl;
|
||||||
|
outfile << "alu_cmp_eq: " << std::to_string(top->alu_cmp_eq) << std::endl;
|
||||||
|
outfile << "alu_cmp_sig: " << std::to_string(top->alu_cmp_sig) << std::endl;
|
||||||
|
outfile << "alu_rd_sel: " << std::to_string(top->alu_rd_sel) << std::endl;
|
||||||
|
outfile << "mem_signed: " << std::to_string(top->mem_signed) << std::endl;
|
||||||
|
outfile << "mem_word: " << std::to_string(top->mem_word) << std::endl;
|
||||||
|
outfile << "mem_half: " << std::to_string(top->mem_half) << std::endl;
|
||||||
|
outfile << "mem_cmd: " << std::to_string(top->mem_cmd) << std::endl;
|
||||||
|
outfile << "csr_en: " << std::to_string(top->csr_en) << std::endl;
|
||||||
|
outfile << "csr_addr: " << std::to_string(top->csr_addr) << std::endl;
|
||||||
|
outfile << "csr_mstatus_en: " << std::to_string(top->csr_mstatus_en) << std::endl;
|
||||||
|
outfile << "csr_mie_en: " << std::to_string(top->csr_mie_en) << std::endl;
|
||||||
|
outfile << "csr_mcause_en: " << std::to_string(top->csr_mcause_en) << std::endl;
|
||||||
|
outfile << "csr_source: " << std::to_string(top->csr_source) << std::endl;
|
||||||
|
outfile << "csr_d_sel: " << std::to_string(top->csr_d_sel) << std::endl;
|
||||||
|
outfile << "csr_imm_en: " << std::to_string(top->csr_imm_en) << std::endl;
|
||||||
|
outfile << "mtval_pc: " << std::to_string(top->mtval_pc) << std::endl;
|
||||||
|
outfile << "immdec_ctrl: " << std::to_string(top->immdec_ctrl) << std::endl;
|
||||||
|
outfile << "immdec_en: " << std::to_string(top->immdec_en) << std::endl;
|
||||||
|
outfile << "op_b_source: " << std::to_string(top->op_b_source) << std::endl;
|
||||||
|
outfile << "rd_mem_en: " << std::to_string(top->rd_mem_en) << std::endl;
|
||||||
|
outfile << "rd_csr_en: " << std::to_string(top->rd_csr_en) << std::endl;
|
||||||
|
outfile << "rd_alu_en: " << std::to_string(top->rd_alu_en) << std::endl;
|
||||||
|
|
||||||
|
assert(!(top->wfi && instr_name != "wfi"));
|
||||||
|
|
||||||
|
top->wb_en = 0;
|
||||||
|
cycle(top);
|
||||||
|
outfile.close();
|
||||||
|
}
|
42
bench/servant_external_sim.v
Normal file
42
bench/servant_external_sim.v
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
`default_nettype none
|
||||||
|
module servant_external_sim
|
||||||
|
(input wire wb_clk,
|
||||||
|
input wire wb_rst,
|
||||||
|
input wire ext_irq,
|
||||||
|
output wire [31:0] pc_adr,
|
||||||
|
output wire pc_vld,
|
||||||
|
output wire q,
|
||||||
|
output wire mret
|
||||||
|
);
|
||||||
|
|
||||||
|
parameter memfile = "";
|
||||||
|
parameter memsize = 8192;
|
||||||
|
parameter width = 1;
|
||||||
|
parameter with_csr = 1;
|
||||||
|
parameter compressed = 0;
|
||||||
|
parameter align = compressed;
|
||||||
|
parameter interrupt_time = 3000;
|
||||||
|
|
||||||
|
reg [1023:0] firmware_file;
|
||||||
|
initial
|
||||||
|
if ($value$plusargs("firmware=%s", firmware_file)) begin
|
||||||
|
$display("Loading RAM from %0s", firmware_file);
|
||||||
|
$readmemh(firmware_file, dut.servant.ram.mem);
|
||||||
|
end
|
||||||
|
|
||||||
|
servant_sleep_dummy
|
||||||
|
#(.memfile (memfile),
|
||||||
|
.memsize (memsize),
|
||||||
|
.width (width),
|
||||||
|
.debug (1'b1),
|
||||||
|
.sim (1),
|
||||||
|
.with_csr (with_csr),
|
||||||
|
.compress (compressed[0:0]),
|
||||||
|
.align (align[0:0]))
|
||||||
|
dut(wb_clk, wb_rst, ext_irq, q);
|
||||||
|
|
||||||
|
assign pc_adr = dut.servant.wb_mem_adr;
|
||||||
|
assign pc_vld = dut.servant.wb_mem_ack;
|
||||||
|
assign mret = dut.servant.cpu.cpu.mret;
|
||||||
|
|
||||||
|
endmodule
|
126
bench/servant_external_tb.cpp
Normal file
126
bench/servant_external_tb.cpp
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "verilated_vcd_c.h"
|
||||||
|
#include "Vservant_external_sim.h"
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static bool done;
|
||||||
|
|
||||||
|
vluint64_t main_time = 0; // Current simulation time
|
||||||
|
// This is a 64-bit integer to reduce wrap over issues and
|
||||||
|
// allow modulus. You can also use a double, if you wish.
|
||||||
|
|
||||||
|
double sc_time_stamp () { // Called by $time in Verilog
|
||||||
|
return main_time; // converts to double, to match
|
||||||
|
// what SystemC does
|
||||||
|
}
|
||||||
|
|
||||||
|
void INThandler(int signal) {
|
||||||
|
printf("\nCaught ctrl-c\n");
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int reset(Vservant_external_sim *, VerilatedVcdC *);
|
||||||
|
int timer_test(Vservant_external_sim *, VerilatedVcdC *,
|
||||||
|
vluint64_t, vluint64_t);
|
||||||
|
|
||||||
|
int main(int argc, char **argv, char **env) {
|
||||||
|
Verilated::commandArgs(argc, argv);
|
||||||
|
|
||||||
|
Vservant_external_sim* top = new Vservant_external_sim;
|
||||||
|
|
||||||
|
VerilatedVcdC * tfp = 0;
|
||||||
|
const char *vcd = Verilated::commandArgsPlusMatch("vcd=");
|
||||||
|
if (vcd[0]) {
|
||||||
|
Verilated::traceEverOn(true);
|
||||||
|
tfp = new VerilatedVcdC;
|
||||||
|
top->trace (tfp, 99);
|
||||||
|
tfp->open ("trace.vcd");
|
||||||
|
}
|
||||||
|
|
||||||
|
signal(SIGINT, INThandler);
|
||||||
|
|
||||||
|
vluint64_t timeout = 0;
|
||||||
|
const char *arg_timeout = Verilated::commandArgsPlusMatch("timeout=");
|
||||||
|
if (arg_timeout[0])
|
||||||
|
timeout = atoi(arg_timeout+9);
|
||||||
|
|
||||||
|
vluint64_t interrupt_time = 1500;
|
||||||
|
const char *arg_interrupt_time =
|
||||||
|
Verilated::commandArgsPlusMatch("interrupt_time=");
|
||||||
|
if (arg_interrupt_time[0]) {
|
||||||
|
interrupt_time = atoi(arg_interrupt_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
vluint64_t vcd_start = 0;
|
||||||
|
const char *arg_vcd_start = Verilated::commandArgsPlusMatch("vcd_start=");
|
||||||
|
if (arg_vcd_start[0])
|
||||||
|
vcd_start = atoi(arg_vcd_start+11);
|
||||||
|
|
||||||
|
int cur_cycle = 0;
|
||||||
|
int last_cycle = 0;
|
||||||
|
std::time_t last_time = std::time(nullptr);
|
||||||
|
|
||||||
|
top->wb_clk = 1;
|
||||||
|
top->ext_irq = 0;
|
||||||
|
bool q = top->q;
|
||||||
|
int clock = 0;
|
||||||
|
reset(top, tfp);
|
||||||
|
timer_test(top, tfp, timeout, interrupt_time);
|
||||||
|
if (tfp) {
|
||||||
|
tfp->close();
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int reset(Vservant_external_sim *top, VerilatedVcdC *tfp) {
|
||||||
|
top->wb_rst = 1;
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
top->wb_clk = !top->wb_clk;
|
||||||
|
top->eval();
|
||||||
|
}
|
||||||
|
top->wb_clk = !top->wb_clk;
|
||||||
|
top->wb_rst = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int timer_test(Vservant_external_sim *top, VerilatedVcdC *tfp,
|
||||||
|
vluint64_t timeout, vluint64_t interrupt_time) {
|
||||||
|
int clock = 0;
|
||||||
|
while (Verilated::gotFinish()) {
|
||||||
|
top->eval();
|
||||||
|
if (top->wb_clk) {
|
||||||
|
clock++;
|
||||||
|
}
|
||||||
|
if (tfp && top->wb_clk) {
|
||||||
|
tfp->dump(clock);
|
||||||
|
}
|
||||||
|
if (clock >= interrupt_time && clock <= interrupt_time + 100) {
|
||||||
|
if (top->ext_irq == 0) {
|
||||||
|
printf("interrupting %d\n", clock);
|
||||||
|
}
|
||||||
|
top->ext_irq = 1;
|
||||||
|
} else {
|
||||||
|
top->ext_irq = 0;
|
||||||
|
}
|
||||||
|
if (top->wb_clk && top->pc_vld && top->pc_adr) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
|
printf("%d | %d\n", clock, top->pc_adr);
|
||||||
|
if (top->mret) {
|
||||||
|
printf("mret detected, exiting\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (timeout && (clock >= timeout)) {
|
||||||
|
printf("Timeout: Exiting at time %d\n", clock);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
top->wb_clk = !top->wb_clk;
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,7 +29,7 @@ module servant_sim
|
||||||
.with_csr (with_csr),
|
.with_csr (with_csr),
|
||||||
.compress (compressed[0:0]),
|
.compress (compressed[0:0]),
|
||||||
.align (align[0:0]))
|
.align (align[0:0]))
|
||||||
dut(wb_clk, wb_rst, q);
|
dut(wb_clk, wb_clk, wb_rst, q);
|
||||||
|
|
||||||
assign pc_adr = dut.wb_mem_adr;
|
assign pc_adr = dut.wb_mem_adr;
|
||||||
assign pc_vld = dut.wb_mem_ack;
|
assign pc_vld = dut.wb_mem_ack;
|
||||||
|
|
43
bench/servant_timer_sim.v
Normal file
43
bench/servant_timer_sim.v
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
`default_nettype none
|
||||||
|
module servant_timer_sim
|
||||||
|
(input wire wb_clk,
|
||||||
|
input wire wb_rst,
|
||||||
|
input wire timer_clk,
|
||||||
|
output wire [31:0] pc_adr,
|
||||||
|
output wire pc_vld,
|
||||||
|
output wire q,
|
||||||
|
output wire timer_irq
|
||||||
|
);
|
||||||
|
|
||||||
|
parameter memfile = "";
|
||||||
|
parameter memsize = 8192;
|
||||||
|
parameter width = 1;
|
||||||
|
parameter with_csr = 1;
|
||||||
|
parameter compressed = 0;
|
||||||
|
parameter align = compressed;
|
||||||
|
|
||||||
|
wire sleep;
|
||||||
|
wire ext_irq;
|
||||||
|
|
||||||
|
reg [1023:0] firmware_file;
|
||||||
|
initial
|
||||||
|
if ($value$plusargs("firmware=%s", firmware_file)) begin
|
||||||
|
$display("Loading RAM from %0s", firmware_file);
|
||||||
|
$readmemh(firmware_file, dut.servant.ram.mem);
|
||||||
|
end
|
||||||
|
|
||||||
|
servant_sleep_dummy
|
||||||
|
#(.memfile (memfile),
|
||||||
|
.memsize (memsize),
|
||||||
|
.width (width),
|
||||||
|
.debug (1'b1),
|
||||||
|
.sim (1),
|
||||||
|
.with_csr (with_csr),
|
||||||
|
.compress (compressed[0:0]),
|
||||||
|
.align (align[0:0]))
|
||||||
|
dut(wb_clk, wb_rst, ext_irq, q);
|
||||||
|
|
||||||
|
assign pc_adr = dut.servant.wb_mem_adr;
|
||||||
|
assign pc_vld = dut.servant.wb_mem_ack;
|
||||||
|
assign timer_irq = dut.servant.timer_irq;
|
||||||
|
endmodule
|
92
bench/servant_timer_tb.cpp
Normal file
92
bench/servant_timer_tb.cpp
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "verilated_vcd_c.h"
|
||||||
|
#include "Vservant_timer_sim.h"
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static bool done;
|
||||||
|
|
||||||
|
vluint64_t main_time = 0; // Current simulation time
|
||||||
|
// This is a 64-bit integer to reduce wrap over issues and
|
||||||
|
// allow modulus. You can also use a double, if you wish.
|
||||||
|
|
||||||
|
double sc_time_stamp () { // Called by $time in Verilog
|
||||||
|
return main_time; // converts to double, to match
|
||||||
|
// what SystemC does
|
||||||
|
}
|
||||||
|
|
||||||
|
void INThandler(int signal)
|
||||||
|
{
|
||||||
|
printf("\nCaught ctrl-c\n");
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv, char **env)
|
||||||
|
{
|
||||||
|
int baud_rate = 0;
|
||||||
|
|
||||||
|
Verilated::commandArgs(argc, argv);
|
||||||
|
|
||||||
|
Vservant_timer_sim* top = new Vservant_timer_sim;
|
||||||
|
|
||||||
|
VerilatedVcdC * tfp = 0;
|
||||||
|
const char *vcd = Verilated::commandArgsPlusMatch("vcd=");
|
||||||
|
if (vcd[0]) {
|
||||||
|
Verilated::traceEverOn(true);
|
||||||
|
tfp = new VerilatedVcdC;
|
||||||
|
top->trace (tfp, 99);
|
||||||
|
tfp->open ("trace.vcd");
|
||||||
|
}
|
||||||
|
|
||||||
|
signal(SIGINT, INThandler);
|
||||||
|
|
||||||
|
vluint64_t timeout = 0;
|
||||||
|
const char *arg_timeout = Verilated::commandArgsPlusMatch("timeout=");
|
||||||
|
if (arg_timeout[0])
|
||||||
|
timeout = atoi(arg_timeout+9);
|
||||||
|
|
||||||
|
vluint64_t vcd_start = 0;
|
||||||
|
const char *arg_vcd_start = Verilated::commandArgsPlusMatch("vcd_start=");
|
||||||
|
if (arg_vcd_start[0])
|
||||||
|
vcd_start = atoi(arg_vcd_start+11);
|
||||||
|
|
||||||
|
int cur_cycle = 0;
|
||||||
|
int last_cycle = 0;
|
||||||
|
std::time_t last_time = std::time(nullptr);
|
||||||
|
|
||||||
|
top->wb_clk = 0;
|
||||||
|
top->timer_clk = 0;
|
||||||
|
bool q = top->q;
|
||||||
|
int clock = 0;
|
||||||
|
top->eval();
|
||||||
|
while (!(done || Verilated::gotFinish())) {
|
||||||
|
top->eval();
|
||||||
|
if (top->wb_clk) {
|
||||||
|
clock++;
|
||||||
|
}
|
||||||
|
top->wb_rst = main_time < 1000;
|
||||||
|
if (tfp) {
|
||||||
|
tfp->dump(main_time);
|
||||||
|
}
|
||||||
|
if (top->wb_clk && top->pc_vld && top->pc_adr) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
|
printf("%d | %d\n", clock, top->pc_adr);
|
||||||
|
}
|
||||||
|
if (timeout && (main_time >= timeout)) {
|
||||||
|
printf("Timeout: Exiting at time %lu\n", main_time);
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
top->wb_clk = !top->wb_clk;
|
||||||
|
top->timer_clk = top->wb_clk;
|
||||||
|
main_time+=31.25;
|
||||||
|
}
|
||||||
|
if (tfp) {
|
||||||
|
tfp->close();
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
17
data/nexys_4.xdc
Normal file
17
data/nexys_4.xdc
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
## 100 MHz Clock Signal (period 10)
|
||||||
|
set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { i_clk }];
|
||||||
|
create_clock -add -name sys_clk_pin -period 10 -waveform {0 5} [get_ports { i_clk }];
|
||||||
|
|
||||||
|
## External interrupt (to BTNL)
|
||||||
|
set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports {ext_irq}];
|
||||||
|
|
||||||
|
## LEDs
|
||||||
|
set_property -dict { PACKAGE_PIN T8 IOSTANDARD LVCMOS33 } [get_ports { q }];
|
||||||
|
|
||||||
|
## UART
|
||||||
|
set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { o_uart_tx }];
|
||||||
|
|
||||||
|
set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { i_rst }]; # ACTIVE LOW !!!
|
||||||
|
|
||||||
|
set_property CFGBVS VCCO [current_design]
|
||||||
|
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
|
@ -1,4 +1,23 @@
|
||||||
set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports i_clk];
|
## 100 MHz Clock Signal (period 10)
|
||||||
set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports q]
|
set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { i_clk }];
|
||||||
|
create_clock -add -name sys_clk_pin -period 10 -waveform {0 5} [get_ports { i_clk }];
|
||||||
|
|
||||||
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports i_clk];
|
## External interrupt (to BTNL)
|
||||||
|
set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports {ext_irq}];
|
||||||
|
|
||||||
|
## LEDs (LED0)
|
||||||
|
set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { q }];
|
||||||
|
|
||||||
|
## UART
|
||||||
|
set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { o_uart_tx }];
|
||||||
|
|
||||||
|
set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { i_rst }]; # ACTIVE LOW !!!
|
||||||
|
|
||||||
|
set_property CFGBVS VCCO [current_design]
|
||||||
|
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
||||||
|
|
||||||
|
## DEBUG (JA1)
|
||||||
|
#set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { debug_wb_clk }]; #JA1
|
||||||
|
#set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { q }]; #JA2
|
||||||
|
#set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { debug_sleep_req }]; #JA3
|
||||||
|
#set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { debug_wakeup_req }]; #JA4
|
||||||
|
|
|
@ -19,6 +19,7 @@ module serv_csr
|
||||||
input wire i_cnt_done,
|
input wire i_cnt_done,
|
||||||
input wire i_mem_op,
|
input wire i_mem_op,
|
||||||
input wire i_mtip,
|
input wire i_mtip,
|
||||||
|
input wire i_meip,
|
||||||
input wire i_trap,
|
input wire i_trap,
|
||||||
output reg o_new_irq,
|
output reg o_new_irq,
|
||||||
//Control
|
//Control
|
||||||
|
@ -36,7 +37,9 @@ module serv_csr
|
||||||
output wire [B:0] o_csr_in,
|
output wire [B:0] o_csr_in,
|
||||||
input wire [B:0] i_csr_imm,
|
input wire [B:0] i_csr_imm,
|
||||||
input wire [B:0] i_rs1,
|
input wire [B:0] i_rs1,
|
||||||
output wire [B:0] o_q);
|
output wire [B:0] o_q,
|
||||||
|
output wire o_meie,
|
||||||
|
output wire o_mtie);
|
||||||
|
|
||||||
localparam [1:0]
|
localparam [1:0]
|
||||||
CSR_SOURCE_CSR = 2'b00,
|
CSR_SOURCE_CSR = 2'b00,
|
||||||
|
@ -47,6 +50,10 @@ module serv_csr
|
||||||
reg mstatus_mie;
|
reg mstatus_mie;
|
||||||
reg mstatus_mpie;
|
reg mstatus_mpie;
|
||||||
reg mie_mtie;
|
reg mie_mtie;
|
||||||
|
reg mie_meie;
|
||||||
|
|
||||||
|
assign o_meie = mie_meie;
|
||||||
|
assign o_mtie = mie_mtie;
|
||||||
|
|
||||||
reg mcause31;
|
reg mcause31;
|
||||||
reg [3:0] mcause3_0;
|
reg [3:0] mcause3_0;
|
||||||
|
@ -55,7 +62,7 @@ module serv_csr
|
||||||
wire [B:0] csr_in;
|
wire [B:0] csr_in;
|
||||||
wire [B:0] csr_out;
|
wire [B:0] csr_out;
|
||||||
|
|
||||||
reg timer_irq_r;
|
reg irq_r;
|
||||||
|
|
||||||
wire [B:0] d = i_csr_d_sel ? i_csr_imm : i_rs1;
|
wire [B:0] d = i_csr_d_sel ? i_csr_imm : i_rs1;
|
||||||
|
|
||||||
|
@ -81,7 +88,9 @@ module serv_csr
|
||||||
|
|
||||||
assign o_q = csr_out;
|
assign o_q = csr_out;
|
||||||
|
|
||||||
wire timer_irq = i_mtip & mstatus_mie & mie_mtie;
|
wire timer_irq = i_mtip & mie_mtie;
|
||||||
|
wire ext_irq = i_meip & mie_meie;
|
||||||
|
wire irq = (timer_irq | ext_irq) & mstatus_mie;
|
||||||
|
|
||||||
assign mcause = i_cnt0to3 ? mcause3_0[B:0] : //[3:0]
|
assign mcause = i_cnt0to3 ? mcause3_0[B:0] : //[3:0]
|
||||||
i_cnt_done ? {mcause31,{B{1'b0}}} //[31]
|
i_cnt_done ? {mcause31,{B{1'b0}}} //[31]
|
||||||
|
@ -91,13 +100,16 @@ module serv_csr
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
if (i_trig_irq) begin
|
if (i_trig_irq) begin
|
||||||
timer_irq_r <= timer_irq;
|
irq_r <= irq;
|
||||||
o_new_irq <= timer_irq & !timer_irq_r;
|
o_new_irq <= (irq & !irq_r);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (i_mie_en & i_cnt7)
|
if (i_mie_en & i_cnt7)
|
||||||
mie_mtie <= csr_in[B];
|
mie_mtie <= csr_in[B];
|
||||||
|
|
||||||
|
if(i_mie_en & i_cnt11)
|
||||||
|
mie_meie <= csr_in[B];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The mie bit in mstatus gets updated under three conditions
|
The mie bit in mstatus gets updated under three conditions
|
||||||
|
|
||||||
|
@ -126,8 +138,8 @@ module serv_csr
|
||||||
During an mcause CSR access function, they are assigned when
|
During an mcause CSR access function, they are assigned when
|
||||||
bits 0 to 3 gets updated
|
bits 0 to 3 gets updated
|
||||||
|
|
||||||
During an external interrupt the exception code is set to
|
During an interrupt, the exception code is assigned to indicate
|
||||||
7, since SERV only support timer interrupts
|
if it was caused by a timer interrupt (7) or an external interrupt (11).
|
||||||
|
|
||||||
During an exception, the exception code is assigned to indicate
|
During an exception, the exception code is assigned to indicate
|
||||||
if it was caused by an ebreak instruction (3),
|
if it was caused by an ebreak instruction (3),
|
||||||
|
@ -135,14 +147,15 @@ module serv_csr
|
||||||
or misaligned jump (0)
|
or misaligned jump (0)
|
||||||
|
|
||||||
The expressions below are derived from the following truth table
|
The expressions below are derived from the following truth table
|
||||||
irq => 0111 (timer=7)
|
timer_irq => 0111 (timer=7)
|
||||||
|
ext_irq => 1011 (ext=11)
|
||||||
e_op => x011 (ebreak=3, ecall=11)
|
e_op => x011 (ebreak=3, ecall=11)
|
||||||
mem => 01x0 (store=6, load=4)
|
mem => 01x0 (store=6, load=4)
|
||||||
ctrl => 0000 (jump=0)
|
ctrl => 0000 (jump=0)
|
||||||
*/
|
*/
|
||||||
if (i_mcause_en & i_en & i_cnt0to3 | (i_trap & i_cnt_done)) begin
|
if (i_mcause_en & i_en & i_cnt0to3 | (i_trap & i_cnt_done)) begin
|
||||||
mcause3_0[3] <= (i_e_op & !i_ebreak) | (!i_trap & csr_in[B]);
|
mcause3_0[3] <= (o_new_irq & ext_irq) | (i_e_op & !i_ebreak) | (!i_trap & csr_in[B]);
|
||||||
mcause3_0[2] <= o_new_irq | i_mem_op | (!i_trap & ((W == 1) ? mcause3_0[3] : csr_in[(W == 1) ? 0 : 2]));
|
mcause3_0[2] <= (o_new_irq & !ext_irq) | i_mem_op | (!i_trap & ((W == 1) ? mcause3_0[3] : csr_in[(W == 1) ? 0 : 2]));
|
||||||
mcause3_0[1] <= o_new_irq | i_e_op | (i_mem_op & i_mem_cmd) | (!i_trap & ((W == 1) ? mcause3_0[2] : csr_in[(W == 1) ? 0 : 1]));
|
mcause3_0[1] <= o_new_irq | i_e_op | (i_mem_op & i_mem_cmd) | (!i_trap & ((W == 1) ? mcause3_0[2] : csr_in[(W == 1) ? 0 : 1]));
|
||||||
mcause3_0[0] <= o_new_irq | i_e_op | (!i_trap & ((W == 1) ? mcause3_0[1] : csr_in[0]));
|
mcause3_0[0] <= o_new_irq | i_e_op | (!i_trap & ((W == 1) ? mcause3_0[1] : csr_in[0]));
|
||||||
end
|
end
|
||||||
|
@ -152,6 +165,7 @@ module serv_csr
|
||||||
if (RESET_STRATEGY != "NONE") begin
|
if (RESET_STRATEGY != "NONE") begin
|
||||||
o_new_irq <= 1'b0;
|
o_new_irq <= 1'b0;
|
||||||
mie_mtie <= 1'b0;
|
mie_mtie <= 1'b0;
|
||||||
|
mie_meie <= 1'b0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -176,7 +176,7 @@ module serv_debug
|
||||||
if (update_mcause) dbg_mcause <= dbg_csr;
|
if (update_mcause) dbg_mcause <= dbg_csr;
|
||||||
end
|
end
|
||||||
|
|
||||||
reg LUI, AUIPC, JAL, JALR, BEQ, BNE, BLT, BGE, BLTU, BGEU, LB, LH, LW, LBU, LHU, SB, SH, SW, ADDI, SLTI, SLTIU, XORI, ORI, ANDI,SLLI, SRLI, SRAI, ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND, FENCE, ECALL, EBREAK;
|
reg LUI, AUIPC, JAL, JALR, BEQ, BNE, BLT, BGE, BLTU, BGEU, LB, LH, LW, LBU, LHU, SB, SH, SW, ADDI, SLTI, SLTIU, XORI, ORI, ANDI,SLLI, SRLI, SRAI, ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND, FENCE, ECALL, EBREAK, WFI;
|
||||||
reg CSRRW, CSRRS, CSRRC, CSRRWI, CSRRSI, CSRRCI;
|
reg CSRRW, CSRRS, CSRRC, CSRRWI, CSRRSI, CSRRCI;
|
||||||
reg OTHER;
|
reg OTHER;
|
||||||
|
|
||||||
|
@ -222,6 +222,7 @@ module serv_debug
|
||||||
FENCE <= 1'b0;
|
FENCE <= 1'b0;
|
||||||
ECALL <= 1'b0;
|
ECALL <= 1'b0;
|
||||||
EBREAK <= 1'b0;
|
EBREAK <= 1'b0;
|
||||||
|
WFI <= 1'b0;
|
||||||
CSRRW <= 1'b0;
|
CSRRW <= 1'b0;
|
||||||
CSRRS <= 1'b0;
|
CSRRS <= 1'b0;
|
||||||
CSRRC <= 1'b0;
|
CSRRC <= 1'b0;
|
||||||
|
@ -273,6 +274,7 @@ module serv_debug
|
||||||
32'b???????_?????_?????_000_?????_00011_11 : FENCE <= 1'b1;
|
32'b???????_?????_?????_000_?????_00011_11 : FENCE <= 1'b1;
|
||||||
32'b0000000_00000_00000_000_00000_11100_11 : ECALL <= 1'b1;
|
32'b0000000_00000_00000_000_00000_11100_11 : ECALL <= 1'b1;
|
||||||
32'b0000000_00001_00000_000_00000_11100_11 : EBREAK <= 1'b1;
|
32'b0000000_00001_00000_000_00000_11100_11 : EBREAK <= 1'b1;
|
||||||
|
32'b0001000_00010_00000_000_00000_11100_11 : WFI <= 1'b1;
|
||||||
32'b???????_?????_?????_001_?????_11100_11 : CSRRW <= 1'b1;
|
32'b???????_?????_?????_001_?????_11100_11 : CSRRW <= 1'b1;
|
||||||
32'b???????_?????_?????_010_?????_11100_11 : CSRRS <= 1'b1;
|
32'b???????_?????_?????_010_?????_11100_11 : CSRRS <= 1'b1;
|
||||||
32'b???????_?????_?????_011_?????_11100_11 : CSRRC <= 1'b1;
|
32'b???????_?????_?????_011_?????_11100_11 : CSRRC <= 1'b1;
|
||||||
|
|
|
@ -13,6 +13,7 @@ module serv_decode
|
||||||
output reg o_cond_branch,
|
output reg o_cond_branch,
|
||||||
output reg o_e_op,
|
output reg o_e_op,
|
||||||
output reg o_ebreak,
|
output reg o_ebreak,
|
||||||
|
output reg o_wfi,
|
||||||
output reg o_branch_op,
|
output reg o_branch_op,
|
||||||
output reg o_shift_op,
|
output reg o_shift_op,
|
||||||
output reg o_rd_op,
|
output reg o_rd_op,
|
||||||
|
@ -76,7 +77,7 @@ module serv_decode
|
||||||
|
|
||||||
wire co_two_stage_op =
|
wire co_two_stage_op =
|
||||||
~opcode[2] | (funct3[0] & ~funct3[1] & ~opcode[0] & ~opcode[4]) |
|
~opcode[2] | (funct3[0] & ~funct3[1] & ~opcode[0] & ~opcode[4]) |
|
||||||
(funct3[1] & ~funct3[2] & ~opcode[0] & ~opcode[4]) | co_mdu_op;
|
(funct3[1] & ~funct3[2] & ~opcode[0] & ~opcode[4]) | co_mdu_op | o_wfi;
|
||||||
wire co_shift_op = (opcode[2] & ~funct3[1]) & !co_mdu_op;
|
wire co_shift_op = (opcode[2] & ~funct3[1]) & !co_mdu_op;
|
||||||
wire co_branch_op = opcode[4];
|
wire co_branch_op = opcode[4];
|
||||||
wire co_dbus_en = ~opcode[2] & ~opcode[4];
|
wire co_dbus_en = ~opcode[2] & ~opcode[4];
|
||||||
|
@ -127,20 +128,22 @@ module serv_decode
|
||||||
wire co_sh_right = funct3[2];
|
wire co_sh_right = funct3[2];
|
||||||
wire co_bne_or_bge = funct3[0];
|
wire co_bne_or_bge = funct3[0];
|
||||||
|
|
||||||
//Matches system ops except eceall/ebreak/mret
|
//Matches system ops except ecall/ebreak/mret/wfi
|
||||||
wire csr_op = opcode[4] & opcode[2] & (|funct3);
|
wire csr_op = opcode[4] & opcode[2] & (|funct3);
|
||||||
|
|
||||||
|
|
||||||
//op20
|
//op20
|
||||||
wire co_ebreak = op20;
|
wire co_ebreak = op20 & !op22;
|
||||||
|
|
||||||
|
wire co_wfi = opcode[4] & opcode[2] & op22 & !(|funct3);
|
||||||
|
|
||||||
|
|
||||||
//opcode & funct3 & op21
|
//opcode & funct3 & op21
|
||||||
|
|
||||||
wire co_ctrl_mret = opcode[4] & opcode[2] & op21 & !(|funct3);
|
wire co_ctrl_mret = opcode[4] & opcode[2] & op21 & !(|funct3);
|
||||||
//Matches system opcodes except CSR accesses (funct3 == 0)
|
//Matches system opcodes except CSR accesses (funct3 == 0)
|
||||||
//and mret (!op21)
|
//and mret (!op21) and wfi (!op22)
|
||||||
wire co_e_op = opcode[4] & opcode[2] & !op21 & !(|funct3);
|
wire co_e_op = opcode[4] & opcode[2] & !op21 & !op22 & !(|funct3);
|
||||||
|
|
||||||
//opcode & funct3 & imm30
|
//opcode & funct3 & imm30
|
||||||
|
|
||||||
|
@ -255,6 +258,7 @@ module serv_decode
|
||||||
o_two_stage_op = co_two_stage_op;
|
o_two_stage_op = co_two_stage_op;
|
||||||
o_e_op = co_e_op;
|
o_e_op = co_e_op;
|
||||||
o_ebreak = co_ebreak;
|
o_ebreak = co_ebreak;
|
||||||
|
o_wfi = co_wfi;
|
||||||
o_branch_op = co_branch_op;
|
o_branch_op = co_branch_op;
|
||||||
o_shift_op = co_shift_op;
|
o_shift_op = co_shift_op;
|
||||||
o_rd_op = co_rd_op;
|
o_rd_op = co_rd_op;
|
||||||
|
@ -313,6 +317,7 @@ module serv_decode
|
||||||
o_cond_branch <= co_cond_branch;
|
o_cond_branch <= co_cond_branch;
|
||||||
o_e_op <= co_e_op;
|
o_e_op <= co_e_op;
|
||||||
o_ebreak <= co_ebreak;
|
o_ebreak <= co_ebreak;
|
||||||
|
o_wfi <= co_wfi;
|
||||||
o_two_stage_op <= co_two_stage_op;
|
o_two_stage_op <= co_two_stage_op;
|
||||||
o_dbus_en <= co_dbus_en;
|
o_dbus_en <= co_dbus_en;
|
||||||
o_mtval_pc <= co_mtval_pc;
|
o_mtval_pc <= co_mtval_pc;
|
||||||
|
|
|
@ -19,6 +19,10 @@ module serv_rf_top
|
||||||
0 : Register after the decoder. Faster but uses more resources
|
0 : Register after the decoder. Faster but uses more resources
|
||||||
1 : (default) Register before the decoder. Slower but uses less resources
|
1 : (default) Register before the decoder. Slower but uses less resources
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
parameter [0:0] EI = 0,
|
||||||
|
/* asd */
|
||||||
|
|
||||||
parameter PRE_REGISTER = 1,
|
parameter PRE_REGISTER = 1,
|
||||||
/* Amount of reset applied to design
|
/* Amount of reset applied to design
|
||||||
"NONE" : No reset at all. Relies on a POR to set correct initialization
|
"NONE" : No reset at all. Relies on a POR to set correct initialization
|
||||||
|
@ -36,6 +40,7 @@ module serv_rf_top
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire i_rst,
|
input wire i_rst,
|
||||||
input wire i_timer_irq,
|
input wire i_timer_irq,
|
||||||
|
input wire i_external_irq,
|
||||||
`ifdef RISCV_FORMAL
|
`ifdef RISCV_FORMAL
|
||||||
output wire rvfi_valid,
|
output wire rvfi_valid,
|
||||||
output wire [63:0] rvfi_order,
|
output wire [63:0] rvfi_order,
|
||||||
|
@ -77,6 +82,11 @@ module serv_rf_top
|
||||||
output wire [ 2:0] o_ext_funct3,
|
output wire [ 2:0] o_ext_funct3,
|
||||||
input wire [31:0] i_ext_rd,
|
input wire [31:0] i_ext_rd,
|
||||||
input wire i_ext_ready,
|
input wire i_ext_ready,
|
||||||
|
|
||||||
|
// Sleep functionality
|
||||||
|
output wire o_sleep_req,
|
||||||
|
output wire o_wakeup_req,
|
||||||
|
|
||||||
// MDU
|
// MDU
|
||||||
output wire o_mdu_valid);
|
output wire o_mdu_valid);
|
||||||
|
|
||||||
|
@ -150,6 +160,7 @@ module serv_rf_top
|
||||||
.WITH_CSR (WITH_CSR),
|
.WITH_CSR (WITH_CSR),
|
||||||
.DEBUG (DEBUG),
|
.DEBUG (DEBUG),
|
||||||
.MDU(MDU),
|
.MDU(MDU),
|
||||||
|
.EI(EI),
|
||||||
.COMPRESSED(COMPRESSED),
|
.COMPRESSED(COMPRESSED),
|
||||||
.ALIGN(ALIGN),
|
.ALIGN(ALIGN),
|
||||||
.W(W))
|
.W(W))
|
||||||
|
@ -158,6 +169,7 @@ module serv_rf_top
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
.i_rst (i_rst),
|
.i_rst (i_rst),
|
||||||
.i_timer_irq (i_timer_irq),
|
.i_timer_irq (i_timer_irq),
|
||||||
|
.i_external_irq (i_external_irq),
|
||||||
`ifdef RISCV_FORMAL
|
`ifdef RISCV_FORMAL
|
||||||
.rvfi_valid (rvfi_valid ),
|
.rvfi_valid (rvfi_valid ),
|
||||||
.rvfi_order (rvfi_order ),
|
.rvfi_order (rvfi_order ),
|
||||||
|
@ -208,6 +220,11 @@ module serv_rf_top
|
||||||
.i_dbus_rdt (i_dbus_rdt),
|
.i_dbus_rdt (i_dbus_rdt),
|
||||||
.i_dbus_ack (i_dbus_ack),
|
.i_dbus_ack (i_dbus_ack),
|
||||||
|
|
||||||
|
// Sleep
|
||||||
|
.o_sleep_req (o_sleep_req),
|
||||||
|
.o_wakeup_req (o_wakeup_req),
|
||||||
|
|
||||||
|
|
||||||
//Extension
|
//Extension
|
||||||
.o_ext_funct3 (o_ext_funct3),
|
.o_ext_funct3 (o_ext_funct3),
|
||||||
.i_ext_ready (i_ext_ready),
|
.i_ext_ready (i_ext_ready),
|
||||||
|
|
20
rtl/serv_sleep.v
Normal file
20
rtl/serv_sleep.v
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
`default_nettype none
|
||||||
|
module serv_sleep
|
||||||
|
(
|
||||||
|
input wire i_clk,
|
||||||
|
input wire i_rst,
|
||||||
|
input wire i_timer_irq,
|
||||||
|
input wire i_external_irq,
|
||||||
|
input wire i_cnt0,
|
||||||
|
input wire i_wfi,
|
||||||
|
input wire i_init,
|
||||||
|
input wire i_mtie,
|
||||||
|
input wire i_meie,
|
||||||
|
|
||||||
|
output wire o_sleep_req,
|
||||||
|
output wire o_wakeup_req);
|
||||||
|
|
||||||
|
assign o_sleep_req = i_wfi & i_cnt0 & i_init;
|
||||||
|
assign o_wakeup_req = (i_timer_irq & i_mtie) | (i_external_irq & i_meie);
|
||||||
|
|
||||||
|
endmodule
|
|
@ -86,7 +86,8 @@ module serv_synth_wrapper
|
||||||
.PRE_REGISTER (PRE_REGISTER),
|
.PRE_REGISTER (PRE_REGISTER),
|
||||||
.RESET_STRATEGY (RESET_STRATEGY),
|
.RESET_STRATEGY (RESET_STRATEGY),
|
||||||
.WITH_CSR (WITH_CSR),
|
.WITH_CSR (WITH_CSR),
|
||||||
.MDU(1'b0))
|
.MDU(1'b0),
|
||||||
|
.EI(1'b0))
|
||||||
cpu
|
cpu
|
||||||
(
|
(
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
|
|
|
@ -9,12 +9,14 @@ module serv_top
|
||||||
parameter RESET_PC = 32'd0,
|
parameter RESET_PC = 32'd0,
|
||||||
parameter [0:0] DEBUG = 1'b0,
|
parameter [0:0] DEBUG = 1'b0,
|
||||||
parameter [0:0] MDU = 1'b0,
|
parameter [0:0] MDU = 1'b0,
|
||||||
|
parameter [0:0] EI = 1'b0,
|
||||||
parameter [0:0] COMPRESSED=0,
|
parameter [0:0] COMPRESSED=0,
|
||||||
parameter [0:0] ALIGN = COMPRESSED)
|
parameter [0:0] ALIGN = COMPRESSED)
|
||||||
(
|
(
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire i_rst,
|
input wire i_rst,
|
||||||
input wire i_timer_irq,
|
input wire i_timer_irq,
|
||||||
|
input wire i_external_irq,
|
||||||
`ifdef RISCV_FORMAL
|
`ifdef RISCV_FORMAL
|
||||||
output wire rvfi_valid,
|
output wire rvfi_valid,
|
||||||
output wire [63:0] rvfi_order,
|
output wire [63:0] rvfi_order,
|
||||||
|
@ -70,6 +72,11 @@ module serv_top
|
||||||
input wire [31:0] i_ext_rd,
|
input wire [31:0] i_ext_rd,
|
||||||
output wire [31:0] o_ext_rs1,
|
output wire [31:0] o_ext_rs1,
|
||||||
output wire [31:0] o_ext_rs2,
|
output wire [31:0] o_ext_rs2,
|
||||||
|
|
||||||
|
// Sleep functionality
|
||||||
|
output wire o_sleep_req,
|
||||||
|
output wire o_wakeup_req,
|
||||||
|
|
||||||
//MDU
|
//MDU
|
||||||
output wire o_mdu_valid);
|
output wire o_mdu_valid);
|
||||||
|
|
||||||
|
@ -86,6 +93,7 @@ module serv_top
|
||||||
wire two_stage_op;
|
wire two_stage_op;
|
||||||
wire e_op;
|
wire e_op;
|
||||||
wire ebreak;
|
wire ebreak;
|
||||||
|
wire wfi;
|
||||||
wire branch_op;
|
wire branch_op;
|
||||||
wire shift_op;
|
wire shift_op;
|
||||||
wire rd_op;
|
wire rd_op;
|
||||||
|
@ -183,6 +191,9 @@ module serv_top
|
||||||
wire [31:0] wb_ibus_rdt;
|
wire [31:0] wb_ibus_rdt;
|
||||||
wire wb_ibus_ack;
|
wire wb_ibus_ack;
|
||||||
|
|
||||||
|
wire mie_meie;
|
||||||
|
wire mie_mtie;
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (ALIGN) begin : gen_align
|
if (ALIGN) begin : gen_align
|
||||||
serv_aligner align
|
serv_aligner align
|
||||||
|
@ -222,6 +233,20 @@ module serv_top
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
|
serv_sleep sleep
|
||||||
|
(
|
||||||
|
.i_clk (clk),
|
||||||
|
.i_rst (i_rst),
|
||||||
|
.i_timer_irq (i_timer_irq),
|
||||||
|
.i_external_irq (i_external_irq),
|
||||||
|
.i_cnt0 (cnt0),
|
||||||
|
.i_wfi (wfi),
|
||||||
|
.i_init (init),
|
||||||
|
.o_sleep_req (o_sleep_req),
|
||||||
|
.o_wakeup_req (o_wakeup_req),
|
||||||
|
.i_meie (mie_meie),
|
||||||
|
.i_mtie (mie_mtie));
|
||||||
|
|
||||||
serv_state
|
serv_state
|
||||||
#(.RESET_STRATEGY (RESET_STRATEGY),
|
#(.RESET_STRATEGY (RESET_STRATEGY),
|
||||||
.WITH_CSR (WITH_CSR[0:0]),
|
.WITH_CSR (WITH_CSR[0:0]),
|
||||||
|
@ -298,6 +323,7 @@ module serv_top
|
||||||
.o_dbus_en (dbus_en),
|
.o_dbus_en (dbus_en),
|
||||||
.o_e_op (e_op),
|
.o_e_op (e_op),
|
||||||
.o_ebreak (ebreak),
|
.o_ebreak (ebreak),
|
||||||
|
.o_wfi (wfi),
|
||||||
.o_branch_op (branch_op),
|
.o_branch_op (branch_op),
|
||||||
.o_shift_op (shift_op),
|
.o_shift_op (shift_op),
|
||||||
.o_rd_op (rd_op),
|
.o_rd_op (rd_op),
|
||||||
|
@ -563,6 +589,7 @@ module serv_top
|
||||||
.i_cnt_done (cnt_done),
|
.i_cnt_done (cnt_done),
|
||||||
.i_mem_op (!mtval_pc),
|
.i_mem_op (!mtval_pc),
|
||||||
.i_mtip (i_timer_irq),
|
.i_mtip (i_timer_irq),
|
||||||
|
.i_meip (i_external_irq),
|
||||||
.i_trap (trap),
|
.i_trap (trap),
|
||||||
.o_new_irq (new_irq),
|
.o_new_irq (new_irq),
|
||||||
//Control
|
//Control
|
||||||
|
@ -580,7 +607,9 @@ module serv_top
|
||||||
.o_csr_in (csr_in),
|
.o_csr_in (csr_in),
|
||||||
.i_csr_imm (csr_imm),
|
.i_csr_imm (csr_imm),
|
||||||
.i_rs1 (rs1),
|
.i_rs1 (rs1),
|
||||||
.o_q (csr_rd));
|
.o_q (csr_rd),
|
||||||
|
.o_meie (mie_meie),
|
||||||
|
.o_mtie (mie_mtie));
|
||||||
end else begin : gen_no_csr
|
end else begin : gen_no_csr
|
||||||
assign csr_in = {W{1'b0}};
|
assign csr_in = {W{1'b0}};
|
||||||
assign csr_rd = {W{1'b0}};
|
assign csr_rd = {W{1'b0}};
|
||||||
|
|
34
serv.core
34
serv.core
|
@ -23,6 +23,7 @@ filesets:
|
||||||
- rtl/serv_rf_top.v
|
- rtl/serv_rf_top.v
|
||||||
- rtl/serv_aligner.v
|
- rtl/serv_aligner.v
|
||||||
- rtl/serv_compdec.v
|
- rtl/serv_compdec.v
|
||||||
|
- rtl/serv_sleep.v
|
||||||
file_type : verilogSource
|
file_type : verilogSource
|
||||||
|
|
||||||
openlane:
|
openlane:
|
||||||
|
@ -30,6 +31,21 @@ filesets:
|
||||||
- data/params.tcl : {file_type : tclSource}
|
- data/params.tcl : {file_type : tclSource}
|
||||||
- rtl/serv_synth_wrapper.v : {file_type : verilogSource}
|
- rtl/serv_synth_wrapper.v : {file_type : verilogSource}
|
||||||
|
|
||||||
|
verilator_decoder_tb:
|
||||||
|
files:
|
||||||
|
- bench/decoder_sim.v
|
||||||
|
- "bench/decoder_tb.cpp" : {file_type : cppSource}
|
||||||
|
file_type : verilogSource
|
||||||
|
|
||||||
|
|
||||||
|
decoder_tb:
|
||||||
|
files:
|
||||||
|
- bench/decoder_sim.v
|
||||||
|
- bench/decoder_tb.v
|
||||||
|
file_type : verilogSource
|
||||||
|
depend : [vlog_tb_utils]
|
||||||
|
|
||||||
|
|
||||||
targets:
|
targets:
|
||||||
default:
|
default:
|
||||||
filesets : [core]
|
filesets : [core]
|
||||||
|
@ -37,6 +53,7 @@ targets:
|
||||||
- "is_toplevel? (ALIGN)"
|
- "is_toplevel? (ALIGN)"
|
||||||
- "is_toplevel? (COMPRESSED)"
|
- "is_toplevel? (COMPRESSED)"
|
||||||
- "is_toplevel? (MDU)"
|
- "is_toplevel? (MDU)"
|
||||||
|
- "is_toplevel? (EI)"
|
||||||
- "is_toplevel? (PRE_REGISTER)"
|
- "is_toplevel? (PRE_REGISTER)"
|
||||||
- "is_toplevel? (RESET_STRATEGY)"
|
- "is_toplevel? (RESET_STRATEGY)"
|
||||||
- RISCV_FORMAL
|
- RISCV_FORMAL
|
||||||
|
@ -63,12 +80,29 @@ targets:
|
||||||
filesets : [core, openlane]
|
filesets : [core, openlane]
|
||||||
toplevel : serv_synth_wrapper
|
toplevel : serv_synth_wrapper
|
||||||
|
|
||||||
|
verilator_decoder_tb:
|
||||||
|
description: Verilator decoder testbench
|
||||||
|
filesets : [core, verilator_decoder_tb]
|
||||||
|
flow: sim
|
||||||
|
flow_options:
|
||||||
|
tool: verilator
|
||||||
|
verilator_options : [--trace]
|
||||||
|
parameters :
|
||||||
|
- RISCV_FORMAL
|
||||||
|
- "mdu? (MDU=1)"
|
||||||
|
toplevel : decoder_sim
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
MDU:
|
MDU:
|
||||||
datatype : int
|
datatype : int
|
||||||
description: Enables interface for RISC-V standard M-extension
|
description: Enables interface for RISC-V standard M-extension
|
||||||
paramtype : vlogparam
|
paramtype : vlogparam
|
||||||
|
|
||||||
|
EI:
|
||||||
|
datatype : int
|
||||||
|
description : Enable interface for RISC-V external interrupts
|
||||||
|
paramtype : vlogparam
|
||||||
|
|
||||||
PRE_REGISTER:
|
PRE_REGISTER:
|
||||||
datatype : int
|
datatype : int
|
||||||
description : Register signals before or after the decoder
|
description : Register signals before or after the decoder
|
||||||
|
|
141
servant.core
141
servant.core
|
@ -20,6 +20,22 @@ filesets:
|
||||||
file_type : verilogSource
|
file_type : verilogSource
|
||||||
depend : [vlog_tb_utils]
|
depend : [vlog_tb_utils]
|
||||||
|
|
||||||
|
servant_timer_tb:
|
||||||
|
files:
|
||||||
|
- sw/timer_interrupt.hex : {file_type: user, copyto: .}
|
||||||
|
- bench/servant_timer_sim.v
|
||||||
|
- bench/servant_timer_tb.v
|
||||||
|
file_type : verilogSource
|
||||||
|
depend : [vlog_tb_utils]
|
||||||
|
|
||||||
|
servant_external_tb:
|
||||||
|
files:
|
||||||
|
- sw/external_interrupt.hex : {file_type: user, copyto: .}
|
||||||
|
- bench/servant_external_sim.v
|
||||||
|
- bench/servant_external_tb.v
|
||||||
|
file_type : verilogSource
|
||||||
|
depend : [vlog_tb_utils]
|
||||||
|
|
||||||
service:
|
service:
|
||||||
files:
|
files:
|
||||||
- servant/ice40_pll.v
|
- servant/ice40_pll.v
|
||||||
|
@ -37,7 +53,13 @@ filesets:
|
||||||
- "!tool_quartus? (servant/servant_ram.v)"
|
- "!tool_quartus? (servant/servant_ram.v)"
|
||||||
- servant/servant.v
|
- servant/servant.v
|
||||||
file_type : verilogSource
|
file_type : verilogSource
|
||||||
depend : [servile, "mdu? (mdu)"]
|
depend : [servile, "mdu? (mdu)", "ei? (ei)"]
|
||||||
|
|
||||||
|
sleep_dummy:
|
||||||
|
files:
|
||||||
|
- servant/servant_sleep_dummy.v
|
||||||
|
file_type : verilogSource
|
||||||
|
depend : [servile]
|
||||||
|
|
||||||
verilator_tb:
|
verilator_tb:
|
||||||
files:
|
files:
|
||||||
|
@ -47,6 +69,18 @@ filesets:
|
||||||
file_type : verilogSource
|
file_type : verilogSource
|
||||||
depend : ["vidbo? (vidbo)"]
|
depend : ["vidbo? (vidbo)"]
|
||||||
|
|
||||||
|
verilator_timer_tb:
|
||||||
|
files:
|
||||||
|
- bench/servant_timer_sim.v
|
||||||
|
- "bench/servant_timer_tb.cpp" : {file_type : cppSource}
|
||||||
|
file_type : verilogSource
|
||||||
|
|
||||||
|
verilator_external_tb:
|
||||||
|
files:
|
||||||
|
- bench/servant_external_sim.v
|
||||||
|
- "bench/servant_external_tb.cpp" : {file_type : cppSource}
|
||||||
|
file_type : verilogSource
|
||||||
|
|
||||||
# Target-specific filesets. Alphabetically sorted
|
# Target-specific filesets. Alphabetically sorted
|
||||||
|
|
||||||
ac701:
|
ac701:
|
||||||
|
@ -96,6 +130,19 @@ filesets:
|
||||||
- servant/servant_cmod_a7.v : {file_type : verilogSource}
|
- servant/servant_cmod_a7.v : {file_type : verilogSource}
|
||||||
- data/cmod_a7_35t.xdc : {file_type : xdc}
|
- data/cmod_a7_35t.xdc : {file_type : xdc}
|
||||||
|
|
||||||
|
nexys_4:
|
||||||
|
files:
|
||||||
|
- servant/servant_nexys_4_clock_gen.v : {file_type : verilogSource}
|
||||||
|
- servant/servant_nexys_4.v : {file_type : verilogSource}
|
||||||
|
- data/nexys_4.xdc : {file_type : xdc}
|
||||||
|
|
||||||
|
nexys_a7:
|
||||||
|
files:
|
||||||
|
- servant/servant_nexys_a7_clock_gen.v : {file_type : verilogSource}
|
||||||
|
- servant/servant_nexys_a7.v : {file_type : verilogSource}
|
||||||
|
- data/nexys_a7.xdc : {file_type : xdc}
|
||||||
|
|
||||||
|
|
||||||
cyc1000:
|
cyc1000:
|
||||||
files:
|
files:
|
||||||
- data/cyc1000.sdc : {file_type : SDC}
|
- data/cyc1000.sdc : {file_type : SDC}
|
||||||
|
@ -188,11 +235,11 @@ filesets:
|
||||||
- data/nexys_2.tcl : {file_type : tclSource}
|
- data/nexys_2.tcl : {file_type : tclSource}
|
||||||
- data/nexys_2.ucf : {file_type : UCF}
|
- data/nexys_2.ucf : {file_type : UCF}
|
||||||
|
|
||||||
nexys_a7:
|
# nexys_a7:
|
||||||
files:
|
# files:
|
||||||
- servant/servix_clock_gen.v : {file_type : verilogSource}
|
# - servant/servix_clock_gen.v : {file_type : verilogSource}
|
||||||
- servant/servix.v : {file_type : verilogSource}
|
# - servant/servix.v : {file_type : verilogSource}
|
||||||
- data/nexys_a7.xdc : {file_type : xdc}
|
# - data/nexys_a7.xdc : {file_type : xdc}
|
||||||
|
|
||||||
orangecrab:
|
orangecrab:
|
||||||
files:
|
files:
|
||||||
|
@ -330,6 +377,24 @@ targets:
|
||||||
parameters : [memfile, memsize]
|
parameters : [memfile, memsize]
|
||||||
toplevel : servant_cmod_a7
|
toplevel : servant_cmod_a7
|
||||||
|
|
||||||
|
nexys_4:
|
||||||
|
description: Digilent Nexys 4
|
||||||
|
filesets : [mem_files, soc, nexys_4]
|
||||||
|
flow: vivado
|
||||||
|
flow_options:
|
||||||
|
part : xc7a100tcsg324-1
|
||||||
|
parameters : [memfile, memsize]
|
||||||
|
toplevel : servant_nexys_4
|
||||||
|
|
||||||
|
nexys_a7:
|
||||||
|
description: Digilent Nexys A7
|
||||||
|
filesets : [mem_files, soc, nexys_a7]
|
||||||
|
flow: vivado
|
||||||
|
flow_options:
|
||||||
|
part : xc7a100tcsg324-1
|
||||||
|
parameters : [memfile, memsize]
|
||||||
|
toplevel : servant_nexys_a7
|
||||||
|
|
||||||
cyc1000:
|
cyc1000:
|
||||||
default_tool: quartus
|
default_tool: quartus
|
||||||
description: cyc1000 FPGA board
|
description: cyc1000 FPGA board
|
||||||
|
@ -536,15 +601,6 @@ targets:
|
||||||
speed : -4
|
speed : -4
|
||||||
toplevel : servax
|
toplevel : servax
|
||||||
|
|
||||||
nexys_a7:
|
|
||||||
description: Digilent Nexys A7
|
|
||||||
filesets : [mem_files, soc, nexys_a7]
|
|
||||||
flow: vivado
|
|
||||||
flow_options:
|
|
||||||
part : xc7a100tcsg324-1
|
|
||||||
parameters : [memfile, memsize, frequency=32]
|
|
||||||
toplevel : servix
|
|
||||||
|
|
||||||
orangecrab_r0.2:
|
orangecrab_r0.2:
|
||||||
default_tool: trellis
|
default_tool: trellis
|
||||||
description : OrangeCrab R0.2
|
description : OrangeCrab R0.2
|
||||||
|
@ -588,6 +644,7 @@ targets:
|
||||||
- RISCV_FORMAL
|
- RISCV_FORMAL
|
||||||
- width
|
- width
|
||||||
- "mdu? (MDU=1)"
|
- "mdu? (MDU=1)"
|
||||||
|
- "ei? (EI=1)"
|
||||||
- SERV_CLEAR_RAM=true
|
- SERV_CLEAR_RAM=true
|
||||||
- firmware
|
- firmware
|
||||||
- memsize
|
- memsize
|
||||||
|
@ -656,6 +713,7 @@ targets:
|
||||||
parameters :
|
parameters :
|
||||||
- RISCV_FORMAL
|
- RISCV_FORMAL
|
||||||
- "mdu? (MDU=1)"
|
- "mdu? (MDU=1)"
|
||||||
|
- "ei? (EI=1)"
|
||||||
- cps
|
- cps
|
||||||
- firmware
|
- firmware
|
||||||
- memsize
|
- memsize
|
||||||
|
@ -671,6 +729,54 @@ targets:
|
||||||
- with_csr=1
|
- with_csr=1
|
||||||
toplevel : servant_sim
|
toplevel : servant_sim
|
||||||
|
|
||||||
|
verilator_timer_tb:
|
||||||
|
description: Verilator timer testbench
|
||||||
|
filesets : [soc, sleep_dummy, verilator_timer_tb]
|
||||||
|
flow: sim
|
||||||
|
flow_options:
|
||||||
|
tool: verilator
|
||||||
|
verilator_options : [--trace]
|
||||||
|
parameters :
|
||||||
|
- RISCV_FORMAL
|
||||||
|
- "mdu? (MDU=1)"
|
||||||
|
- cps
|
||||||
|
- firmware
|
||||||
|
- memsize
|
||||||
|
- signature
|
||||||
|
- timeout
|
||||||
|
- trace_pc
|
||||||
|
- vcd
|
||||||
|
- vcd_start
|
||||||
|
- width
|
||||||
|
- compressed
|
||||||
|
- align
|
||||||
|
- with_csr=1
|
||||||
|
toplevel : servant_timer_sim
|
||||||
|
|
||||||
|
verilator_external_tb:
|
||||||
|
description: Verilator timer testbench
|
||||||
|
filesets : [soc, sleep_dummy, verilator_external_tb]
|
||||||
|
flow: sim
|
||||||
|
flow_options:
|
||||||
|
tool: verilator
|
||||||
|
verilator_options : [--trace]
|
||||||
|
parameters :
|
||||||
|
- RISCV_FORMAL
|
||||||
|
- "mdu? (MDU=1)"
|
||||||
|
- cps
|
||||||
|
- firmware
|
||||||
|
- memsize
|
||||||
|
- signature
|
||||||
|
- timeout
|
||||||
|
- trace_pc
|
||||||
|
- vcd
|
||||||
|
- vcd_start
|
||||||
|
- width
|
||||||
|
- compressed
|
||||||
|
- align
|
||||||
|
- with_csr=1
|
||||||
|
toplevel : servant_external_sim
|
||||||
|
|
||||||
zcu106:
|
zcu106:
|
||||||
default_tool: vivado
|
default_tool: vivado
|
||||||
description : Zynq UltraScale+ MPSoC ZCU106 Evaluation Kit
|
description : Zynq UltraScale+ MPSoC ZCU106 Evaluation Kit
|
||||||
|
@ -711,6 +817,11 @@ parameters:
|
||||||
description : Enables RISC-V standard M-extension
|
description : Enables RISC-V standard M-extension
|
||||||
paramtype : vlogdefine
|
paramtype : vlogdefine
|
||||||
|
|
||||||
|
EI:
|
||||||
|
datatype : int
|
||||||
|
description : Enable interface for RISC-V external interrupts
|
||||||
|
paramtype : vlogdefine
|
||||||
|
|
||||||
memfile:
|
memfile:
|
||||||
datatype : file
|
datatype : file
|
||||||
description : Preload RAM with a hex file at compile-time
|
description : Preload RAM with a hex file at compile-time
|
||||||
|
|
|
@ -2,8 +2,11 @@
|
||||||
module servant
|
module servant
|
||||||
(
|
(
|
||||||
input wire wb_clk,
|
input wire wb_clk,
|
||||||
|
input wire main_clk,
|
||||||
input wire wb_rst,
|
input wire wb_rst,
|
||||||
output wire q);
|
input wire ext_irq,
|
||||||
|
output wire q,
|
||||||
|
output reg o_sleep);
|
||||||
|
|
||||||
parameter memfile = "zephyr_hello.hex";
|
parameter memfile = "zephyr_hello.hex";
|
||||||
parameter memsize = 8192;
|
parameter memsize = 8192;
|
||||||
|
@ -22,6 +25,12 @@ module servant
|
||||||
localparam [0:0] with_mdu = 1'b0;
|
localparam [0:0] with_mdu = 1'b0;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
`ifdef EI
|
||||||
|
localparam [0:0] with_ei = 1'b1;
|
||||||
|
`else
|
||||||
|
localparam [0:0] with_ei = 1'b0;
|
||||||
|
`endif
|
||||||
|
|
||||||
localparam aw = $clog2(memsize);
|
localparam aw = $clog2(memsize);
|
||||||
localparam csr_regs = with_csr*4;
|
localparam csr_regs = with_csr*4;
|
||||||
|
|
||||||
|
@ -63,6 +72,8 @@ module servant
|
||||||
wire [rf_l2d-1:0] rf_raddr;
|
wire [rf_l2d-1:0] rf_raddr;
|
||||||
wire rf_ren;
|
wire rf_ren;
|
||||||
wire [rf_width-1:0] rf_rdata;
|
wire [rf_width-1:0] rf_rdata;
|
||||||
|
wire sleep_req;
|
||||||
|
wire wakeup_req;
|
||||||
|
|
||||||
servant_mux servant_mux
|
servant_mux servant_mux
|
||||||
(
|
(
|
||||||
|
@ -106,7 +117,7 @@ module servant
|
||||||
#(.RESET_STRATEGY (reset_strategy),
|
#(.RESET_STRATEGY (reset_strategy),
|
||||||
.WIDTH (32))
|
.WIDTH (32))
|
||||||
timer
|
timer
|
||||||
(.i_clk (wb_clk),
|
(.i_clk (main_clk),
|
||||||
.i_rst (wb_rst),
|
.i_rst (wb_rst),
|
||||||
.o_irq (timer_irq),
|
.o_irq (timer_irq),
|
||||||
.i_wb_cyc (wb_timer_stb),
|
.i_wb_cyc (wb_timer_stb),
|
||||||
|
@ -140,12 +151,16 @@ module servant
|
||||||
.debug (debug),
|
.debug (debug),
|
||||||
.with_c (compress[0]),
|
.with_c (compress[0]),
|
||||||
.with_csr (with_csr[0]),
|
.with_csr (with_csr[0]),
|
||||||
.with_mdu (with_mdu))
|
.with_mdu (with_mdu),
|
||||||
|
.with_ei (with_ei))
|
||||||
cpu
|
cpu
|
||||||
(
|
(
|
||||||
.i_clk (wb_clk),
|
.i_clk (wb_clk),
|
||||||
.i_rst (wb_rst),
|
.i_rst (wb_rst),
|
||||||
.i_timer_irq (timer_irq),
|
.i_timer_irq (timer_irq),
|
||||||
|
.i_external_irq (ext_irq),
|
||||||
|
.o_wakeup_req (wakeup_req),
|
||||||
|
.o_sleep_req (sleep_req),
|
||||||
|
|
||||||
.o_wb_mem_adr (wb_mem_adr),
|
.o_wb_mem_adr (wb_mem_adr),
|
||||||
.o_wb_mem_dat (wb_mem_dat),
|
.o_wb_mem_dat (wb_mem_dat),
|
||||||
|
@ -170,4 +185,13 @@ module servant
|
||||||
.o_rf_ren (rf_ren),
|
.o_rf_ren (rf_ren),
|
||||||
.i_rf_rdata (rf_rdata));
|
.i_rf_rdata (rf_rdata));
|
||||||
|
|
||||||
|
always @(posedge main_clk) begin
|
||||||
|
if (sleep_req)
|
||||||
|
o_sleep <= 1;
|
||||||
|
if (wakeup_req)
|
||||||
|
o_sleep <= 0;
|
||||||
|
if (wb_rst)
|
||||||
|
o_sleep <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
53
servant/servant_nexys_4.v
Normal file
53
servant/servant_nexys_4.v
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
`default_nettype none
|
||||||
|
module servant_nexys_4
|
||||||
|
(
|
||||||
|
input wire i_clk,
|
||||||
|
input wire i_rst,
|
||||||
|
input wire ext_irq,
|
||||||
|
output wire o_uart_tx,
|
||||||
|
output wire q);
|
||||||
|
|
||||||
|
parameter memfile = "zephyr_hello.hex";
|
||||||
|
parameter memsize = 8192;
|
||||||
|
|
||||||
|
wire main_clk;
|
||||||
|
wire wb_clk;
|
||||||
|
wire wb_rst;
|
||||||
|
|
||||||
|
wire sleep_req;
|
||||||
|
wire wakeup_req;
|
||||||
|
|
||||||
|
reg sleep;
|
||||||
|
|
||||||
|
always @(posedge main_clk) begin
|
||||||
|
if (sleep_req)
|
||||||
|
sleep <= 0;
|
||||||
|
if (wakeup_req)
|
||||||
|
sleep <= 1;
|
||||||
|
if (wb_rst)
|
||||||
|
sleep <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
assign o_uart_tx = q;
|
||||||
|
|
||||||
|
servant_nexys_4_clock_gen
|
||||||
|
clock_gen
|
||||||
|
(.i_clk (i_clk),
|
||||||
|
.i_rst (i_rst),
|
||||||
|
.i_clk0_en (sleep),
|
||||||
|
.i_clk1_en (1),
|
||||||
|
.o_clk0 (main_clk),
|
||||||
|
.o_clk1 (wb_clk),
|
||||||
|
.o_rst (wb_rst));
|
||||||
|
servant
|
||||||
|
#(.memfile (memfile),
|
||||||
|
.memsize (memsize))
|
||||||
|
servant
|
||||||
|
(.wb_clk (wb_clk),
|
||||||
|
.wb_rst (wb_rst),
|
||||||
|
.q (q),
|
||||||
|
.o_sleep_req (sleep_req),
|
||||||
|
.o_wakeup_req (wakeup_req));
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
`default_nettype wire
|
54
servant/servant_nexys_4_clock_gen.v
Normal file
54
servant/servant_nexys_4_clock_gen.v
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
`default_nettype none
|
||||||
|
module servant_nexys_4_clock_gen
|
||||||
|
(input wire i_clk,
|
||||||
|
input wire i_rst,
|
||||||
|
input wire i_clk0_en,
|
||||||
|
input wire i_clk1_en,
|
||||||
|
output wire o_clk0,
|
||||||
|
output wire o_clk1,
|
||||||
|
output reg o_rst);
|
||||||
|
|
||||||
|
wire clkfb;
|
||||||
|
wire locked;
|
||||||
|
wire pll_rst;
|
||||||
|
wire pll_clk;
|
||||||
|
reg locked_r;
|
||||||
|
|
||||||
|
assign pll_rst = !i_rst;
|
||||||
|
|
||||||
|
MMCME2_BASE
|
||||||
|
#(.CLKIN1_PERIOD (10), //100MHz
|
||||||
|
|
||||||
|
/* Set VCO frequency to 100*8.0=800 MHz
|
||||||
|
Allowed values are 2.0 to 64.0. Resulting VCO freq
|
||||||
|
needs to be 600-1200MHz */
|
||||||
|
.CLKFBOUT_MULT_F (8.000),
|
||||||
|
|
||||||
|
.CLKOUT0_DIVIDE_F (25.000)) // 800/25 = 32 MHz
|
||||||
|
pll
|
||||||
|
(.CLKIN1 (i_clk),
|
||||||
|
.RST (pll_rst),
|
||||||
|
.CLKOUT0 (pll_clk),
|
||||||
|
.LOCKED (locked),
|
||||||
|
.CLKFBOUT (clkfb),
|
||||||
|
.CLKFBIN (clkfb));
|
||||||
|
|
||||||
|
always @(posedge pll_clk) begin
|
||||||
|
locked_r <= locked;
|
||||||
|
o_rst <= !locked_r;
|
||||||
|
end
|
||||||
|
|
||||||
|
BUFGCE clk0_buf
|
||||||
|
(
|
||||||
|
.I (pll_clk),
|
||||||
|
.O (o_clk0),
|
||||||
|
.CE (i_clk0_en));
|
||||||
|
|
||||||
|
BUFGCE clk1_buf
|
||||||
|
(
|
||||||
|
.I (pll_clk),
|
||||||
|
.O (o_clk1),
|
||||||
|
.CE (i_clk0_en));
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
`default_nettype wire
|
42
servant/servant_nexys_a7.v
Normal file
42
servant/servant_nexys_a7.v
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
`default_nettype none
|
||||||
|
module servant_nexys_a7
|
||||||
|
(
|
||||||
|
input wire i_clk,
|
||||||
|
input wire i_rst,
|
||||||
|
input wire ext_irq,
|
||||||
|
output wire o_uart_tx,
|
||||||
|
output wire q);
|
||||||
|
|
||||||
|
parameter memfile = "zephyr_hello.hex";
|
||||||
|
parameter memsize = 8192;
|
||||||
|
|
||||||
|
wire main_clk;
|
||||||
|
wire wb_clk;
|
||||||
|
wire wb_rst;
|
||||||
|
wire sleep;
|
||||||
|
|
||||||
|
assign o_uart_tx = q;
|
||||||
|
|
||||||
|
servant_nexys_a7_clock_gen
|
||||||
|
clock_gen
|
||||||
|
(.i_clk (i_clk),
|
||||||
|
.i_rst (i_rst),
|
||||||
|
.i_clk0_en (1),
|
||||||
|
.i_clk1_en (!sleep),
|
||||||
|
.o_clk0 (main_clk),
|
||||||
|
.o_clk1 (wb_clk),
|
||||||
|
.o_rst (wb_rst));
|
||||||
|
|
||||||
|
servant
|
||||||
|
#(.memfile (memfile),
|
||||||
|
.memsize (memsize))
|
||||||
|
servant
|
||||||
|
(.wb_clk (wb_clk),
|
||||||
|
.main_clk (main_clk),
|
||||||
|
.wb_rst (wb_rst),
|
||||||
|
.q (q),
|
||||||
|
.ext_irq (ext_irq),
|
||||||
|
.o_sleep (sleep));
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
`default_nettype wire
|
57
servant/servant_nexys_a7_clock_gen.v
Normal file
57
servant/servant_nexys_a7_clock_gen.v
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
`default_nettype none
|
||||||
|
module servant_nexys_a7_clock_gen
|
||||||
|
(input wire i_clk,
|
||||||
|
input wire i_rst,
|
||||||
|
input wire i_clk0_en,
|
||||||
|
input wire i_clk1_en,
|
||||||
|
output wire o_clk0,
|
||||||
|
output wire o_clk1,
|
||||||
|
output reg o_rst);
|
||||||
|
|
||||||
|
wire clkfb;
|
||||||
|
wire locked;
|
||||||
|
wire pll_rst;
|
||||||
|
wire pll_clk;
|
||||||
|
reg locked_r;
|
||||||
|
|
||||||
|
assign pll_rst = !i_rst;
|
||||||
|
|
||||||
|
MMCME2_BASE
|
||||||
|
#(.CLKIN1_PERIOD (10), //100MHz
|
||||||
|
|
||||||
|
/* Set VCO frequency to 100*8.0=800 MHz
|
||||||
|
Allowed values are 2.0 to 64.0. Resulting VCO freq
|
||||||
|
needs to be 600-1200MHz */
|
||||||
|
.CLKFBOUT_MULT_F (6.000),
|
||||||
|
|
||||||
|
.CLKOUT0_DIVIDE_F (64.000)) // 800/25 = 32 MHz
|
||||||
|
pll
|
||||||
|
(.CLKIN1 (i_clk),
|
||||||
|
.RST (pll_rst),
|
||||||
|
.CLKOUT0 (pll_clk),
|
||||||
|
.LOCKED (locked),
|
||||||
|
.CLKFBOUT (clkfb),
|
||||||
|
.CLKFBIN (clkfb));
|
||||||
|
|
||||||
|
always @(posedge pll_clk) begin
|
||||||
|
locked_r <= locked;
|
||||||
|
o_rst <= !locked_r;
|
||||||
|
end
|
||||||
|
|
||||||
|
BUFGCE clk0_buf
|
||||||
|
(
|
||||||
|
.I (pll_clk),
|
||||||
|
.O (o_clk0),
|
||||||
|
.CE (i_clk0_en));
|
||||||
|
|
||||||
|
BUFGCE clk1_buf
|
||||||
|
(
|
||||||
|
.I (pll_clk),
|
||||||
|
.O (o_clk1),
|
||||||
|
.CE (i_clk1_en));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
`default_nettype wire
|
47
servant/servant_sleep_dummy.v
Normal file
47
servant/servant_sleep_dummy.v
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
`default_nettype none
|
||||||
|
module servant_sleep_dummy
|
||||||
|
(
|
||||||
|
input wire i_clk,
|
||||||
|
input wire i_rst,
|
||||||
|
input wire ext_irq,
|
||||||
|
output wire q);
|
||||||
|
|
||||||
|
parameter memfile = "zephyr_hello.hex";
|
||||||
|
parameter memsize = 8192;
|
||||||
|
parameter reset_strategy = "MINI";
|
||||||
|
parameter width = 1;
|
||||||
|
parameter sim = 0;
|
||||||
|
parameter [0:0] debug = 1'b0;
|
||||||
|
parameter with_csr = 1;
|
||||||
|
parameter [0:0] compress = 0;
|
||||||
|
parameter [0:0] align = compress;
|
||||||
|
|
||||||
|
|
||||||
|
wire sleep;
|
||||||
|
wire wb_clk;
|
||||||
|
wire sleep_req;
|
||||||
|
wire wakeup_req;
|
||||||
|
|
||||||
|
assign wb_clk = i_clk & !sleep;
|
||||||
|
|
||||||
|
servant #(
|
||||||
|
.memfile(memfile),
|
||||||
|
.memsize(memsize),
|
||||||
|
.reset_strategy(reset_strategy),
|
||||||
|
.width(width),
|
||||||
|
.sim(sim),
|
||||||
|
.debug(debug),
|
||||||
|
.with_csr(with_csr),
|
||||||
|
.compress(compress),
|
||||||
|
.align(align)
|
||||||
|
)
|
||||||
|
servant (
|
||||||
|
.wb_clk (wb_clk),
|
||||||
|
.main_clk (i_clk),
|
||||||
|
.wb_rst (i_rst),
|
||||||
|
.ext_irq (ext_irq),
|
||||||
|
.q (q),
|
||||||
|
.o_sleep (sleep));
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
`default_nettype wire
|
|
@ -16,6 +16,7 @@ module servile
|
||||||
parameter [0:0] debug = 1'b0,
|
parameter [0:0] debug = 1'b0,
|
||||||
parameter [0:0] with_c = 1'b0,
|
parameter [0:0] with_c = 1'b0,
|
||||||
parameter [0:0] with_csr = 1'b0,
|
parameter [0:0] with_csr = 1'b0,
|
||||||
|
parameter [0:0] with_ei = 1'b0,
|
||||||
parameter [0:0] with_mdu = 1'b0,
|
parameter [0:0] with_mdu = 1'b0,
|
||||||
//Internally calculated. Do not touch
|
//Internally calculated. Do not touch
|
||||||
parameter B = width-1,
|
parameter B = width-1,
|
||||||
|
@ -25,6 +26,10 @@ module servile
|
||||||
input wire i_clk,
|
input wire i_clk,
|
||||||
input wire i_rst,
|
input wire i_rst,
|
||||||
input wire i_timer_irq,
|
input wire i_timer_irq,
|
||||||
|
input wire i_external_irq,
|
||||||
|
|
||||||
|
output wire o_sleep_req,
|
||||||
|
output wire o_wakeup_req,
|
||||||
|
|
||||||
//Memory (WB) interface
|
//Memory (WB) interface
|
||||||
output wire [31:0] o_wb_mem_adr,
|
output wire [31:0] o_wb_mem_adr,
|
||||||
|
@ -96,6 +101,8 @@ module servile
|
||||||
wire [31:0] mdu_rd;
|
wire [31:0] mdu_rd;
|
||||||
wire mdu_ready;
|
wire mdu_ready;
|
||||||
|
|
||||||
|
wire ei_irq;
|
||||||
|
|
||||||
servile_mux
|
servile_mux
|
||||||
#(.sim (sim))
|
#(.sim (sim))
|
||||||
mux
|
mux
|
||||||
|
@ -194,7 +201,16 @@ module servile
|
||||||
end else begin
|
end else begin
|
||||||
assign mdu_ready = 1'b0;
|
assign mdu_ready = 1'b0;
|
||||||
assign mdu_rd = 32'd0;
|
assign mdu_rd = 32'd0;
|
||||||
end
|
end // else: !if(with_mdu)
|
||||||
|
|
||||||
|
if (with_ei) begin : gen_ei
|
||||||
|
ei_top ei_serv
|
||||||
|
(.i_clk (i_clk),
|
||||||
|
.i_rst (i_rst),
|
||||||
|
.o_eirq (ei_irq));
|
||||||
|
end else begin
|
||||||
|
assign ei_irq = 1'b0;
|
||||||
|
end // else !if(with_ei)
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
serv_top
|
serv_top
|
||||||
|
@ -206,12 +222,15 @@ module servile
|
||||||
.RESET_PC (reset_pc),
|
.RESET_PC (reset_pc),
|
||||||
.DEBUG (debug),
|
.DEBUG (debug),
|
||||||
.MDU (with_mdu),
|
.MDU (with_mdu),
|
||||||
|
.EI (with_ei),
|
||||||
.COMPRESSED (with_c))
|
.COMPRESSED (with_c))
|
||||||
cpu
|
cpu
|
||||||
(
|
(
|
||||||
.clk (i_clk),
|
.clk (i_clk),
|
||||||
.i_rst (i_rst),
|
.i_rst (i_rst),
|
||||||
.i_timer_irq (i_timer_irq),
|
.i_timer_irq (i_timer_irq),
|
||||||
|
.i_external_irq (i_external_irq),
|
||||||
|
|
||||||
|
|
||||||
`ifdef RISCV_FORMAL
|
`ifdef RISCV_FORMAL
|
||||||
.rvfi_valid (),
|
.rvfi_valid (),
|
||||||
|
@ -266,6 +285,10 @@ module servile
|
||||||
.i_dbus_rdt (wb_dbus_rdt),
|
.i_dbus_rdt (wb_dbus_rdt),
|
||||||
.i_dbus_ack (wb_dbus_ack),
|
.i_dbus_ack (wb_dbus_ack),
|
||||||
|
|
||||||
|
// Sleep
|
||||||
|
.o_sleep_req (o_sleep_req),
|
||||||
|
.o_wakeup_req (o_wakeup_req),
|
||||||
|
|
||||||
//Extension IF
|
//Extension IF
|
||||||
.o_ext_rs1 (mdu_rs1),
|
.o_ext_rs1 (mdu_rs1),
|
||||||
.o_ext_rs2 (mdu_rs2),
|
.o_ext_rs2 (mdu_rs2),
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
TOOLCHAIN_PREFIX?=riscv64-unknown-elf-
|
TOOLCHAIN_PREFIX?=riscv64-unknown-elf-
|
||||||
|
CC?=$(TOOLCHAIN_PREFIX)gcc
|
||||||
|
OBJCOPY=$(TOOLCHAIN_PREFIX)objcopy
|
||||||
|
|
||||||
%.elf: %.S link.ld
|
%.elf: %.S link.ld
|
||||||
$(TOOLCHAIN_PREFIX)gcc -nostartfiles -nostdlib -march=rv32i_zicsr -mabi=ilp32 -Tlink.ld -o$@ $<
|
$(CC) -nostartfiles -nostdlib -march=rv32i_zicsr -mabi=ilp32 -Tlink.ld -o$@ $<
|
||||||
%.bin: %.elf
|
%.bin: %.elf
|
||||||
$(TOOLCHAIN_PREFIX)objcopy -O binary $< $@
|
$(OBJCOPY) -O binary $< $@
|
||||||
%.hex: %.bin
|
%.hex: %.bin
|
||||||
python3 makehex.py $< > $@
|
python3 makehex.py $< > $@
|
||||||
|
|
||||||
|
|
18
sw/external_interrupt.S
Normal file
18
sw/external_interrupt.S
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
.section .text
|
||||||
|
.global _start
|
||||||
|
.global handler
|
||||||
|
_start:
|
||||||
|
la t0, handler
|
||||||
|
csrw mtvec, t0
|
||||||
|
li t0, 0x8
|
||||||
|
csrrs x0, mstatus, t0
|
||||||
|
li t0, 0x800
|
||||||
|
csrrs x0, mie, t0
|
||||||
|
loop:
|
||||||
|
j loop
|
||||||
|
handler:
|
||||||
|
li t0, 0x8
|
||||||
|
csrrc x0, mstatus, t0
|
||||||
|
li t0, 0x800
|
||||||
|
csrrc x0, mie, t0
|
||||||
|
mret
|
16
sw/external_interrupt.hex
Normal file
16
sw/external_interrupt.hex
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
00000297
|
||||||
|
02428293
|
||||||
|
30529073
|
||||||
|
00800293
|
||||||
|
3002A073
|
||||||
|
00100293
|
||||||
|
00B29293
|
||||||
|
3042A073
|
||||||
|
0000006F
|
||||||
|
00800293
|
||||||
|
3002B073
|
||||||
|
00100293
|
||||||
|
00B29293
|
||||||
|
3042B073
|
||||||
|
30200073
|
||||||
|
00000000
|
17
sw/external_interrupt_wfi.S
Normal file
17
sw/external_interrupt_wfi.S
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
.section .text
|
||||||
|
.global _start
|
||||||
|
.global handler
|
||||||
|
_start:
|
||||||
|
la t0, handler
|
||||||
|
csrw mtvec, t0
|
||||||
|
li t0, 0x8
|
||||||
|
csrrs x0, mstatus, t0
|
||||||
|
li t0, 0x800
|
||||||
|
csrrs x0, mie, t0
|
||||||
|
wfi
|
||||||
|
handler:
|
||||||
|
li t0, 0x8
|
||||||
|
csrrc x0, mstatus, t0
|
||||||
|
li t0, 0x800
|
||||||
|
csrrc x0, mie, t0
|
||||||
|
mret
|
16
sw/external_interrupt_wfi.hex
Normal file
16
sw/external_interrupt_wfi.hex
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
00000297
|
||||||
|
02428293
|
||||||
|
30529073
|
||||||
|
00800293
|
||||||
|
3002A073
|
||||||
|
00100293
|
||||||
|
00B29293
|
||||||
|
3042A073
|
||||||
|
10500073
|
||||||
|
00800293
|
||||||
|
3002B073
|
||||||
|
00100293
|
||||||
|
00B29293
|
||||||
|
3042B073
|
||||||
|
30200073
|
||||||
|
00000000
|
22
sw/timer_interrupt.S
Normal file
22
sw/timer_interrupt.S
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
.section .text
|
||||||
|
.global _start
|
||||||
|
.global handler
|
||||||
|
.equ DELAY, 1500
|
||||||
|
_start:
|
||||||
|
la t0, handler
|
||||||
|
csrw mtvec, t0
|
||||||
|
li t0, 0x80000000
|
||||||
|
li t1, DELAY
|
||||||
|
sw t1, 0(t0)
|
||||||
|
li t0, 0x8
|
||||||
|
csrrs x0, mstatus, t0
|
||||||
|
li t0, 0x80
|
||||||
|
csrrs x0, mie, t0
|
||||||
|
wait:
|
||||||
|
j wait
|
||||||
|
handler:
|
||||||
|
li t0, 0x8
|
||||||
|
csrrc x0, mstatus, t0
|
||||||
|
li t0, 0x80
|
||||||
|
csrrc x0, mie, t0
|
||||||
|
mret
|
17
sw/timer_interrupt.hex
Normal file
17
sw/timer_interrupt.hex
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
00000297
|
||||||
|
02C28293
|
||||||
|
30529073
|
||||||
|
800002B7
|
||||||
|
5DC00313
|
||||||
|
0062A023
|
||||||
|
00800293
|
||||||
|
3002A073
|
||||||
|
08000293
|
||||||
|
3042A073
|
||||||
|
0000006F
|
||||||
|
00800293
|
||||||
|
3002B073
|
||||||
|
08000293
|
||||||
|
3042B073
|
||||||
|
30200073
|
||||||
|
00000000
|
17
sw/timer_interrupt_wfi.hex
Normal file
17
sw/timer_interrupt_wfi.hex
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
00000297
|
||||||
|
02C28293
|
||||||
|
30529073
|
||||||
|
800002B7
|
||||||
|
5DC00313
|
||||||
|
0062A023
|
||||||
|
00800293
|
||||||
|
3002A073
|
||||||
|
08000293
|
||||||
|
3042A073
|
||||||
|
10500073
|
||||||
|
00800293
|
||||||
|
3002B073
|
||||||
|
08000293
|
||||||
|
3042B073
|
||||||
|
30200073
|
||||||
|
00000000
|
29
sw/timer_interrupt_wfi_recurring.S
Normal file
29
sw/timer_interrupt_wfi_recurring.S
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
.section .text
|
||||||
|
.global _start
|
||||||
|
.global handler
|
||||||
|
.equ DELAY, 8000
|
||||||
|
_start:
|
||||||
|
la t0, handler
|
||||||
|
csrw mtvec, t0
|
||||||
|
|
||||||
|
li t0, 0x80000000
|
||||||
|
li s2, DELAY
|
||||||
|
sw s2, 0(t0)
|
||||||
|
|
||||||
|
li t0, 0x8
|
||||||
|
csrrs x0, mstatus, t0
|
||||||
|
li t0, 0x80
|
||||||
|
csrrs x0, mie, t0
|
||||||
|
wait:
|
||||||
|
wfi
|
||||||
|
j wait
|
||||||
|
|
||||||
|
handler:
|
||||||
|
|
||||||
|
li t1, DELAY
|
||||||
|
add s2, t1, s2
|
||||||
|
|
||||||
|
li t0, 0x80000000
|
||||||
|
sw s2, 0(t0)
|
||||||
|
|
||||||
|
mret
|
Loading…
Add table
Add a link
Reference in a new issue