mirror of
https://github.com/olofk/serv.git
synced 2026-01-11 23:42:50 +00:00
csr, verilator, traps
This commit is contained in:
parent
c33d97d80f
commit
a92c933af1
57
bench/serv_soc_tb.cpp
Normal file
57
bench/serv_soc_tb.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "verilated_vcd_c.h"
|
||||
#include "Vserv_wrapper.h"
|
||||
|
||||
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)
|
||||
{
|
||||
uint32_t insn = 0;
|
||||
uint32_t ex_pc = 0;
|
||||
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
Vserv_wrapper* top = new Vserv_wrapper;
|
||||
|
||||
//const char *vcd = Verilated::commandArgsPlusMatch("vcd=");
|
||||
//if (vcd[0]) == '\0' || atoi(arg + 11) != 0)
|
||||
Verilated::traceEverOn(true);
|
||||
VerilatedVcdC* tfp = new VerilatedVcdC;
|
||||
top->trace (tfp, 99);
|
||||
tfp->open ("trace.vcd");
|
||||
|
||||
signal(SIGINT, INThandler);
|
||||
|
||||
top->wb_clk = 1;
|
||||
top->wb_rst = 1;
|
||||
|
||||
while (!(done || Verilated::gotFinish())) {
|
||||
top->eval();
|
||||
tfp->dump(main_time);
|
||||
top->wb_clk = !top->wb_clk;
|
||||
main_time+=5;
|
||||
if (main_time > 100)
|
||||
top->wb_rst = false;
|
||||
}
|
||||
tfp->close();
|
||||
exit(0);
|
||||
}
|
||||
@ -1,73 +1,16 @@
|
||||
`default_nettype none
|
||||
module serv_top_tb;
|
||||
|
||||
reg clk = 1'b1;
|
||||
parameter firmware = "firmware.hex";
|
||||
|
||||
reg wb_clk = 1'b1;
|
||||
reg wb_rst = 1'b1;
|
||||
|
||||
reg [1023:0] firmware_file;
|
||||
|
||||
wire wb_clk = clk;
|
||||
|
||||
always #5 clk <= !clk;
|
||||
always #5 wb_clk <= !wb_clk;
|
||||
initial #100 wb_rst = 1'b0;
|
||||
|
||||
`include "wb_intercon.vh"
|
||||
|
||||
localparam MEMORY_SIZE = 16384*4;
|
||||
|
||||
wb_ram
|
||||
#(.memfile ("firmware.hex"),
|
||||
.depth (MEMORY_SIZE))
|
||||
ram
|
||||
(// Wishbone interface
|
||||
.wb_clk_i (clk),
|
||||
.wb_rst_i (wb_rst),
|
||||
.wb_adr_i (wb_m2s_mem_adr[$clog2(MEMORY_SIZE)-1:0]),
|
||||
.wb_stb_i (wb_m2s_mem_stb),
|
||||
.wb_cyc_i (wb_m2s_mem_cyc),
|
||||
.wb_cti_i (wb_m2s_mem_cti),
|
||||
.wb_bte_i (wb_m2s_mem_bte),
|
||||
.wb_we_i (wb_m2s_mem_we) ,
|
||||
.wb_sel_i (wb_m2s_mem_sel),
|
||||
.wb_dat_i (wb_m2s_mem_dat),
|
||||
.wb_dat_o (wb_s2m_mem_dat),
|
||||
.wb_ack_o (wb_s2m_mem_ack),
|
||||
.wb_err_o ());
|
||||
|
||||
vlog_tb_utils vtu();
|
||||
|
||||
testprint testprint
|
||||
(
|
||||
.i_wb_clk (clk),
|
||||
.i_wb_dat (wb_m2s_testprint_dat),
|
||||
.i_wb_we (wb_m2s_testprint_we),
|
||||
.i_wb_cyc (wb_m2s_testprint_cyc),
|
||||
.i_wb_stb (wb_m2s_testprint_stb),
|
||||
.o_wb_ack (wb_s2m_testprint_ack));
|
||||
serv_wrapper #(firmware) dut(wb_clk, wb_rst);
|
||||
|
||||
serv_top
|
||||
#(.RESET_PC (32'd8))
|
||||
dut
|
||||
(
|
||||
.clk (clk),
|
||||
.o_ibus_adr (wb_m2s_cpu_ibus_adr),
|
||||
.o_ibus_cyc (wb_m2s_cpu_ibus_cyc),
|
||||
.o_ibus_stb (wb_m2s_cpu_ibus_stb),
|
||||
.i_ibus_rdt (wb_s2m_cpu_ibus_dat),
|
||||
.i_ibus_ack (wb_s2m_cpu_ibus_ack),
|
||||
.o_dbus_adr (wb_m2s_cpu_dbus_adr),
|
||||
.o_dbus_dat (wb_m2s_cpu_dbus_dat),
|
||||
.o_dbus_sel (wb_m2s_cpu_dbus_sel),
|
||||
.o_dbus_we (wb_m2s_cpu_dbus_we),
|
||||
.o_dbus_cyc (wb_m2s_cpu_dbus_cyc),
|
||||
.o_dbus_stb (wb_m2s_cpu_dbus_stb),
|
||||
.i_dbus_rdt (wb_s2m_cpu_dbus_dat),
|
||||
.i_dbus_ack (wb_s2m_cpu_dbus_ack));
|
||||
|
||||
assign wb_m2s_cpu_ibus_dat = 32'd0;
|
||||
assign wb_m2s_cpu_ibus_we = 1'b0;
|
||||
assign wb_m2s_cpu_ibus_sel = 4'b1111;
|
||||
assign wb_m2s_cpu_ibus_cti = 3'b000;
|
||||
assign wb_m2s_cpu_ibus_bte = 2'b00;
|
||||
|
||||
endmodule
|
||||
|
||||
97
bench/serv_wrapper.v
Normal file
97
bench/serv_wrapper.v
Normal file
@ -0,0 +1,97 @@
|
||||
`default_nettype none
|
||||
module serv_wrapper
|
||||
(
|
||||
input wb_clk,
|
||||
input wb_rst);
|
||||
|
||||
parameter firmware = "firmware.hex";
|
||||
|
||||
wire timer_irq;
|
||||
|
||||
`include "wb_intercon.vh"
|
||||
|
||||
localparam MEMORY_SIZE = 16384*4;
|
||||
|
||||
reg [1023:0] firmware_file;
|
||||
initial
|
||||
if ($value$plusargs("firmware=%s", firmware_file)) begin
|
||||
$display("Loading RAM from %0s", firmware_file);
|
||||
$readmemh(firmware_file, ram.ram0.mem);
|
||||
end
|
||||
|
||||
|
||||
wb_ram
|
||||
#(/*.memfile (firmware),*/
|
||||
.depth (MEMORY_SIZE))
|
||||
ram
|
||||
(// Wishbone interface
|
||||
.wb_clk_i (wb_clk),
|
||||
.wb_rst_i (wb_rst),
|
||||
.wb_adr_i (wb_m2s_mem_adr[$clog2(MEMORY_SIZE)-1:0]),
|
||||
.wb_stb_i (wb_m2s_mem_stb),
|
||||
.wb_cyc_i (wb_m2s_mem_cyc),
|
||||
.wb_cti_i (wb_m2s_mem_cti),
|
||||
.wb_bte_i (wb_m2s_mem_bte),
|
||||
.wb_we_i (wb_m2s_mem_we) ,
|
||||
.wb_sel_i (wb_m2s_mem_sel),
|
||||
.wb_dat_i (wb_m2s_mem_dat),
|
||||
.wb_dat_o (wb_s2m_mem_dat),
|
||||
.wb_ack_o (wb_s2m_mem_ack),
|
||||
.wb_err_o ());
|
||||
|
||||
testprint testprint
|
||||
(
|
||||
.i_wb_clk (wb_clk),
|
||||
.i_wb_dat (wb_m2s_testprint_dat),
|
||||
.i_wb_we (wb_m2s_testprint_we),
|
||||
.i_wb_cyc (wb_m2s_testprint_cyc),
|
||||
.i_wb_stb (wb_m2s_testprint_stb),
|
||||
.o_wb_ack (wb_s2m_testprint_ack));
|
||||
|
||||
testhalt testhalt
|
||||
(
|
||||
.i_wb_clk (wb_clk),
|
||||
.i_wb_dat (wb_m2s_testhalt_dat),
|
||||
.i_wb_we (wb_m2s_testhalt_we),
|
||||
.i_wb_cyc (wb_m2s_testhalt_cyc),
|
||||
.i_wb_stb (wb_m2s_testhalt_stb),
|
||||
.o_wb_ack (wb_s2m_testhalt_ack));
|
||||
|
||||
riscv_timer riscv_timer
|
||||
(.i_clk (wb_clk),
|
||||
.o_irq (timer_irq),
|
||||
.i_wb_adr (wb_m2s_timer_adr),
|
||||
.i_wb_stb (wb_m2s_timer_stb),
|
||||
.i_wb_cyc (wb_m2s_timer_cyc),
|
||||
.i_wb_we (wb_m2s_timer_we) ,
|
||||
.i_wb_sel (wb_m2s_timer_sel),
|
||||
.i_wb_dat (wb_m2s_timer_dat),
|
||||
.o_wb_dat (wb_s2m_timer_dat),
|
||||
.o_wb_ack (wb_s2m_timer_ack));
|
||||
|
||||
serv_top
|
||||
#(.RESET_PC (32'h8000_0000))
|
||||
cpu
|
||||
(
|
||||
.clk (wb_clk),
|
||||
.o_ibus_adr (wb_m2s_cpu_ibus_adr),
|
||||
.o_ibus_cyc (wb_m2s_cpu_ibus_cyc),
|
||||
.o_ibus_stb (wb_m2s_cpu_ibus_stb),
|
||||
.i_ibus_rdt (wb_s2m_cpu_ibus_dat),
|
||||
.i_ibus_ack (wb_s2m_cpu_ibus_ack),
|
||||
.o_dbus_adr (wb_m2s_cpu_dbus_adr),
|
||||
.o_dbus_dat (wb_m2s_cpu_dbus_dat),
|
||||
.o_dbus_sel (wb_m2s_cpu_dbus_sel),
|
||||
.o_dbus_we (wb_m2s_cpu_dbus_we),
|
||||
.o_dbus_cyc (wb_m2s_cpu_dbus_cyc),
|
||||
.o_dbus_stb (wb_m2s_cpu_dbus_stb),
|
||||
.i_dbus_rdt (wb_s2m_cpu_dbus_dat),
|
||||
.i_dbus_ack (wb_s2m_cpu_dbus_ack));
|
||||
|
||||
assign wb_m2s_cpu_ibus_dat = 32'd0;
|
||||
assign wb_m2s_cpu_ibus_we = 1'b0;
|
||||
assign wb_m2s_cpu_ibus_sel = 4'b1111;
|
||||
assign wb_m2s_cpu_ibus_cti = 3'b000;
|
||||
assign wb_m2s_cpu_ibus_bte = 2'b00;
|
||||
|
||||
endmodule
|
||||
43
rtl/riscv_timer.v
Normal file
43
rtl/riscv_timer.v
Normal file
@ -0,0 +1,43 @@
|
||||
`default_nettype none
|
||||
module riscv_timer
|
||||
(input i_clk,
|
||||
output reg o_irq = 1'b0,
|
||||
input [31:0] i_wb_adr,
|
||||
input [31:0] i_wb_dat,
|
||||
input [3:0] i_wb_sel,
|
||||
input i_wb_we,
|
||||
input i_wb_cyc,
|
||||
input i_wb_stb,
|
||||
output reg [31:0] o_wb_dat,
|
||||
output reg o_wb_ack = 1'b0);
|
||||
|
||||
reg [63:0] mtime = 64'd0;
|
||||
reg [63:0] mtimecmp = 64'd0;
|
||||
|
||||
localparam [1:0]
|
||||
REG_MTIMELO = 2'd0,
|
||||
REG_MTIMEHI = 2'd1,
|
||||
REG_MTIMECMPLO = 2'd2,
|
||||
REG_MTIMECMPHI = 2'd3;
|
||||
|
||||
always @(i_wb_adr)
|
||||
case (i_wb_adr[3:2])
|
||||
REG_MTIMELO : o_wb_dat = mtime[31:0];
|
||||
REG_MTIMEHI : o_wb_dat = mtime[63:32];
|
||||
REG_MTIMECMPLO : o_wb_dat = mtimecmp[31:0];
|
||||
REG_MTIMECMPHI : o_wb_dat = mtimecmp[63:32];
|
||||
endcase
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
o_wb_ack <= 1'b0;
|
||||
if (i_wb_cyc & i_wb_stb) begin
|
||||
o_wb_ack <= !o_wb_ack;
|
||||
if (i_wb_we & (i_wb_adr[3:2] == REG_MTIMECMPLO))
|
||||
mtimecmp[31:0] <= i_wb_dat;
|
||||
if (i_wb_we & (i_wb_adr[3:2] == REG_MTIMECMPHI))
|
||||
mtimecmp[63:32] <= i_wb_dat;
|
||||
end
|
||||
mtime <= mtime + 64'd1;
|
||||
o_irq <= (mtime >= mtimecmp);
|
||||
end
|
||||
endmodule
|
||||
72
rtl/serv_csr.v
Normal file
72
rtl/serv_csr.v
Normal file
@ -0,0 +1,72 @@
|
||||
`default_nettype none
|
||||
module serv_csr
|
||||
(
|
||||
input i_clk,
|
||||
input i_en,
|
||||
input [2:0] i_csr_sel,
|
||||
input [1:0] i_csr_source,
|
||||
input i_trap,
|
||||
input i_pc,
|
||||
input i_mtval,
|
||||
input i_load_misaligned,
|
||||
input i_store_misaligned,
|
||||
input i_d,
|
||||
output o_q);
|
||||
|
||||
`include "serv_params.vh"
|
||||
/*
|
||||
mtvec RW
|
||||
mepc RW
|
||||
mstatus RWSC
|
||||
mcause R
|
||||
mip CWi
|
||||
mie SCWi
|
||||
*/
|
||||
|
||||
reg [31:0] mtvec = 32'h0;
|
||||
reg [31:0] mepc = 32'h0;
|
||||
reg [31:0] mtval = 32'h0;
|
||||
reg [31:0] mcause = 32'h0;
|
||||
|
||||
wire mtvec_en = i_en & (i_csr_sel == CSR_SEL_MTVEC);
|
||||
wire mepc_en = i_en & (i_trap | (i_csr_sel == CSR_SEL_MEPC));
|
||||
wire mcause_en = i_en & (i_csr_sel == CSR_SEL_MCAUSE);
|
||||
wire mtval_en = i_en & (i_trap | (i_csr_sel == CSR_SEL_MTVAL));
|
||||
|
||||
wire csr_in;
|
||||
wire csr_out;
|
||||
|
||||
assign csr_in = (i_csr_source == CSR_SOURCE_EXT) ? i_d :
|
||||
(i_csr_source == CSR_SOURCE_SET) ? csr_out | i_d :
|
||||
(i_csr_source == CSR_SOURCE_CLR) ? csr_out & ~i_d :
|
||||
(i_csr_source == CSR_SOURCE_CSR) ? csr_out :
|
||||
1'bx;
|
||||
|
||||
assign csr_out = (i_csr_sel == CSR_SEL_MTVEC) ? mtvec[0] :
|
||||
(i_csr_sel == CSR_SEL_MEPC) ? mepc[0] :
|
||||
(i_csr_sel == CSR_SEL_MCAUSE) ? mcause[0] :
|
||||
(i_csr_sel == CSR_SEL_MTVAL) ? mtval[0] :
|
||||
1'bx;
|
||||
|
||||
assign o_q = csr_out;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_load_misaligned)
|
||||
mcause[3:0] <= 4'd4;
|
||||
if (i_store_misaligned)
|
||||
mcause[3:0] <= 4'd6;
|
||||
|
||||
if (mtvec_en)
|
||||
mtvec <= {csr_in, mtvec[31:1]};
|
||||
|
||||
if (mepc_en)
|
||||
mepc <= {i_trap ? i_pc : csr_in, mepc[31:1]};
|
||||
|
||||
if (mcause_en)
|
||||
mcause <= {csr_in, mcause[31:1]};
|
||||
|
||||
if (mtval_en)
|
||||
mtval <= {i_trap ? i_mtval : csr_in, mtval[31:1]};
|
||||
end
|
||||
|
||||
endmodule
|
||||
@ -1,35 +1,37 @@
|
||||
`default_nettype none
|
||||
module serv_ctrl
|
||||
(
|
||||
input clk,
|
||||
input i_en,
|
||||
input i_jump,
|
||||
input i_offset,
|
||||
input i_rs1,
|
||||
input i_jalr,
|
||||
input i_auipc,
|
||||
output o_rd,
|
||||
input clk,
|
||||
input i_en,
|
||||
input i_jump,
|
||||
input i_offset,
|
||||
input i_rs1,
|
||||
input i_jalr,
|
||||
input i_auipc,
|
||||
input i_trap,
|
||||
input i_csr_pc,
|
||||
output o_rd,
|
||||
output [31:0] o_ibus_adr,
|
||||
output reg o_ibus_cyc = 1'b0,
|
||||
input i_ibus_ack);
|
||||
output reg o_ibus_cyc = 1'b0,
|
||||
input i_ibus_ack);
|
||||
|
||||
parameter RESET_PC = 32'd8;
|
||||
|
||||
|
||||
wire pc_plus_4;
|
||||
wire pc_plus_offset;
|
||||
|
||||
|
||||
wire plus_4;
|
||||
|
||||
wire pc;
|
||||
|
||||
|
||||
wire new_pc;
|
||||
|
||||
wire offset_a;
|
||||
|
||||
|
||||
assign plus_4 = en_2r & !en_3r;
|
||||
|
||||
assign o_ibus_adr[0] = pc;
|
||||
|
||||
|
||||
ser_add ser_add_pc_plus_4
|
||||
(
|
||||
.clk (clk),
|
||||
@ -52,11 +54,11 @@ module serv_ctrl
|
||||
.o_par (o_ibus_adr[31:1])
|
||||
);
|
||||
|
||||
assign new_pc = i_jump ? pc_plus_offset : pc_plus_4;
|
||||
assign o_rd = i_auipc ? pc_plus_offset : pc_plus_4;
|
||||
assign new_pc = i_trap ? i_csr_pc : i_jump ? pc_plus_offset_aligned : pc_plus_4;
|
||||
assign o_rd = i_auipc ? pc_plus_offset_aligned : pc_plus_4;
|
||||
|
||||
assign offset_a = i_jalr ? i_rs1 : pc;
|
||||
|
||||
|
||||
ser_add ser_add_pc_plus_offset
|
||||
(
|
||||
.clk (clk),
|
||||
@ -66,10 +68,13 @@ module serv_ctrl
|
||||
.q (pc_plus_offset),
|
||||
.o_v ());
|
||||
|
||||
wire pc_plus_offset_aligned = pc_plus_offset & en_r;
|
||||
|
||||
|
||||
reg en_r = 1'b1;
|
||||
reg en_2r = 1'b0;
|
||||
reg en_3r = 1'b0;
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
en_r <= i_en;
|
||||
en_2r <= en_r;
|
||||
@ -80,6 +85,5 @@ module serv_ctrl
|
||||
else if (o_ibus_cyc & i_ibus_ack)
|
||||
o_ibus_cyc <= 1'b0;
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
@ -1,39 +1,45 @@
|
||||
module serv_decode
|
||||
(
|
||||
input clk,
|
||||
input clk,
|
||||
input [31:0] i_wb_rdt,
|
||||
input i_wb_en,
|
||||
output o_ibus_active,
|
||||
output o_ctrl_en,
|
||||
output o_ctrl_jump,
|
||||
output o_ctrl_jalr,
|
||||
output o_ctrl_auipc,
|
||||
output o_rf_rd_en,
|
||||
input i_wb_en,
|
||||
output o_ibus_active,
|
||||
output o_ctrl_en,
|
||||
output o_ctrl_jump,
|
||||
output o_ctrl_jalr,
|
||||
output o_ctrl_auipc,
|
||||
output reg o_ctrl_trap = 1'b0,
|
||||
output o_ctrl_mret,
|
||||
output o_rf_rd_en,
|
||||
output reg [4:0] o_rf_rd_addr,
|
||||
output o_rf_rs_en,
|
||||
output o_rf_rs_en,
|
||||
output reg [4:0] o_rf_rs1_addr,
|
||||
output reg [4:0] o_rf_rs2_addr,
|
||||
output o_alu_en,
|
||||
output o_alu_init,
|
||||
output o_alu_sub,
|
||||
output reg o_alu_cmp_sel,
|
||||
output o_alu_cmp_neg,
|
||||
output reg o_alu_cmp_uns,
|
||||
input i_alu_cmp,
|
||||
output o_alu_shamt_en,
|
||||
output o_alu_sh_signed,
|
||||
output o_alu_sh_right,
|
||||
output o_alu_en,
|
||||
output o_alu_init,
|
||||
output o_alu_sub,
|
||||
output reg o_alu_cmp_sel,
|
||||
output o_alu_cmp_neg,
|
||||
output reg o_alu_cmp_uns,
|
||||
input i_alu_cmp,
|
||||
output o_alu_shamt_en,
|
||||
output o_alu_sh_signed,
|
||||
output o_alu_sh_right,
|
||||
output reg [2:0] o_alu_rd_sel,
|
||||
output o_mem_en,
|
||||
output o_mem_cmd,
|
||||
output o_mem_init,
|
||||
output reg o_mem_dat_valid,
|
||||
input i_mem_busy,
|
||||
output o_mem_en,
|
||||
output o_mem_cmd,
|
||||
output o_mem_init,
|
||||
output reg o_mem_dat_valid,
|
||||
input i_mem_busy,
|
||||
input i_mem_misalign,
|
||||
output o_csr_en,
|
||||
output reg [2:0] o_csr_sel,
|
||||
output reg [1:0] o_csr_source,
|
||||
output reg [2:0] o_funct3,
|
||||
output reg o_imm,
|
||||
output o_offset_source,
|
||||
output o_op_b_source,
|
||||
output [1:0] o_rd_source);
|
||||
output reg o_imm,
|
||||
output o_offset_source,
|
||||
output o_op_b_source,
|
||||
output [2:0] o_rd_source);
|
||||
|
||||
`include "serv_params.vh"
|
||||
|
||||
@ -44,7 +50,7 @@ module serv_decode
|
||||
MEM_INIT = 3'd3,
|
||||
MEM_WAIT = 3'd4,
|
||||
RUN = 3'd5;
|
||||
|
||||
|
||||
localparam [4:0]
|
||||
OP_LOAD = 5'b00000,
|
||||
OP_STORE = 5'b01000,
|
||||
@ -54,7 +60,8 @@ module serv_decode
|
||||
OP_LUI = 5'b01101,
|
||||
OP_BRANCH = 5'b11000,
|
||||
OP_JALR = 5'b11001,
|
||||
OP_JAL = 5'b11011;
|
||||
OP_JAL = 5'b11011,
|
||||
OP_SYSTEM = 5'b11100;
|
||||
|
||||
reg [2:0] state = IDLE;
|
||||
|
||||
@ -63,11 +70,12 @@ module serv_decode
|
||||
wire running;
|
||||
wire mem_op;
|
||||
wire shift_op;
|
||||
wire csr_op;
|
||||
|
||||
reg signbit;
|
||||
|
||||
|
||||
assign o_ibus_active = (state == IDLE);
|
||||
|
||||
|
||||
assign mem_op = (opcode == OP_LOAD) | (opcode == OP_STORE);
|
||||
assign shift_op = ((opcode == OP_OPIMM) & (o_funct3[1:0] == 2'b01)) |
|
||||
((opcode == OP_OP ) & (o_funct3[1:0] == 2'b01));
|
||||
@ -78,10 +86,12 @@ module serv_decode
|
||||
((opcode == OP_BRANCH) & i_alu_cmp);
|
||||
|
||||
assign o_ctrl_jalr = (opcode == OP_JALR);
|
||||
|
||||
|
||||
assign o_ctrl_auipc = (opcode == OP_AUIPC);
|
||||
|
||||
assign o_rf_rd_en = running &
|
||||
assign o_ctrl_mret = (opcode == OP_SYSTEM) & imm[21] & !(|o_funct3);
|
||||
|
||||
assign o_rf_rd_en = running & !o_ctrl_trap &
|
||||
(opcode != OP_STORE) &
|
||||
(opcode != OP_BRANCH);
|
||||
|
||||
@ -104,6 +114,9 @@ module serv_decode
|
||||
|
||||
|
||||
assign o_alu_cmp_neg = (opcode == OP_BRANCH) & o_funct3[0];
|
||||
|
||||
assign o_csr_en = ((opcode == OP_SYSTEM) & (|o_funct3) | o_ctrl_mret | o_ctrl_trap) & running;
|
||||
|
||||
always @(o_funct3) begin
|
||||
casez (o_funct3)
|
||||
3'b00? : o_alu_cmp_sel = ALU_CMP_EQ;
|
||||
@ -111,7 +124,7 @@ module serv_decode
|
||||
3'b1?? : o_alu_cmp_sel = ALU_CMP_LT;
|
||||
default : o_alu_cmp_sel = 1'bx;
|
||||
endcase
|
||||
|
||||
|
||||
casez (o_funct3)
|
||||
3'b00? : o_alu_cmp_uns = 1'b0;
|
||||
3'b010 : o_alu_cmp_uns = 1'b0;
|
||||
@ -131,11 +144,39 @@ module serv_decode
|
||||
3'b111 : o_alu_rd_sel = ALU_RESULT_AND;
|
||||
default : o_alu_rd_sel = 3'bxx;
|
||||
endcase
|
||||
|
||||
casez(o_funct3[1:0])
|
||||
2'b01 : o_csr_source = CSR_SOURCE_EXT; //Check for x0
|
||||
2'b10 : o_csr_source = CSR_SOURCE_SET;
|
||||
2'b11 : o_csr_source = CSR_SOURCE_CLR;
|
||||
default : o_csr_source = 2'bxx;
|
||||
endcase
|
||||
if ((o_rf_rs1_addr == 5'd0) | o_ctrl_trap | o_ctrl_mret)
|
||||
o_csr_source = CSR_SOURCE_CSR;
|
||||
|
||||
casez(imm[31:20])
|
||||
12'h305 : o_csr_sel = CSR_SEL_MTVEC;
|
||||
12'h341 : o_csr_sel = CSR_SEL_MEPC;
|
||||
12'h342 : o_csr_sel = CSR_SEL_MCAUSE;
|
||||
12'h343 : o_csr_sel = CSR_SEL_MTVAL;
|
||||
//12'hf14 : o_csr_sel = CSR_SEL_MHARTID;
|
||||
default : begin
|
||||
o_csr_sel = 3'bxxx;
|
||||
if (o_csr_en) begin
|
||||
$display("%0t: CSR %03h not implemented", $time, imm[31:20]);
|
||||
//#100 $finish;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
if (o_ctrl_trap)
|
||||
o_csr_sel = CSR_SEL_MTVEC;
|
||||
if (o_ctrl_mret)
|
||||
o_csr_sel = CSR_SEL_MEPC;
|
||||
end
|
||||
assign o_alu_shamt_en = (state == SH_INIT) & (cnt < 5);
|
||||
assign o_alu_sh_signed = signbit;
|
||||
assign o_alu_sh_right = o_funct3[2];
|
||||
|
||||
|
||||
assign o_mem_en = mem_op & cnt_en;
|
||||
assign o_mem_cmd = (opcode == OP_STORE);
|
||||
|
||||
@ -143,7 +184,7 @@ module serv_decode
|
||||
|
||||
reg [4:0] opcode;
|
||||
reg [31:0] imm;
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (i_wb_en) begin
|
||||
o_rf_rd_addr <= i_wb_rdt[11:7];
|
||||
@ -153,7 +194,7 @@ module serv_decode
|
||||
signbit <= i_wb_rdt[30];
|
||||
opcode <= i_wb_rdt[6:2];
|
||||
imm <= i_wb_rdt;
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@ -187,8 +228,10 @@ module serv_decode
|
||||
(opcode == OP_LUI) ? RD_SOURCE_IMM :
|
||||
(opcode == OP_AUIPC) ? RD_SOURCE_CTRL :
|
||||
(opcode == OP_JALR) ? RD_SOURCE_CTRL :
|
||||
(opcode == OP_LOAD) ? RD_SOURCE_MEM : 2'bxx;
|
||||
|
||||
(opcode == OP_SYSTEM) ? RD_SOURCE_CSR :
|
||||
(opcode == OP_LOAD) ? RD_SOURCE_MEM : 3'bxx;
|
||||
|
||||
//31, cnt, 20, +20, +7, 7, 1'b0
|
||||
always @(cnt, opcode, imm) begin
|
||||
o_imm = 1'bx;
|
||||
if (opcode == OP_JAL)
|
||||
@ -232,6 +275,8 @@ module serv_decode
|
||||
assign running = (state == RUN);
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (cnt_done)
|
||||
o_ctrl_trap <= i_mem_misalign;
|
||||
state <= state;
|
||||
case (state)
|
||||
IDLE : begin
|
||||
@ -265,5 +310,24 @@ module serv_decode
|
||||
cnt <= cnt + {4'd0,cnt_en};
|
||||
|
||||
end
|
||||
`define SERV_DECODE_CHECKS
|
||||
`ifdef SERV_DECODE_CHECKS
|
||||
reg unknown_op = 1'b0;
|
||||
|
||||
always @(opcode)
|
||||
if (i_wb_en) begin
|
||||
if (!((opcode == OP_LOAD) |
|
||||
(opcode == OP_STORE ) |
|
||||
(opcode == OP_OPIMM ) |
|
||||
(opcode == OP_AUIPC ) |
|
||||
(opcode == OP_OP ) |
|
||||
(opcode == OP_LUI ) |
|
||||
(opcode == OP_BRANCH) |
|
||||
(opcode == OP_JALR ) |
|
||||
(opcode == OP_SYSTEM ) |
|
||||
(opcode == OP_JAL ))) begin
|
||||
$display("Unknown opcode %b at %0t", opcode, $time);
|
||||
end // if ((opcode != OP_LOAD) |...
|
||||
end // if (i_wb_en)
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
@ -1,26 +1,28 @@
|
||||
`default_nettype none
|
||||
module serv_mem_if
|
||||
(
|
||||
input i_clk,
|
||||
input i_en,
|
||||
input i_init,
|
||||
input i_dat_valid,
|
||||
input i_cmd,
|
||||
input [2:0] i_funct3,
|
||||
input i_rs1,
|
||||
input i_rs2,
|
||||
input i_imm,
|
||||
output o_rd,
|
||||
output reg o_busy = 1'b0,
|
||||
input i_clk,
|
||||
input i_en,
|
||||
input i_init,
|
||||
input i_dat_valid,
|
||||
input i_cmd,
|
||||
input [2:0] i_funct3,
|
||||
input i_rs1,
|
||||
input i_rs2,
|
||||
input i_imm,
|
||||
output o_rd,
|
||||
output reg o_busy = 1'b0,
|
||||
output o_misalign,
|
||||
input i_trap,
|
||||
//External interface
|
||||
output [31:0] o_wb_adr,
|
||||
output [31:0] o_wb_dat,
|
||||
output [3:0] o_wb_sel,
|
||||
output o_wb_we ,
|
||||
output reg o_wb_cyc = 1'b0,
|
||||
output o_wb_stb,
|
||||
output o_wb_we ,
|
||||
output reg o_wb_cyc = 1'b0,
|
||||
output o_wb_stb,
|
||||
input [31:0] i_wb_rdt,
|
||||
input i_wb_ack);
|
||||
input i_wb_ack);
|
||||
|
||||
wire wb_en = o_wb_cyc & i_wb_ack;
|
||||
assign o_wb_stb = o_wb_cyc;
|
||||
@ -30,7 +32,7 @@ module serv_mem_if
|
||||
wire adr;
|
||||
reg [31:0] dat = 32'd0;
|
||||
reg signbit = 1'b0;
|
||||
|
||||
|
||||
ser_add ser_add_rs1_plus_imm
|
||||
(
|
||||
.clk (i_clk),
|
||||
@ -43,7 +45,7 @@ module serv_mem_if
|
||||
shift_reg #(32) shift_reg_adr
|
||||
(
|
||||
.clk (i_clk),
|
||||
.i_en (i_init),
|
||||
.i_en (i_init | (i_en & i_trap)),
|
||||
.i_d (adr),
|
||||
.o_q (o_wb_adr[0]),
|
||||
.o_par (o_wb_adr[31:1])
|
||||
@ -56,6 +58,9 @@ module serv_mem_if
|
||||
wire is_half = i_funct3[0];
|
||||
wire is_byte = !(|i_funct3[1:0]);
|
||||
|
||||
assign o_misalign = (|misalign);
|
||||
|
||||
|
||||
wire upper_half = bytepos[1];
|
||||
|
||||
assign o_wb_dat = dat;
|
||||
@ -66,7 +71,7 @@ module serv_mem_if
|
||||
reg [1:0] bytepos;
|
||||
reg [4:0] cnt = 5'd0;
|
||||
reg dat_en;
|
||||
|
||||
|
||||
always @(i_funct3, cnt, bytepos)
|
||||
casez(i_funct3[1:0])
|
||||
2'b1? : dat_en = 1'b1;
|
||||
@ -75,21 +80,29 @@ module serv_mem_if
|
||||
(bytepos == 2'd2) ? (cnt < 16) :
|
||||
(bytepos == 2'd1) ? (cnt < 24) : 1'b1;
|
||||
endcase
|
||||
|
||||
|
||||
reg init_2r = 1'b0;
|
||||
reg [1:0] misalign = 2'b00;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
cnt <= cnt + {4'd0,i_init};
|
||||
|
||||
if (i_init & !init_r)
|
||||
misalign[0] <= (!is_byte & adr);
|
||||
if (init_r & !init_2r)
|
||||
misalign[1] <= (is_word & adr);
|
||||
if (i_trap)
|
||||
misalign <= 2'b00;
|
||||
|
||||
if (i_en & !en_r)
|
||||
bytepos[0] <= adr;
|
||||
if (en_r & !en_2r)
|
||||
bytepos[1] <= adr;
|
||||
|
||||
|
||||
if (i_dat_valid)
|
||||
signbit <= dat[0];
|
||||
|
||||
if (i_en & i_init)
|
||||
o_busy <= 1'b1;
|
||||
else if (wb_en)
|
||||
else if (wb_en | i_trap)
|
||||
o_busy <= 1'b0;
|
||||
|
||||
if (wb_en & !o_wb_we) begin
|
||||
@ -105,9 +118,10 @@ module serv_mem_if
|
||||
en_r <= i_en;
|
||||
en_2r <= en_r;
|
||||
init_r <= i_init;
|
||||
init_2r <= init_r;
|
||||
if (wb_en)
|
||||
o_wb_cyc <= 1'b0;
|
||||
else if (init_r & !i_init) begin //Optimize?
|
||||
else if (init_r & !i_init & !i_trap) begin //Optimize?
|
||||
o_wb_cyc <= 1'b1;
|
||||
end
|
||||
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
localparam [1:0]
|
||||
RD_SOURCE_CTRL = 2'd0,
|
||||
RD_SOURCE_ALU = 2'd1,
|
||||
RD_SOURCE_IMM = 2'd2,
|
||||
RD_SOURCE_MEM = 2'd3;
|
||||
localparam [2:0]
|
||||
RD_SOURCE_CTRL = 3'd0,
|
||||
RD_SOURCE_ALU = 3'd1,
|
||||
RD_SOURCE_IMM = 3'd2,
|
||||
RD_SOURCE_MEM = 3'd3,
|
||||
RD_SOURCE_CSR = 3'd4;
|
||||
|
||||
localparam [0:0]
|
||||
OFFSET_SOURCE_IMM = 1'd0,
|
||||
@ -11,7 +12,7 @@ localparam [0:0]
|
||||
localparam [0:0]
|
||||
OP_B_SOURCE_IMM = 1'd0,
|
||||
OP_B_SOURCE_RS2 = 1'd1;
|
||||
|
||||
|
||||
localparam[2:0]
|
||||
ALU_RESULT_ADD = 3'd0,
|
||||
ALU_RESULT_SR = 3'd1,
|
||||
@ -33,3 +34,16 @@ localparam [0:0]
|
||||
OR
|
||||
AND
|
||||
*/
|
||||
|
||||
localparam [2:0]
|
||||
CSR_SEL_MTVEC = 3'd0,
|
||||
CSR_SEL_MEPC = 3'd1,
|
||||
CSR_SEL_MTVAL = 3'd2,
|
||||
CSR_SEL_MCAUSE = 3'd3
|
||||
;
|
||||
|
||||
localparam [1:0]
|
||||
CSR_SOURCE_CSR = 2'b00,
|
||||
CSR_SOURCE_EXT = 2'b01,
|
||||
CSR_SOURCE_SET = 2'b10,
|
||||
CSR_SOURCE_CLR = 2'b11;
|
||||
|
||||
@ -46,26 +46,29 @@ module serv_top
|
||||
input i_dbus_ack);
|
||||
|
||||
assign o_ibus_stb = o_ibus_cyc;
|
||||
|
||||
|
||||
`include "serv_params.vh"
|
||||
|
||||
wire [4:0] rd_addr;
|
||||
wire [4:0] rs1_addr;
|
||||
wire [4:0] rs2_addr;
|
||||
|
||||
wire [1:0] rd_source;
|
||||
|
||||
wire [2:0] rd_source;
|
||||
wire ctrl_rd;
|
||||
wire alu_rd;
|
||||
wire mem_rd;
|
||||
wire csr_rd;
|
||||
wire rd;
|
||||
|
||||
wire ctrl_en;
|
||||
wire jump;
|
||||
wire jalr;
|
||||
wire auipc;
|
||||
wire mret;
|
||||
wire offset;
|
||||
wire offset_source;
|
||||
wire imm;
|
||||
wire trap;
|
||||
|
||||
wire [2:0] funct3;
|
||||
|
||||
@ -80,7 +83,7 @@ module serv_top
|
||||
wire alu_sh_signed;
|
||||
wire alu_sh_right;
|
||||
wire [2:0] alu_rd_sel;
|
||||
|
||||
|
||||
wire rs1;
|
||||
wire rs2;
|
||||
wire rs_en;
|
||||
@ -90,14 +93,18 @@ module serv_top
|
||||
wire op_b;
|
||||
|
||||
wire mem_en;
|
||||
|
||||
|
||||
wire mem_cmd;
|
||||
wire mem_dat_valid;
|
||||
|
||||
|
||||
wire mem_init;
|
||||
wire mem_busy;
|
||||
wire mem_misalign;
|
||||
|
||||
wire csr_en;
|
||||
wire [2:0] csr_sel;
|
||||
wire [1:0] csr_source;
|
||||
|
||||
|
||||
parameter RESET_PC = 32'd8;
|
||||
|
||||
serv_decode decode
|
||||
@ -110,6 +117,8 @@ module serv_top
|
||||
.o_ctrl_jump (jump),
|
||||
.o_ctrl_jalr (jalr),
|
||||
.o_ctrl_auipc (auipc),
|
||||
.o_ctrl_trap (trap),
|
||||
.o_ctrl_mret (mret),
|
||||
.o_funct3 (funct3),
|
||||
.o_alu_en (alu_en),
|
||||
.o_alu_init (alu_init),
|
||||
@ -132,6 +141,10 @@ module serv_top
|
||||
.o_mem_init (mem_init),
|
||||
.o_mem_dat_valid (mem_dat_valid),
|
||||
.i_mem_busy (mem_busy),
|
||||
.i_mem_misalign (mem_misalign),
|
||||
.o_csr_en (csr_en),
|
||||
.o_csr_sel (csr_sel),
|
||||
.o_csr_source (csr_source),
|
||||
.o_imm (imm),
|
||||
.o_offset_source (offset_source),
|
||||
.o_op_b_source (op_b_source),
|
||||
@ -148,6 +161,8 @@ module serv_top
|
||||
.i_rs1 (rs1),
|
||||
.i_jalr (jalr),
|
||||
.i_auipc (auipc),
|
||||
.i_trap (trap | mret),
|
||||
.i_csr_pc (csr_rd),
|
||||
.o_rd (ctrl_rd),
|
||||
.o_ibus_adr (o_ibus_adr),
|
||||
.o_ibus_cyc (o_ibus_cyc),
|
||||
@ -156,10 +171,12 @@ module serv_top
|
||||
assign offset = (offset_source == OFFSET_SOURCE_IMM) ? imm :
|
||||
(offset_source == OFFSET_SOURCE_RS1) ? rs1 : 1'bx;
|
||||
|
||||
//TODO: Pass imm through alu to avoid 5-way mux
|
||||
assign rd = (rd_source == RD_SOURCE_CTRL) ? ctrl_rd :
|
||||
(rd_source == RD_SOURCE_ALU) ? alu_rd :
|
||||
(rd_source == RD_SOURCE_IMM) ? imm :
|
||||
(rd_source == RD_SOURCE_MEM) ? mem_rd : 1'bx;
|
||||
(rd_source == RD_SOURCE_MEM) ? mem_rd :
|
||||
(rd_source == RD_SOURCE_CSR) ? csr_rd : 1'bx;
|
||||
|
||||
assign op_b = (op_b_source == OP_B_SOURCE_IMM) ? imm :
|
||||
(op_b_source == OP_B_SOURCE_RS2) ? rs2 :
|
||||
@ -208,6 +225,8 @@ module serv_top
|
||||
.i_imm (imm),
|
||||
.o_rd (mem_rd),
|
||||
.o_busy (mem_busy),
|
||||
.o_misalign (mem_misalign),
|
||||
.i_trap (trap),
|
||||
//External interface
|
||||
.o_wb_adr (o_dbus_adr),
|
||||
.o_wb_dat (o_dbus_dat),
|
||||
@ -218,6 +237,20 @@ module serv_top
|
||||
.i_wb_rdt (i_dbus_rdt),
|
||||
.i_wb_ack (i_dbus_ack));
|
||||
|
||||
serv_csr csr
|
||||
(
|
||||
.i_clk (clk),
|
||||
.i_en (csr_en),
|
||||
.i_csr_sel (csr_sel),
|
||||
.i_csr_source (csr_source),
|
||||
.i_trap (trap),
|
||||
.i_pc (o_ibus_adr[0]),
|
||||
.i_mtval (o_dbus_adr[0]),
|
||||
.i_load_misaligned (mem_misalign & !mem_cmd),
|
||||
.i_store_misaligned (mem_misalign & mem_cmd),
|
||||
.i_d (rs1/* FIXME csr_d*/),
|
||||
.o_q (csr_rd));
|
||||
|
||||
`ifdef RISCV_FORMAL
|
||||
reg [31:0] rs1_fv, rs2_fv, rd_fv;
|
||||
reg [31:0] pc = RESET_PC;
|
||||
|
||||
83
serv.core
83
serv.core
@ -5,7 +5,6 @@ name : ::serv:0
|
||||
filesets:
|
||||
core:
|
||||
files:
|
||||
- rtl/camd_ram.v
|
||||
- rtl/serv_params.vh : {is_include_file : true}
|
||||
- rtl/shift_reg.v
|
||||
- rtl/ser_add.v
|
||||
@ -13,38 +12,37 @@ filesets:
|
||||
- rtl/ser_lt.v
|
||||
- rtl/ser_shift.v
|
||||
- rtl/serv_alu.v
|
||||
- rtl/serv_csr.v
|
||||
- rtl/serv_ctrl.v
|
||||
- rtl/serv_decode.v
|
||||
- rtl/serv_mem_if.v
|
||||
- rtl/serv_regfile.v
|
||||
- rtl/serv_top.v
|
||||
file_type : verilogSource
|
||||
depend : [wb_ram]
|
||||
|
||||
ser_add_tb:
|
||||
files:
|
||||
- ser_add_tb.v
|
||||
file_type : verilogSource
|
||||
depend : [vlog_tb_utils]
|
||||
|
||||
serv_ctrl_tb:
|
||||
files:
|
||||
- bench/serv_ctrl_tb.v : {file_type : verilogSource}
|
||||
depend : [vlog_tb_utils]
|
||||
|
||||
serv_decode_tb:
|
||||
files: [bench/serv_decode_tb.v : {file_type : verilogSource}]
|
||||
depend : [vlog_tb_utils]
|
||||
serv_top_tb:
|
||||
files:
|
||||
- firmware.hex : {copyto : firmware.hex, file_type : user}
|
||||
- testprint.v
|
||||
- bench/serv_top_tb.v
|
||||
file_type : verilogSource
|
||||
depend : [vlog_tb_utils, wb_intercon, "yosys:techlibs:ice40"]
|
||||
depend : [vlog_tb_utils, "yosys:techlibs:ice40"]
|
||||
|
||||
wrapper:
|
||||
files:
|
||||
- testhalt.v
|
||||
- testprint.v
|
||||
- rtl/riscv_timer.v
|
||||
- bench/serv_wrapper.v
|
||||
file_type : verilogSource
|
||||
depend : [wb_intercon, wb_ram]
|
||||
|
||||
pcf:
|
||||
files: [data/dummy.pcf : {file_type : PCF}]
|
||||
|
||||
verilator_tb:
|
||||
files:
|
||||
- bench/serv_soc_tb.cpp : {file_type : verilogSource}
|
||||
depend : ["yosys:techlibs:ice40"]
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets : [core]
|
||||
@ -54,6 +52,7 @@ targets:
|
||||
default_tool : icestorm
|
||||
filesets : [core, pcf]
|
||||
toplevel : serv_top
|
||||
|
||||
lint:
|
||||
default_tool : verilator
|
||||
filesets : [core]
|
||||
@ -61,33 +60,37 @@ targets:
|
||||
verilator:
|
||||
mode : lint-only
|
||||
toplevel : serv_top
|
||||
ser_add_tb:
|
||||
default_tool : icarus
|
||||
filesets: [core, ser_add_tb]
|
||||
toplevel: ser_add_tb
|
||||
|
||||
serv_ctrl_tb:
|
||||
default_tool: icarus
|
||||
filesets : [core, serv_ctrl_tb]
|
||||
toplevel : serv_ctrl_tb
|
||||
|
||||
serv_decode_tb:
|
||||
default_tool: icarus
|
||||
filesets : [core, serv_decode_tb]
|
||||
toplevel : serv_decode_tb
|
||||
|
||||
serv_top_tb:
|
||||
default_tool: icarus
|
||||
filesets : [core, serv_top_tb]
|
||||
filesets : [core, wrapper, serv_top_tb]
|
||||
generate : [wb_intercon]
|
||||
parameters : [RISCV_FORMAL=true]
|
||||
parameters : [RISCV_FORMAL=true, firmware]
|
||||
toplevel : serv_top_tb
|
||||
|
||||
verilator_tb:
|
||||
default_tool: verilator
|
||||
filesets : [core, wrapper, verilator_tb]
|
||||
generate : [wb_intercon]
|
||||
parameters : [RISCV_FORMAL=true, firmware, signature]
|
||||
tools:
|
||||
verilator:
|
||||
verilator_options : [-Wno-fatal, --trace]
|
||||
toplevel : serv_wrapper
|
||||
|
||||
parameters:
|
||||
RISCV_FORMAL:
|
||||
datatype : bool
|
||||
paramtype : vlogdefine
|
||||
|
||||
firmware:
|
||||
datatype : file
|
||||
paramtype : plusarg
|
||||
|
||||
signature:
|
||||
datatype : file
|
||||
paramtype : plusarg
|
||||
|
||||
generate:
|
||||
wb_intercon:
|
||||
generator: wb_intercon_gen
|
||||
@ -96,15 +99,17 @@ generate:
|
||||
cpu_ibus:
|
||||
slaves : [mem]
|
||||
cpu_dbus:
|
||||
slaves : [mem, testprint, testpassed]
|
||||
slaves : [mem, testprint, testhalt, timer]
|
||||
slaves:
|
||||
mem:
|
||||
offset : 0
|
||||
offset : 0x80000000
|
||||
size : 65536
|
||||
testprint:
|
||||
offset : 0x10000000
|
||||
size : 4
|
||||
testpassed:
|
||||
testhalt:
|
||||
offset : 0x20000000
|
||||
size : 4
|
||||
|
||||
timer:
|
||||
offset : 0xf00fff40
|
||||
size : 16
|
||||
|
||||
20
testhalt.v
Normal file
20
testhalt.v
Normal file
@ -0,0 +1,20 @@
|
||||
`default_nettype none
|
||||
module testhalt
|
||||
(
|
||||
input i_wb_clk,
|
||||
|
||||
input [31:0] i_wb_dat,
|
||||
input i_wb_we,
|
||||
input i_wb_cyc,
|
||||
input i_wb_stb,
|
||||
output reg o_wb_ack = 1'b0);
|
||||
|
||||
always @(posedge i_wb_clk) begin
|
||||
if (i_wb_cyc & i_wb_stb) begin
|
||||
$display("Test complete");
|
||||
$finish;
|
||||
end
|
||||
if (i_wb_cyc & i_wb_stb & !o_wb_ack)
|
||||
o_wb_ack <= 1'b1;
|
||||
end
|
||||
endmodule
|
||||
24
testprint.v
24
testprint.v
@ -7,16 +7,34 @@ module testprint
|
||||
input i_wb_we,
|
||||
input i_wb_cyc,
|
||||
input i_wb_stb,
|
||||
output reg o_wb_ack = 1'b0);
|
||||
output reg o_wb_ack /* verilator public */ = 1'b0);
|
||||
|
||||
wire wb_en /* verilator public */;
|
||||
|
||||
wire [7:0] ch /* verilator public */;
|
||||
assign ch = i_wb_dat[7:0];
|
||||
|
||||
assign wb_en = i_wb_cyc & i_wb_stb;
|
||||
reg [1023:0] signature_file;
|
||||
integer f = 0;
|
||||
|
||||
initial
|
||||
if ($value$plusargs("signature=%s", signature_file)) begin
|
||||
$display("Writing signature to %0s", signature_file);
|
||||
f = $fopen(signature_file, "w");
|
||||
end
|
||||
|
||||
always @(posedge i_wb_clk) begin
|
||||
if (i_wb_cyc & i_wb_stb) begin
|
||||
o_wb_ack <= 1'b0;
|
||||
if (wb_en & o_wb_ack) begin
|
||||
if (f)
|
||||
$fwrite(f, "%c", i_wb_dat[7:0]);
|
||||
$write("%c", i_wb_dat[7:0]);
|
||||
`ifndef VERILATOR
|
||||
$fflush();
|
||||
`endif
|
||||
end
|
||||
if (i_wb_cyc & i_wb_stb & !o_wb_ack)
|
||||
if (wb_en & !o_wb_ack)
|
||||
o_wb_ack <= 1'b1;
|
||||
end
|
||||
endmodule
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user