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 (
|
) servile (
|
||||||
.i_clk(i_clk),
|
.i_clk(i_clk),
|
||||||
.i_rst(rst),
|
.i_rst(rst),
|
||||||
.i_timer_irq(1'b0), //timer_irq),
|
.i_timer_irq(timer_irq),
|
||||||
|
|
||||||
//Memory interface
|
//Memory interface
|
||||||
.o_wb_mem_adr(wb_mem_adr),
|
.o_wb_mem_adr(wb_mem_adr),
|
||||||
|
|||||||
@@ -23,6 +23,26 @@ module top_generic #(
|
|||||||
.clk_out_15(clk_15)
|
.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_A;
|
||||||
wire [31:0] GPIO_B;
|
wire [31:0] GPIO_B;
|
||||||
wire [31:0] GPIO_C;
|
wire [31:0] GPIO_C;
|
||||||
@@ -35,7 +55,7 @@ module top_generic #(
|
|||||||
.sim(sim)
|
.sim(sim)
|
||||||
) mcu (
|
) mcu (
|
||||||
.i_clk(clk_15),
|
.i_clk(clk_15),
|
||||||
.i_rst(!aresetn),
|
.i_rst(sys_reset),
|
||||||
.i_GPI_A(GPIO_A),
|
.i_GPI_A(GPIO_A),
|
||||||
.i_GPI_B(GPIO_B),
|
.i_GPI_B(GPIO_B),
|
||||||
.i_GPI_C(GPIO_C),
|
.i_GPI_C(GPIO_C),
|
||||||
@@ -55,7 +75,7 @@ module top_generic #(
|
|||||||
.FS_HZ(80_000)
|
.FS_HZ(80_000)
|
||||||
) nco (
|
) nco (
|
||||||
.clk (clk_15),
|
.clk (clk_15),
|
||||||
.rst_n (aresetn),
|
.rst_n (sys_resetn),
|
||||||
.freq_hz(GPIO_A),
|
.freq_hz(GPIO_A),
|
||||||
.sin_q15(sin_q15),
|
.sin_q15(sin_q15),
|
||||||
.cos_q15(),
|
.cos_q15(),
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ module jtag_wb_bridge #(
|
|||||||
reg [31:0] wb_dat_r;
|
reg [31:0] wb_dat_r;
|
||||||
reg [3:0] wb_sel_r;
|
reg [3:0] wb_sel_r;
|
||||||
reg wb_we_r;
|
reg wb_we_r;
|
||||||
reg cmd_reset_pulse_r;
|
reg cmd_reset_level_r;
|
||||||
reg [31:0] resp_addr_r;
|
reg [31:0] resp_addr_r;
|
||||||
reg [7:0] resp_data_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_we = wb_we_r;
|
||||||
assign o_wb_cyc = wb_busy;
|
assign o_wb_cyc = wb_busy;
|
||||||
assign o_wb_stb = 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
|
always @(posedge i_clk) begin
|
||||||
if (i_rst) begin
|
if (i_rst) begin
|
||||||
@@ -148,7 +148,7 @@ module jtag_wb_bridge #(
|
|||||||
wb_dat_r <= 32'b0;
|
wb_dat_r <= 32'b0;
|
||||||
wb_sel_r <= 4'b0000;
|
wb_sel_r <= 4'b0000;
|
||||||
wb_we_r <= 1'b0;
|
wb_we_r <= 1'b0;
|
||||||
cmd_reset_pulse_r <= 1'b0;
|
cmd_reset_level_r <= 1'b0;
|
||||||
resp_addr_r <= 32'b0;
|
resp_addr_r <= 32'b0;
|
||||||
resp_data_r <= 8'b0;
|
resp_data_r <= 8'b0;
|
||||||
end else begin
|
end else begin
|
||||||
@@ -157,12 +157,11 @@ module jtag_wb_bridge #(
|
|||||||
s_req_sync_3 <= s_req_sync_2;
|
s_req_sync_3 <= s_req_sync_2;
|
||||||
s_cmd_sync_1 <= j_cmd_hold;
|
s_cmd_sync_1 <= j_cmd_hold;
|
||||||
s_cmd_sync_2 <= s_cmd_sync_1;
|
s_cmd_sync_2 <= s_cmd_sync_1;
|
||||||
cmd_reset_pulse_r <= 1'b0;
|
|
||||||
|
|
||||||
if (req_pulse && !wb_busy) begin
|
if (req_pulse && !wb_busy) begin
|
||||||
wb_busy <= 1'b1;
|
wb_busy <= 1'b1;
|
||||||
wb_we_r <= cmd_we;
|
wb_we_r <= cmd_we;
|
||||||
wb_adr_r <= cmd_addr;
|
wb_adr_r <= cmd_addr;
|
||||||
|
cmd_reset_level_r <= cmd_reset;
|
||||||
|
|
||||||
case (req_lane)
|
case (req_lane)
|
||||||
2'b00: begin wb_sel_r <= 4'b0001; wb_dat_r <= {24'b0, cmd_wdata}; end
|
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
|
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
|
default: begin wb_sel_r <= 4'b1000; wb_dat_r <= {cmd_wdata, 24'b0}; end
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
cmd_reset_pulse_r <= cmd_reset;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if (wb_busy && i_wb_ack) begin
|
if (wb_busy && i_wb_ack) begin
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ module tb_top_generic();
|
|||||||
|
|
||||||
// 100 MHz board input clock
|
// 100 MHz board input clock
|
||||||
initial aclk = 1'b0;
|
initial aclk = 1'b0;
|
||||||
always #5 aclk = ~aclk;
|
always #33.33 aclk = ~aclk;
|
||||||
|
|
||||||
// Hold reset low, then release
|
// Hold reset low, then release
|
||||||
initial begin
|
initial begin
|
||||||
@@ -39,7 +39,7 @@ module tb_top_generic();
|
|||||||
$dumpvars(0, tb_top_generic);
|
$dumpvars(0, tb_top_generic);
|
||||||
|
|
||||||
// Let firmware run for a while.
|
// Let firmware run for a while.
|
||||||
#5_000_000;
|
#2_000_000;
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ SECTIONS
|
|||||||
{
|
{
|
||||||
__bss_start = .;
|
__bss_start = .;
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
*(.sbss .sbss.*)
|
||||||
|
*(.scommon)
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
__bss_end = .;
|
__bss_end = .;
|
||||||
} > RAM
|
} > RAM
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
.section .text.init
|
.section .text.init
|
||||||
.globl _start
|
.globl _start
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
|
|
||||||
_start:
|
_start:
|
||||||
la sp, __stack_top
|
la sp, __stack_top
|
||||||
|
|
||||||
@@ -21,3 +20,80 @@ _start:
|
|||||||
j 3b
|
j 3b
|
||||||
|
|
||||||
.size _start, .-_start
|
.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>
|
#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(){
|
void main(){
|
||||||
|
irq_init();
|
||||||
|
|
||||||
|
*LEDGR = 3;
|
||||||
|
*TIMER = 18400;
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
for(int i=1000; i<10000; i++){
|
for(int i=1000; i<10000; i++){
|
||||||
*R_FREQ = 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