add perips

Signed-off-by: liangkangnan <liangkangnan@163.com>
pull/4/head
liangkangnan 2021-05-14 21:00:57 +08:00
parent 5811bdde13
commit 6e466fbbf7
23 changed files with 666 additions and 317 deletions

View File

@ -37,6 +37,7 @@
../rtl/perips/rom.sv
../rtl/perips/timer.sv
../rtl/perips/uart.sv
../rtl/perips/machine_timer.sv
../rtl/sys_bus/obi_interconnect.sv
../rtl/sys_bus/obi_interconnect_master_sel.sv

View File

@ -40,6 +40,9 @@
// UART
`define UART_ADDR_MASK ~32'hffff
`define UART_ADDR_BASE 32'h50000000
// Machine Timer
`define MTIMER_ADDR_MASK ~32'hffff
`define MTIMER_ADDR_BASE 32'hA0000000
// SIM CTRL
`define SIM_CTRL_ADDR_MASK ~32'hffff
`define SIM_CTRL_ADDR_BASE 32'hE0000000

View File

@ -89,14 +89,14 @@ module exception (
localparam FAST_INT_OFFSET = 44;
localparam S_IDLE = 4'b0001;
localparam S_W_MEPC = 4'b0010;
localparam S_W_DCSR = 4'b0100;
localparam S_ASSERT = 4'b1000;
localparam S_IDLE = 5'b00001;
localparam S_W_MEPC = 5'b00010;
localparam S_W_DCSR = 5'b00100;
localparam S_ASSERT = 5'b01000;
localparam S_W_MSTATUS = 5'b10000;
reg debug_mode_d, debug_mode_q;
reg[3:0] state_d, state_q;
reg[4:0] state_d, state_q;
reg[31:0] assert_addr_d, assert_addr_q;
reg[31:0] return_addr_d, return_addr_q;
reg csr_we;
@ -239,13 +239,13 @@ module exception (
case (state_q)
S_IDLE: begin
if (int_or_exception_req) begin
if (int_or_exception_req & (!debug_mode_q)) begin
csr_we = 1'b1;
csr_waddr = {20'h0, `CSR_MCAUSE};
csr_wdata = int_or_exception_cause;
assert_addr_d = mtvec_i + int_or_exception_offset;
return_addr_d = inst_addr_i;
state_d = S_W_MEPC;
state_d = S_W_MSTATUS;
end else if (debug_mode_req) begin
debug_mode_d = 1'b1;
if (enter_debug_cause_debugger_req |
@ -269,6 +269,9 @@ module exception (
end
end else if (inst_mret_i) begin
assert_addr_d = mepc_i;
csr_we = 1'b1;
csr_waddr = {20'h0, `CSR_MSTATUS};
csr_wdata = {mstatus_i[31:4], 1'b1, mstatus_i[2:0]};
state_d = S_ASSERT;
end else if (inst_dret_i) begin
assert_addr_d = dpc_i;
@ -277,6 +280,13 @@ module exception (
end
end
S_W_MSTATUS: begin
csr_we = 1'b1;
csr_waddr = {20'h0, `CSR_MSTATUS};
csr_wdata = {mstatus_i[31:4], 1'b0, mstatus_i[2:0]};
state_d = S_W_MEPC;
end
S_W_MEPC: begin
csr_we = 1'b1;
csr_waddr = {20'h0, `CSR_MEPC};

View File

@ -46,8 +46,8 @@ module gpio(
assign reg_ctrl = gpio_ctrl;
assign reg_data = gpio_data;
wire wen = we_i & req_valid_i;
wire ren = (~we_i) & req_valid_i;
wire wen = we_i;
wire ren = (~we_i);
wire write_reg_ctrl_en = wen & (addr_i[3:0] == GPIO_CTRL);
wire write_reg_data_en = wen & (addr_i[3:0] == GPIO_DATA);

117
rtl/perips/machine_timer.sv Normal file
View File

@ -0,0 +1,117 @@
/*
Copyright 2021 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
module machine_timer(
input wire clk,
input wire rst_n,
input wire[31:0] addr_i,
input wire[31:0] data_i,
input wire[3:0] sel_i,
input wire we_i,
output wire[31:0] data_o,
output wire irq_o
);
localparam mtime_ctrl_reg = 4'h0;
localparam mtime_cmp_reg = 4'h4;
localparam mtime_count_reg = 4'h8;
localparam start = 0;
localparam irq_pending = 1;
reg[31:0] mtime_ctrl_d, mtime_ctrl_q;
reg[31:0] mtime_cmp_d, mtime_cmp_q;
reg[31:0] mtime_count_q;
reg data_q;
wire[3:0] rw_addr = addr_i[3:0];
wire w0 = we_i & sel_i[0];
wire w1 = we_i & sel_i[1];
wire w2 = we_i & sel_i[2];
wire w3 = we_i & sel_i[3];
// write
always @ (*) begin
mtime_cmp_d = mtime_cmp_q;
mtime_ctrl_d = mtime_ctrl_q;
case (rw_addr)
mtime_ctrl_reg: begin
if (w0) begin
mtime_ctrl_d[0] = data_i[0];
mtime_ctrl_d[irq_pending] = mtime_ctrl_q & (~data_i[irq_pending]);
end
end
mtime_cmp_reg: begin
if (w0) mtime_cmp_d[7:0] = data_i[7:0];
if (w1) mtime_cmp_d[15:8] = data_i[15:8];
if (w2) mtime_cmp_d[23:16] = data_i[23:16];
if (w3) mtime_cmp_d[31:24] = data_i[31:24];
end
default:;
endcase
if (mtime_count_q == mtime_cmp_q) begin
mtime_ctrl_d[irq_pending] = 1'b1;
end
end
assign irq_o = mtime_ctrl_q[irq_pending] & mtime_ctrl_q[start];
// read
always @ (*) begin
data_q = 32'h0;
case (rw_addr)
mtime_ctrl_reg: data_q = mtime_ctrl_q;
mtime_cmp_reg: data_q = mtime_cmp_q;
mtime_count_reg: data_q = mtime_count_q;
default:;
endcase
end
assign data_o = data_q;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
mtime_ctrl_q <= 32'h0;
mtime_cmp_q <= 32'h0;
end else begin
mtime_ctrl_q <= mtime_ctrl_d;
mtime_cmp_q <= mtime_cmp_d;
end
end
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
mtime_count_q <= 32'h0;
end else begin
if (mtime_ctrl_q[start]) begin
mtime_count_q <= mtime_count_q + 1'b1;
if (mtime_count_q == mtime_cmp_q) begin
mtime_count_q <= 32'h0;
end
end else begin
mtime_count_q <= 32'h0;
end
end
end
endmodule

View File

@ -85,8 +85,8 @@ module uart(
// UART接收数据寄存器只读
reg[31:0] uart_rx;
wire wen = we_i & req_valid_i;
wire ren = (~we_i) & req_valid_i;
wire wen = we_i;
wire ren = (~we_i);
wire write_reg_ctrl_en = wen & (addr_i[7:0] == UART_CTRL);
wire write_reg_status_en = wen & (addr_i[7:0] == UART_STATUS);
wire write_reg_baud_en = wen & (addr_i[7:0] == UART_BAUD);

View File

@ -39,9 +39,9 @@ module tinyriscv_soc_top(
localparam int MASTERS = 3; // Number of master ports
`ifdef VERILATOR
localparam int SLAVES = 4; // Number of slave ports
localparam int SLAVES = 7; // Number of slave ports
`else
localparam int SLAVES = 3; // Number of slave ports
localparam int SLAVES = 6; // Number of slave ports
`endif
// masters
@ -53,8 +53,11 @@ module tinyriscv_soc_top(
localparam int Rom = 0;
localparam int Ram = 1;
localparam int JtagDevice = 2;
localparam int Mtimer = 3;
localparam int Gpio = 4;
localparam int Uart = 5;
`ifdef VERILATOR
localparam int SimCtrl = 3;
localparam int SimCtrl = 6;
`endif
@ -93,6 +96,12 @@ module tinyriscv_soc_top(
wire debug_req;
wire core_halted;
wire mtimer_irq;
wire[1:0] io_in;
wire[31:0] gpio_ctrl;
wire[31:0] gpio_data;
assign halted_ind_pin = core_halted;
tinyriscv_core #(
@ -120,7 +129,7 @@ module tinyriscv_soc_top(
.data_err_i (1'b0),
.irq_software_i (1'b0),
.irq_timer_i (1'b0),
.irq_timer_i (mtimer_irq),
.irq_external_i (1'b0),
.irq_fast_i (15'b0),
@ -129,7 +138,7 @@ module tinyriscv_soc_top(
assign slave_addr_mask[Rom] = `ROM_ADDR_MASK;
assign slave_addr_base[Rom] = `ROM_ADDR_BASE;
// 指令存储器
// 1.指令存储器
rom #(
.DP(`ROM_DEPTH)
) u_rom (
@ -144,7 +153,7 @@ module tinyriscv_soc_top(
assign slave_addr_mask[Ram] = `RAM_ADDR_MASK;
assign slave_addr_base[Ram] = `RAM_ADDR_BASE;
// 数据存储器
// 2.数据存储器
ram #(
.DP(`RAM_DEPTH)
) u_ram (
@ -157,17 +166,70 @@ module tinyriscv_soc_top(
.data_o (slave_rdata[Ram])
);
assign slave_addr_mask[Mtimer] = `MTIMER_ADDR_MASK;
assign slave_addr_base[Mtimer] = `MTIMER_ADDR_BASE;
// 3.机器定时器模块
machine_timer u_machine_timer(
.clk (clk),
.rst_n (ndmreset_n),
.addr_i (slave_addr[Mtimer]),
.data_i (slave_wdata[Mtimer]),
.sel_i (slave_be[Mtimer]),
.we_i (slave_we[Mtimer]),
.data_o (slave_rdata[Mtimer]),
.irq_o (mtimer_irq)
);
// IO0
assign gpio_pins[0] = (gpio_ctrl[1:0] == 2'b01)? gpio_data[0]: 1'bz;
assign io_in[0] = gpio_pins[0];
// IO1
assign gpio_pins[1] = (gpio_ctrl[3:2] == 2'b01)? gpio_data[1]: 1'bz;
assign io_in[1] = gpio_pins[1];
assign slave_addr_mask[Gpio] = `GPIO_ADDR_MASK;
assign slave_addr_base[Gpio] = `GPIO_ADDR_BASE;
// 4.GPIO模块
gpio u_gpio(
.clk (clk),
.rst_n (ndmreset_n),
.addr_i (slave_addr[Gpio]),
.data_i (slave_wdata[Gpio]),
.sel_i (slave_be[Gpio]),
.we_i (slave_we[Gpio]),
.data_o (slave_rdata[Gpio]),
.io_pin_i(io_in),
.reg_ctrl(gpio_ctrl),
.reg_data(gpio_data)
);
assign slave_addr_mask[Uart] = `UART_ADDR_MASK;
assign slave_addr_base[Uart] = `UART_ADDR_BASE;
// 5.串口模块
uart u_uart(
.clk (clk),
.rst_n (ndmreset_n),
.addr_i (slave_addr[Uart]),
.data_i (slave_wdata[Uart]),
.sel_i (slave_be[Uart]),
.we_i (slave_we[Uart]),
.data_o (slave_rdata[Uart]),
.tx_pin (uart_tx_pin),
.rx_pin (uart_rx_pin)
);
`ifdef VERILATOR
assign slave_addr_mask[SimCtrl] = `SIM_CTRL_ADDR_MASK;
assign slave_addr_base[SimCtrl] = `SIM_CTRL_ADDR_BASE;
// 6.仿真控制模块
sim_ctrl u_sim_ctrl(
.clk_i(clk),
.rst_ni(ndmreset_n),
.req_i(),
.gnt_o(),
.addr_i(slave_addr[SimCtrl]),
.we_i(slave_we[SimCtrl]),
.be_i(slave_be[SimCtrl]),
.clk_i (clk),
.rst_ni (ndmreset_n),
.req_i (),
.gnt_o (),
.addr_i (slave_addr[SimCtrl]),
.we_i (slave_we[SimCtrl]),
.be_i (slave_be[SimCtrl]),
.wdata_i(slave_wdata[SimCtrl]),
.rdata_o(slave_rdata[SimCtrl])
);

View File

@ -22,6 +22,7 @@ C_SRCS += $(BSP_DIR)/lib/utils.c
C_SRCS += $(BSP_DIR)/lib/xprintf.c
C_SRCS += $(BSP_DIR)/lib/uart.c
C_SRCS += $(BSP_DIR)/lib/sim_ctrl.c
C_SRCS += $(BSP_DIR)/lib/machine_timer.c
LINKER_SCRIPT := $(BSP_DIR)/link.lds

View File

@ -0,0 +1,16 @@
#ifndef _MACHINE_TIMER_H_
#define _MACHINE_TIMER_H_
#define MTIMER_BASE (0xA0000000)
#define MTIMER_CTRL (MTIMER_BASE + (0x00))
#define MTIMER_CMP (MTIMER_BASE + (0x04))
#define MTIMER_COUNT (MTIMER_BASE + (0x08))
#define MTIMER_REG(addr) (*((volatile uint32_t *)addr))
void machine_timer_set_cmp_val(uint32_t val);
void machine_timer_enable(uint8_t en);
void machine_timer_irq_enable(uint8_t en);
void machine_timer_clear_irq_pending();
#endif

View File

@ -25,4 +25,9 @@
uint64_t get_cycle_value();
void busy_wait(uint32_t us);
void global_irq_enable();
void global_irq_disable();
void mtime_irq_enable();
void mtime_irq_disable();
#endif

View File

@ -0,0 +1,30 @@
#include <stdint.h>
#include "../../bsp/include/machine_timer.h"
#include "../../bsp/include/utils.h"
void machine_timer_set_cmp_val(uint32_t val)
{
MTIMER_REG(MTIMER_CMP) = val;
}
void machine_timer_enable(uint8_t en)
{
if (en)
MTIMER_REG(MTIMER_CTRL) |= 1;
else
MTIMER_REG(MTIMER_CTRL) &= ~1;
}
void machine_timer_irq_enable(uint8_t en)
{
if (en)
mtime_irq_enable();
else
mtime_irq_disable();
}
void machine_timer_clear_irq_pending()
{
MTIMER_REG(MTIMER_CTRL) |= 1 << 1;
}

View File

@ -24,3 +24,23 @@ void busy_wait(uint32_t us)
while (get_cycle_value() < (tmp + count));
}
void global_irq_enable()
{
asm volatile("csrs mstatus, %0\n" : : "r"(0x8));
}
void global_irq_disable()
{
asm volatile("csrc mstatus, %0\n" : : "r"(0x8));
}
void mtime_irq_enable()
{
asm volatile("csrs mie, %0\n" : : "r"(0x80));
}
void mtime_irq_disable()
{
asm volatile("csrc mie, %0\n" : : "r"(0x80));
}

8
sdk/examples/machine_timer/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Object files
*.o
*.ko
*.obj
*.bin
*.dump
*.mem
machine_timer

View File

@ -0,0 +1,20 @@
RISCV_ARCH := rv32im
RISCV_ABI := ilp32
RISCV_MCMODEL := medlow
TARGET = machine_timer
CFLAGS += -DSIMULATION
#CFLAGS += -Os
#ASM_SRCS +=
#LDFLAGS +=
#INCLUDES += -I.
C_SRCS := \
main.c \
BSP_DIR = ../../bsp
include ../../bsp/bsp.mk

View File

@ -0,0 +1 @@
机器定时器(中断)例程。

View File

@ -0,0 +1,55 @@
#include <stdint.h>
#include "../../bsp/include/machine_timer.h"
#include "../../bsp/include/utils.h"
#include "../../bsp/include/gpio.h"
static volatile uint32_t count;
int main()
{
count = 0;
#ifdef SIMULATION
machine_timer_set_cmp_val(5000); // 100us period
machine_timer_clear_irq_pending();
global_irq_enable();
machine_timer_irq_enable(1);
machine_timer_enable(1);
while (1) {
if (count == 3) {
machine_timer_enable(0);
// TODO: do something
set_test_pass();
break;
}
}
return 0;
#else
machine_timer_set_cmp_val(500000); // 10ms period
machine_timer_clear_irq_pending();
global_irq_enable();
machine_timer_irq_enable(1);
machine_timer_enable(1);
GPIO_REG(GPIO_CTRL) |= 0x1; // set gpio0 output mode
while (1) {
// 500ms
if (count == 50) {
count = 0;
GPIO_REG(GPIO_DATA) ^= 0x1; // toggle led
}
}
#endif
}
void timer_irq_handler() __attribute__((interrupt));
void timer_irq_handler()
{
count++;
machine_timer_clear_irq_pending();
}