Add RISC-V timer to example soc, and tweak ULX3S config
This commit is contained in:
parent
a18c3018e1
commit
8721bd3deb
|
@ -62,6 +62,7 @@ activity_led #(
|
|||
);
|
||||
|
||||
example_soc #(
|
||||
.CLK_MHZ (12),
|
||||
.EXTENSION_A (1),
|
||||
.EXTENSION_C (0),
|
||||
.EXTENSION_M (1),
|
||||
|
@ -72,6 +73,7 @@ example_soc #(
|
|||
.EXTENSION_ZBKB (0),
|
||||
.EXTENSION_ZIFENCEI (0),
|
||||
.EXTENSION_XH3BEXTM (0),
|
||||
.EXTENSION_XH3PMPM (0),
|
||||
.EXTENSION_XH3POWER (0),
|
||||
.CSR_COUNTER (0),
|
||||
.U_MODE (0),
|
||||
|
|
|
@ -17,7 +17,7 @@ wire clk_sys;
|
|||
wire pll_sys_locked;
|
||||
wire rst_n_sys;
|
||||
|
||||
pll_25_40 pll_sys (
|
||||
pll_25_50 pll_sys (
|
||||
.clkin (clk_osc),
|
||||
.clkout0 (clk_sys),
|
||||
.locked (pll_sys_locked)
|
||||
|
@ -32,19 +32,29 @@ fpga_reset #(
|
|||
);
|
||||
|
||||
example_soc #(
|
||||
.DTM_TYPE ("ECP5"),
|
||||
.SRAM_DEPTH (1 << 15),
|
||||
.DTM_TYPE ("ECP5"),
|
||||
.SRAM_DEPTH (1 << 15),
|
||||
.CLK_MHZ (50),
|
||||
|
||||
.EXTENSION_M (1),
|
||||
.EXTENSION_A (1),
|
||||
.EXTENSION_C (0),
|
||||
.EXTENSION_ZBA (0),
|
||||
.EXTENSION_ZBB (0),
|
||||
.EXTENSION_ZBC (0),
|
||||
.EXTENSION_ZBS (0),
|
||||
.CSR_COUNTER (0),
|
||||
.MUL_FAST (1),
|
||||
.MULDIV_UNROLL (1)
|
||||
.EXTENSION_M (1),
|
||||
.EXTENSION_A (1),
|
||||
.EXTENSION_C (0),
|
||||
.EXTENSION_ZBA (0),
|
||||
.EXTENSION_ZBB (0),
|
||||
.EXTENSION_ZBC (0),
|
||||
.EXTENSION_ZBS (0),
|
||||
.EXTENSION_ZBKB (0),
|
||||
.EXTENSION_ZIFENCEI (1),
|
||||
.EXTENSION_XH3BEXTM (0),
|
||||
.EXTENSION_XH3PMPM (0),
|
||||
.EXTENSION_XH3POWER (0),
|
||||
.CSR_COUNTER (1),
|
||||
.MUL_FAST (1),
|
||||
.MUL_FASTER (0),
|
||||
.MULH_FAST (0),
|
||||
.MULDIV_UNROLL (1),
|
||||
.FAST_BRANCHCMP (1),
|
||||
.BRANCH_PREDICTOR (1)
|
||||
) soc_u (
|
||||
.clk (clk_sys),
|
||||
.rst_n (rst_n_sys),
|
||||
|
|
|
@ -9,8 +9,9 @@
|
|||
`default_nettype none
|
||||
|
||||
module example_soc #(
|
||||
parameter DTM_TYPE = "JTAG", // can be "JTAG" or "ECP5"
|
||||
parameter SRAM_DEPTH = 1 << 15, // default 32 kwords -> 128 kB
|
||||
parameter DTM_TYPE = "JTAG", // Can be "JTAG" or "ECP5"
|
||||
parameter SRAM_DEPTH = 1 << 15, // Default 32 kwords -> 128 kB
|
||||
parameter CLK_MHZ = 12, // For timer timebase
|
||||
|
||||
`include "hazard3_config.vh"
|
||||
) (
|
||||
|
@ -262,6 +263,8 @@ hazard3_cpu_1port #(
|
|||
.EXTENSION_ZBKB (EXTENSION_ZBKB),
|
||||
.EXTENSION_ZIFENCEI (EXTENSION_ZIFENCEI),
|
||||
.EXTENSION_XH3BEXTM (EXTENSION_XH3BEXTM),
|
||||
.EXTENSION_XH3IRQ (EXTENSION_XH3IRQ),
|
||||
.EXTENSION_XH3PMPM (EXTENSION_XH3PMPM),
|
||||
.EXTENSION_XH3POWER (EXTENSION_XH3POWER),
|
||||
.CSR_COUNTER (CSR_COUNTER),
|
||||
.U_MODE (U_MODE),
|
||||
|
@ -538,30 +541,43 @@ uart_mini uart_u (
|
|||
.dreq (/* unused */)
|
||||
);
|
||||
|
||||
// hazard3_riscv_timer timer_u (
|
||||
// .clk (clk),
|
||||
// .rst_n (rst_n),
|
||||
// Microsecond timebase for timer
|
||||
|
||||
// .psel (timer_psel),
|
||||
// .penable (timer_penable),
|
||||
// .pwrite (timer_pwrite),
|
||||
// .paddr (timer_paddr),
|
||||
// .pwdata (timer_pwdata),
|
||||
// .prdata (timer_prdata),
|
||||
// .pready (timer_pready),
|
||||
// .pslverr (timer_pslverr),
|
||||
reg [$clog2(CLK_MHZ)-1:0] timer_tick_ctr;
|
||||
reg timer_tick;
|
||||
|
||||
// .dbg_halt (&hart_halted),
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
timer_tick_ctr <= {$clog2(CLK_MHZ){1'b0}};
|
||||
timer_tick <= 1'b0;
|
||||
end else begin
|
||||
if (|timer_tick_ctr) begin
|
||||
timer_tick_ctr <= timer_tick_ctr - 1'b1;
|
||||
end else begin
|
||||
timer_tick_ctr <= CLK_MHZ - 1;
|
||||
end
|
||||
timer_tick <= ~|timer_tick_ctr;
|
||||
end
|
||||
end
|
||||
|
||||
// // Tie high for 64-cycle timebase:
|
||||
// .tick (1'b1),
|
||||
hazard3_riscv_timer timer_u (
|
||||
.clk (clk),
|
||||
.rst_n (rst_n),
|
||||
|
||||
// .timer_irq (timer_irq)
|
||||
// );
|
||||
.psel (timer_psel),
|
||||
.penable (timer_penable),
|
||||
.pwrite (timer_pwrite),
|
||||
.paddr (timer_paddr),
|
||||
.pwdata (timer_pwdata),
|
||||
.prdata (timer_prdata),
|
||||
.pready (timer_pready),
|
||||
.pslverr (timer_pslverr),
|
||||
|
||||
assign timer_pslverr = 1'b0;
|
||||
assign timer_pready = 1'b1;
|
||||
assign timer_prdata = 32'h0;
|
||||
assign timer_irq = 1'b0;
|
||||
.dbg_halt (&hart_halted),
|
||||
|
||||
.tick (timer_tick),
|
||||
|
||||
.timer_irq (timer_irq)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
file hazard3_riscv_timer.v
|
||||
file ../../../hdl/debug/cdc/hazard3_sync_1bit.v
|
|
@ -0,0 +1,142 @@
|
|||
/*****************************************************************************\
|
||||
| Copyright (C) 2022 Luke Wren |
|
||||
| SPDX-License-Identifier: Apache-2.0 |
|
||||
\*****************************************************************************/
|
||||
|
||||
`default_nettype none
|
||||
|
||||
// Basic implementation of standard 64-bit RISC-V timer with 32-bit APB.
|
||||
|
||||
// TICK_IS_NRZ = 1: tick is an NRZ signal that is asynchronous to clk.
|
||||
// TICK_IS_NRZ = 0: tick is a level-sensitive signal that is synchronous to clk.
|
||||
|
||||
module hazard3_riscv_timer #(
|
||||
parameter TICK_IS_NRZ = 0
|
||||
) (
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
input wire [15:0] paddr,
|
||||
input wire psel,
|
||||
input wire penable,
|
||||
input wire pwrite,
|
||||
input wire [31:0] pwdata,
|
||||
output reg [31:0] prdata,
|
||||
output wire pready,
|
||||
output wire pslverr,
|
||||
|
||||
input wire dbg_halt,
|
||||
input wire tick,
|
||||
|
||||
output reg timer_irq
|
||||
);
|
||||
|
||||
localparam ADDR_CTRL = 16'h0000;
|
||||
localparam ADDR_MTIME = 16'h0008;
|
||||
localparam ADDR_MTIMEH = 16'h000c;
|
||||
localparam ADDR_MTIMECMP = 16'h0010;
|
||||
localparam ADDR_MTIMECMPH = 16'h0014;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Timer tick logic
|
||||
|
||||
wire tick_event;
|
||||
|
||||
generate
|
||||
if (TICK_IS_NRZ) begin: edge_detect
|
||||
|
||||
wire tick_nrz_sync;
|
||||
|
||||
hazard3_sync_1bit tick_sync_u (
|
||||
.clk (clk),
|
||||
.rst_n (rst_n),
|
||||
.i (tick_nrz),
|
||||
.o (tick_nrz_sync)
|
||||
);
|
||||
|
||||
reg tick_nrz_prev;
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
tick_nrz_prev <= 1'b0;
|
||||
end else begin
|
||||
tick_nrz_prev <= tick_nrz_sync;
|
||||
end
|
||||
end
|
||||
|
||||
assign tick_event = tick_nrz_sync ^ tick_nrz_sync_prev;
|
||||
|
||||
end else begin: no_edge_detect
|
||||
|
||||
assign tick_event = tick;
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
||||
reg ctrl_en;
|
||||
wire tick_now = tick_event && ctrl_en && !dbg_halt;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Counter registers
|
||||
|
||||
wire bus_write = pwrite && psel && penable;
|
||||
wire bus_read = !pwrite && psel && penable;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
ctrl_en <= 1'b1;
|
||||
end else if (bus_write && paddr == ADDR_CTRL) begin
|
||||
ctrl_en <= pwdata[0];
|
||||
end
|
||||
end
|
||||
|
||||
reg [63:0] mtime;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
mtime <= 64'h0;
|
||||
end else begin
|
||||
if (tick_now)
|
||||
mtime <= mtime + 1'b1;
|
||||
if (bus_write && paddr == ADDR_MTIME)
|
||||
mtime[31:0] <= pwdata;
|
||||
if (bus_write && paddr == ADDR_MTIMEH)
|
||||
mtime[63:32] <= pwdata;
|
||||
end
|
||||
end
|
||||
|
||||
// mtimecmp is stored inverted for minor LUT savings on iCE40
|
||||
reg [63:0] mtimecmp;
|
||||
wire [64:0] cmp_diff = {1'b0, mtime} + {1'b0, mtimecmp} + 65'd1;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
mtimecmp <= 64'h0;
|
||||
timer_irq <= 1'b0;
|
||||
end else begin
|
||||
if (bus_write && paddr == ADDR_MTIMECMP)
|
||||
mtimecmp[31:0] <= ~pwdata;
|
||||
if (bus_write && paddr == ADDR_MTIMECMPH)
|
||||
mtimecmp[63:32] <= ~pwdata;
|
||||
timer_irq <= cmp_diff[64];
|
||||
end
|
||||
end
|
||||
|
||||
always @ (*) begin
|
||||
case (paddr)
|
||||
ADDR_CTRL: prdata = {31'h0, ctrl_en};
|
||||
ADDR_MTIME: prdata = mtime[31:0];
|
||||
ADDR_MTIMEH: prdata = mtime[63:32];
|
||||
ADDR_MTIMECMP: prdata = ~mtimecmp[31:0];
|
||||
ADDR_MTIMECMPH: prdata = ~mtimecmp[63:32];
|
||||
default: prdata = 32'h0;
|
||||
endcase
|
||||
end
|
||||
|
||||
assign pready = 1'b1;
|
||||
assign pslverr = 1'b0;
|
||||
|
||||
endmodule
|
||||
|
||||
`ifndef YOSYS
|
||||
`default_nettype none
|
||||
`endif
|
|
@ -8,6 +8,10 @@ list $HDL/hazard3.f
|
|||
list $HDL/debug/dtm/hazard3_jtag_dtm.f
|
||||
list $HDL/debug/dm/hazard3_dm.f
|
||||
|
||||
# RISC-V timer
|
||||
|
||||
list peri/hazard3_riscv_timer.f
|
||||
|
||||
# Generic SoC components from libfpga
|
||||
|
||||
file ../libfpga/common/reset_sync.v
|
||||
|
|
Loading…
Reference in New Issue