TImer working with tests
TODO: think of other way of shifting in data. Bit errors make uploading difficult
This commit is contained in:
@@ -88,7 +88,7 @@ module mcu #(
|
||||
) servile (
|
||||
.i_clk(i_clk),
|
||||
.i_rst(rst),
|
||||
.i_timer_irq(1'b0), //timer_irq),
|
||||
.i_timer_irq(timer_irq),
|
||||
|
||||
//Memory interface
|
||||
.o_wb_mem_adr(wb_mem_adr),
|
||||
|
||||
@@ -23,6 +23,26 @@ module top_generic #(
|
||||
.clk_out_15(clk_15)
|
||||
);
|
||||
|
||||
// Reset conditioning for button input:
|
||||
// - asynchronous assert when button is pressed (aresetn=0)
|
||||
// - synchronous, debounced deassert in clk_15 domain
|
||||
localparam [17:0] RESET_RELEASE_CYCLES = sim ? 18'd16 : 18'd150000; // ~10 ms @ 15 MHz on hardware
|
||||
reg [17:0] rst_cnt = 18'd0;
|
||||
reg sys_reset_r = 1'b1;
|
||||
always @(posedge clk_15 or negedge aresetn) begin
|
||||
if (!aresetn) begin
|
||||
rst_cnt <= 18'd0;
|
||||
sys_reset_r <= 1'b1;
|
||||
end else if (sys_reset_r) begin
|
||||
if (rst_cnt == RESET_RELEASE_CYCLES - 1'b1)
|
||||
sys_reset_r <= 1'b0;
|
||||
else
|
||||
rst_cnt <= rst_cnt + 1'b1;
|
||||
end
|
||||
end
|
||||
wire sys_reset = sys_reset_r;
|
||||
wire sys_resetn = !sys_reset_r;
|
||||
|
||||
wire [31:0] GPIO_A;
|
||||
wire [31:0] GPIO_B;
|
||||
wire [31:0] GPIO_C;
|
||||
@@ -35,7 +55,7 @@ module top_generic #(
|
||||
.sim(sim)
|
||||
) mcu (
|
||||
.i_clk(clk_15),
|
||||
.i_rst(!aresetn),
|
||||
.i_rst(sys_reset),
|
||||
.i_GPI_A(GPIO_A),
|
||||
.i_GPI_B(GPIO_B),
|
||||
.i_GPI_C(GPIO_C),
|
||||
@@ -55,7 +75,7 @@ module top_generic #(
|
||||
.FS_HZ(80_000)
|
||||
) nco (
|
||||
.clk (clk_15),
|
||||
.rst_n (aresetn),
|
||||
.rst_n (sys_resetn),
|
||||
.freq_hz(GPIO_A),
|
||||
.sin_q15(sin_q15),
|
||||
.cos_q15(),
|
||||
|
||||
@@ -107,7 +107,7 @@ module jtag_wb_bridge #(
|
||||
reg [31:0] wb_dat_r;
|
||||
reg [3:0] wb_sel_r;
|
||||
reg wb_we_r;
|
||||
reg cmd_reset_pulse_r;
|
||||
reg cmd_reset_level_r;
|
||||
reg [31:0] resp_addr_r;
|
||||
reg [7:0] resp_data_r;
|
||||
|
||||
@@ -133,7 +133,7 @@ module jtag_wb_bridge #(
|
||||
assign o_wb_we = wb_we_r;
|
||||
assign o_wb_cyc = wb_busy;
|
||||
assign o_wb_stb = wb_busy;
|
||||
assign o_cmd_reset = cmd_reset_pulse_r;
|
||||
assign o_cmd_reset = cmd_reset_level_r;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_rst) begin
|
||||
@@ -148,7 +148,7 @@ module jtag_wb_bridge #(
|
||||
wb_dat_r <= 32'b0;
|
||||
wb_sel_r <= 4'b0000;
|
||||
wb_we_r <= 1'b0;
|
||||
cmd_reset_pulse_r <= 1'b0;
|
||||
cmd_reset_level_r <= 1'b0;
|
||||
resp_addr_r <= 32'b0;
|
||||
resp_data_r <= 8'b0;
|
||||
end else begin
|
||||
@@ -157,12 +157,11 @@ module jtag_wb_bridge #(
|
||||
s_req_sync_3 <= s_req_sync_2;
|
||||
s_cmd_sync_1 <= j_cmd_hold;
|
||||
s_cmd_sync_2 <= s_cmd_sync_1;
|
||||
cmd_reset_pulse_r <= 1'b0;
|
||||
|
||||
if (req_pulse && !wb_busy) begin
|
||||
wb_busy <= 1'b1;
|
||||
wb_we_r <= cmd_we;
|
||||
wb_adr_r <= cmd_addr;
|
||||
cmd_reset_level_r <= cmd_reset;
|
||||
|
||||
case (req_lane)
|
||||
2'b00: begin wb_sel_r <= 4'b0001; wb_dat_r <= {24'b0, cmd_wdata}; end
|
||||
@@ -170,8 +169,6 @@ module jtag_wb_bridge #(
|
||||
2'b10: begin wb_sel_r <= 4'b0100; wb_dat_r <= {8'b0, cmd_wdata, 16'b0}; end
|
||||
default: begin wb_sel_r <= 4'b1000; wb_dat_r <= {cmd_wdata, 24'b0}; end
|
||||
endcase
|
||||
|
||||
cmd_reset_pulse_r <= cmd_reset;
|
||||
end
|
||||
|
||||
if (wb_busy && i_wb_ack) begin
|
||||
|
||||
@@ -11,7 +11,7 @@ module tb_top_generic();
|
||||
|
||||
// 100 MHz board input clock
|
||||
initial aclk = 1'b0;
|
||||
always #5 aclk = ~aclk;
|
||||
always #33.33 aclk = ~aclk;
|
||||
|
||||
// Hold reset low, then release
|
||||
initial begin
|
||||
@@ -39,7 +39,7 @@ module tb_top_generic();
|
||||
$dumpvars(0, tb_top_generic);
|
||||
|
||||
// Let firmware run for a while.
|
||||
#5_000_000;
|
||||
#2_000_000;
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
@@ -24,6 +24,8 @@ SECTIONS
|
||||
{
|
||||
__bss_start = .;
|
||||
*(.bss .bss.*)
|
||||
*(.sbss .sbss.*)
|
||||
*(.scommon)
|
||||
*(COMMON)
|
||||
__bss_end = .;
|
||||
} > RAM
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
.section .text.init
|
||||
.globl _start
|
||||
.type _start, @function
|
||||
|
||||
_start:
|
||||
la sp, __stack_top
|
||||
|
||||
@@ -21,3 +20,80 @@ _start:
|
||||
j 3b
|
||||
|
||||
.size _start, .-_start
|
||||
|
||||
|
||||
.section .text
|
||||
.globl trap_entry
|
||||
.type trap_entry, @function
|
||||
trap_entry:
|
||||
# Save full integer context (except x0/x2) because an interrupt can
|
||||
# preempt code with live values in any register, not just caller-saved.
|
||||
addi sp, sp, -128
|
||||
sw ra, 124(sp)
|
||||
sw gp, 120(sp)
|
||||
sw tp, 116(sp)
|
||||
sw t0, 112(sp)
|
||||
sw t1, 108(sp)
|
||||
sw t2, 104(sp)
|
||||
sw s0, 100(sp)
|
||||
sw s1, 96(sp)
|
||||
sw a0, 92(sp)
|
||||
sw a1, 88(sp)
|
||||
sw a2, 84(sp)
|
||||
sw a3, 80(sp)
|
||||
sw a4, 76(sp)
|
||||
sw a5, 72(sp)
|
||||
sw a6, 68(sp)
|
||||
sw a7, 64(sp)
|
||||
sw s2, 60(sp)
|
||||
sw s3, 56(sp)
|
||||
sw s4, 52(sp)
|
||||
sw s5, 48(sp)
|
||||
sw s6, 44(sp)
|
||||
sw s7, 40(sp)
|
||||
sw s8, 36(sp)
|
||||
sw s9, 32(sp)
|
||||
sw s10, 28(sp)
|
||||
sw s11, 24(sp)
|
||||
sw t3, 20(sp)
|
||||
sw t4, 16(sp)
|
||||
sw t5, 12(sp)
|
||||
sw t6, 8(sp)
|
||||
|
||||
csrr t0, mcause
|
||||
li t1, 0x80000007 # machine timer interrupt (RV32)
|
||||
bne t0, t1, 1f
|
||||
call timer_isr # C function that ACKs/clears the timer so i_timer_irq goes low
|
||||
1:
|
||||
lw t6, 8(sp)
|
||||
lw t5, 12(sp)
|
||||
lw t4, 16(sp)
|
||||
lw t3, 20(sp)
|
||||
lw s11, 24(sp)
|
||||
lw s10, 28(sp)
|
||||
lw s9, 32(sp)
|
||||
lw s8, 36(sp)
|
||||
lw s7, 40(sp)
|
||||
lw s6, 44(sp)
|
||||
lw s5, 48(sp)
|
||||
lw s4, 52(sp)
|
||||
lw s3, 56(sp)
|
||||
lw s2, 60(sp)
|
||||
lw a7, 64(sp)
|
||||
lw a6, 68(sp)
|
||||
lw a5, 72(sp)
|
||||
lw a4, 76(sp)
|
||||
lw a3, 80(sp)
|
||||
lw a2, 84(sp)
|
||||
lw a1, 88(sp)
|
||||
lw a0, 92(sp)
|
||||
lw s1, 96(sp)
|
||||
lw s0, 100(sp)
|
||||
lw t2, 104(sp)
|
||||
lw t1, 108(sp)
|
||||
lw t0, 112(sp)
|
||||
lw tp, 116(sp)
|
||||
lw gp, 120(sp)
|
||||
lw ra, 124(sp)
|
||||
addi sp, sp, 128
|
||||
mret
|
||||
|
||||
@@ -1,14 +1,45 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#define GPIO_BASE 0x40000000u
|
||||
#define GPIO_BASE 0x40000000u
|
||||
static volatile uint32_t * const R_FREQ = (volatile uint32_t *)(GPIO_BASE+0);
|
||||
static volatile uint32_t * const LEDS = (volatile uint32_t *)(GPIO_BASE+4);
|
||||
static volatile uint32_t * const LEDGR = (volatile uint32_t *)(GPIO_BASE+8);
|
||||
|
||||
static volatile uint32_t * const R_FREQ = (volatile uint32_t *)GPIO_BASE;
|
||||
#define TIMER_BASE 0x40010000u
|
||||
static volatile uint32_t * const TIMER = (volatile uint32_t *)(TIMER_BASE+0);
|
||||
|
||||
#define MSTATUS_MIE (1u << 3)
|
||||
#define MIE_MTIE (1u << 7)
|
||||
|
||||
extern void trap_entry();
|
||||
|
||||
static inline void irq_init() {
|
||||
/* mtvec first */
|
||||
asm volatile ("csrw mtvec, %0" :: "r"(trap_entry));
|
||||
|
||||
/* enable machine timer interrupt */
|
||||
asm volatile ("csrs mie, %0" :: "r"(MIE_MTIE));
|
||||
|
||||
/* global enable last */
|
||||
asm volatile ("csrs mstatus, %0" :: "r"(MSTATUS_MIE));
|
||||
}
|
||||
|
||||
void timer_isr(){
|
||||
static int set = 0;
|
||||
*TIMER = 18400;
|
||||
*LEDGR = ~(*LEDGR);
|
||||
}
|
||||
|
||||
void main(){
|
||||
irq_init();
|
||||
|
||||
*LEDGR = 3;
|
||||
*TIMER = 18400;
|
||||
|
||||
for(;;){
|
||||
for(int i=1000; i<10000; i++){
|
||||
*R_FREQ = i;
|
||||
// for(int j=0; j<100; j++) asm volatile("nop");
|
||||
for(int j=0; j<100; j++) asm volatile("nop");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user