First pass at a 64-bit system timer
This commit is contained in:
		
							parent
							
								
									924967ee72
								
							
						
					
					
						commit
						4aba165166
					
				| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					file hazard3_riscv_timer.v
 | 
				
			||||||
 | 
					file ../debug/cdc/hazard3_sync_1bit.v
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,120 @@
 | 
				
			||||||
 | 
					/**********************************************************************
 | 
				
			||||||
 | 
					 * DO WHAT THE FUCK YOU WANT TO AND DON'T BLAME US PUBLIC LICENSE     *
 | 
				
			||||||
 | 
					 *                    Version 3, April 2008                           *
 | 
				
			||||||
 | 
					 *                                                                    *
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Luke Wren                                       *
 | 
				
			||||||
 | 
					 *                                                                    *
 | 
				
			||||||
 | 
					 * Everyone is permitted to copy and distribute verbatim or modified  *
 | 
				
			||||||
 | 
					 * copies of this license document and accompanying software, and     *
 | 
				
			||||||
 | 
					 * changing either is allowed.                                        *
 | 
				
			||||||
 | 
					 *                                                                    *
 | 
				
			||||||
 | 
					 *   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION  *
 | 
				
			||||||
 | 
					 *                                                                    *
 | 
				
			||||||
 | 
					 * 0. You just DO WHAT THE FUCK YOU WANT TO.                          *
 | 
				
			||||||
 | 
					 * 1. We're NOT RESPONSIBLE WHEN IT DOESN'T FUCKING WORK.             *
 | 
				
			||||||
 | 
					 *                                                                    *
 | 
				
			||||||
 | 
					 *********************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Implementation of standard RISC-V timer (mtime/mtimeh mtimecmp/mtimecmph)
 | 
				
			||||||
 | 
					// accessed over 32-bit data bus. Ticks on both edges of tick_nrz, which is
 | 
				
			||||||
 | 
					// provided by some external timebase, and is assumed to be asynchronous to
 | 
				
			||||||
 | 
					// clk. Nothing fancy, just a simple implementation of the spec.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module hazard3_riscv_timer (
 | 
				
			||||||
 | 
						input  wire               clk,
 | 
				
			||||||
 | 
						input  wire               rst_n,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						input  wire               psel,
 | 
				
			||||||
 | 
						input  wire               penable,
 | 
				
			||||||
 | 
						input  wire               pwrite,
 | 
				
			||||||
 | 
						input  wire [7:0]         paddr,
 | 
				
			||||||
 | 
						input  wire [31:0]        pwdata,
 | 
				
			||||||
 | 
						output reg  [31:0]        prdata,
 | 
				
			||||||
 | 
						output wire               pready,
 | 
				
			||||||
 | 
						output wire               pslverr,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						input  wire               dbg_halt,
 | 
				
			||||||
 | 
						input  wire               tick_nrz,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output reg                timer_irq
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					wire bus_write = pwrite && psel && penable;
 | 
				
			||||||
 | 
					wire bus_read = !pwrite && psel && penable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					localparam W_ADDR = 8;
 | 
				
			||||||
 | 
					localparam W_DATA = 32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					localparam ADDR_CTRL      = 8'h00;
 | 
				
			||||||
 | 
					localparam ADDR_MTIME     = 8'h08;
 | 
				
			||||||
 | 
					localparam ADDR_MTIMEH    = 8'h0c;
 | 
				
			||||||
 | 
					localparam ADDR_MTIMECMP  = 8'h10;
 | 
				
			||||||
 | 
					localparam ADDR_MTIMECMPH = 8'h14;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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)
 | 
				
			||||||
 | 
						if (!rst_n)
 | 
				
			||||||
 | 
							tick_nrz_prev <= 1'b0;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							tick_nrz_prev <= tick_nrz_sync;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					reg ctrl_en;
 | 
				
			||||||
 | 
					always @ (posedge clk or negedge rst_n)
 | 
				
			||||||
 | 
						if (!rst_n)
 | 
				
			||||||
 | 
							ctrl_en <= 1'b1;
 | 
				
			||||||
 | 
						else if (bus_write && paddr == ADDR_CTRL)
 | 
				
			||||||
 | 
							ctrl_en <= pwdata[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					wire tick = ctrl_en && !dbg_halt && tick_nrz_prev != tick_nrz_sync;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					reg [63:0] mtime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					always @ (posedge clk or negedge rst_n) begin
 | 
				
			||||||
 | 
						if (!rst_n) begin
 | 
				
			||||||
 | 
							mtime <= 64'h0;
 | 
				
			||||||
 | 
						end else begin
 | 
				
			||||||
 | 
							if (tick)
 | 
				
			||||||
 | 
								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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					reg [63:0] mtimecmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 <= mtime >= mtimecmp; // oof
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					always @ (*) begin
 | 
				
			||||||
 | 
						case (paddr)
 | 
				
			||||||
 | 
						ADDR_CTRL:      prdata = {{W_DATA-1{1'b0}}, 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 = {W_DATA{1'b0}};
 | 
				
			||||||
 | 
						endcase
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
		Loading…
	
		Reference in New Issue