mirror of
https://github.com/WangXuan95/USTC-RVSoC.git
synced 2025-01-30 23:02:55 +08:00
first commit
This commit is contained in:
commit
d12408b6d7
79
ASM/asm2verilogrom.py
Normal file
79
ASM/asm2verilogrom.py
Normal file
@ -0,0 +1,79 @@
|
||||
#coding: utf-8
|
||||
#!/usr/bin/env python
|
||||
|
||||
|
||||
# 作用:汇编.S文件并将指令流转换为verilog rom文件
|
||||
# 命令示例:python asm2verilogrom.py uart_print.S uart_print.sv
|
||||
# 请使用python2
|
||||
|
||||
import os
|
||||
import sys
|
||||
import binascii
|
||||
|
||||
|
||||
verilog_head = '''// asm file name: %s
|
||||
module instr_rom(
|
||||
input logic clk, rst_n,
|
||||
naive_bus.slave bus
|
||||
);
|
||||
localparam INSTR_CNT = 30'd%d;
|
||||
|
||||
wire [0:INSTR_CNT-1] [31:0] instr_rom_cell = {
|
||||
'''
|
||||
|
||||
verilog_tail = ''' };
|
||||
|
||||
logic [29:0] cell_rd_addr;
|
||||
|
||||
assign bus.rd_gnt = bus.rd_req;
|
||||
assign bus.wr_gnt = bus.wr_req;
|
||||
assign cell_rd_addr = bus.rd_addr[31:2];
|
||||
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n)
|
||||
bus.rd_data <= 0;
|
||||
else begin
|
||||
if(bus.rd_req)
|
||||
bus.rd_data <= (cell_rd_addr>=INSTR_CNT) ? 0 : instr_rom_cell[cell_rd_addr];
|
||||
else
|
||||
bus.rd_data <= 0;
|
||||
end
|
||||
|
||||
endmodule
|
||||
'''
|
||||
|
||||
RISCV_TOOLCHAIN_PATH = '.\\riscv32-gnu-toolchain-windows\\'
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
print(" 正确的命令格式:python asm2verilogrom.py aaa.S aaa.sv");
|
||||
print(" 将aaa.S汇编后的指令流以verilog ROM的方式输出到aaa.sv中");
|
||||
print(" 请确保使用python2");
|
||||
sys.exit()
|
||||
|
||||
INPUT = sys.argv[1]
|
||||
OUTPUT = sys.argv[2]
|
||||
|
||||
res = os.system( '%sriscv32-elf-as %s -o compile_tmp.o -march=rv32i' % (RISCV_TOOLCHAIN_PATH, INPUT) )
|
||||
if res != 0:
|
||||
print('\n Assembling Error!')
|
||||
sys.exit()
|
||||
os.system( '%sriscv32-elf-ld compile_tmp.o -o compile_tmp.om' % (RISCV_TOOLCHAIN_PATH ) )
|
||||
os.system( 'del compile_tmp.o' )
|
||||
os.system( '%sriscv32-elf-objcopy -O binary compile_tmp.om compile_tmp.bin' % (RISCV_TOOLCHAIN_PATH, ) )
|
||||
os.system( 'del compile_tmp.om' )
|
||||
s = binascii.b2a_hex( open('compile_tmp.bin', 'rb').read() )
|
||||
os.system( 'del compile_tmp.bin' )
|
||||
|
||||
def byte_wise_reverse(b):
|
||||
return b[6:8] + b[4:6] + b[2:4] + b[0:2]
|
||||
|
||||
with open(OUTPUT, 'w') as f:
|
||||
f.write(verilog_head % (INPUT, len(s)//8))
|
||||
for i in range(0, len(s), 8):
|
||||
instr_addr = '0x%08x' % (i//2,)
|
||||
if i+8<len(s):
|
||||
f.write(' 32\'h'+byte_wise_reverse(s[i:i+8])+', //'+instr_addr+'\n')
|
||||
else:
|
||||
f.write(' 32\'h'+byte_wise_reverse(s[i:i+8])+' //'+instr_addr+'\n')
|
||||
f.write(verilog_tail)
|
||||
|
33
ASM/load_store.S
Normal file
33
ASM/load_store.S
Normal file
@ -0,0 +1,33 @@
|
||||
.org 0x0
|
||||
.global _start
|
||||
_start:
|
||||
ori a0, zero, 0x200
|
||||
addi a1, zero, 0xc8
|
||||
addi a2, zero, 0x56
|
||||
addi a3, zero, 0xa4
|
||||
addi a4, zero, 0x12
|
||||
sb a1, 0(a0)
|
||||
sb a2, 1(a0)
|
||||
sb a3, 2(a0)
|
||||
sb a4, 3(a0)
|
||||
lw t0, 0(a0)
|
||||
lb t0, 0(a0)
|
||||
lb t0, 1(a0)
|
||||
lb t0, 2(a0)
|
||||
lb t0, 3(a0)
|
||||
lbu t0, 0(a0)
|
||||
lbu t0, 1(a0)
|
||||
lbu t0, 2(a0)
|
||||
lbu t0, 3(a0)
|
||||
lh t0, 0(a0)
|
||||
lh t0, 2(a0)
|
||||
lhu t0, 0(a0)
|
||||
lhu t0, 2(a0)
|
||||
lui a5, 0x12345
|
||||
addi a5, a5, 0x678
|
||||
sh a5, 16(a0)
|
||||
addi t0, zero, 16
|
||||
srli a6, a5, 16
|
||||
srl a7, a5, t0
|
||||
sh a7, 18(a0)
|
||||
here: jal zero,here
|
54
ASM/load_store.sv
Normal file
54
ASM/load_store.sv
Normal file
@ -0,0 +1,54 @@
|
||||
// asm file name: load_store.S
|
||||
module instr_rom(
|
||||
input logic clk, rst_n,
|
||||
input logic [13:0] i_addr,
|
||||
output logic [31:0] o_data
|
||||
);
|
||||
localparam INSTR_CNT = 12'd30;
|
||||
|
||||
wire [0:INSTR_CNT-1] [31:0] instr_rom_cell = {
|
||||
32'h20006513, //0x00000000
|
||||
32'h0c800593, //0x00000004
|
||||
32'h05600613, //0x00000008
|
||||
32'h0a400693, //0x0000000c
|
||||
32'h01200713, //0x00000010
|
||||
32'h00b50023, //0x00000014
|
||||
32'h00c500a3, //0x00000018
|
||||
32'h00d50123, //0x0000001c
|
||||
32'h00e501a3, //0x00000020
|
||||
32'h00052283, //0x00000024
|
||||
32'h00050283, //0x00000028
|
||||
32'h00150283, //0x0000002c
|
||||
32'h00250283, //0x00000030
|
||||
32'h00350283, //0x00000034
|
||||
32'h00054283, //0x00000038
|
||||
32'h00154283, //0x0000003c
|
||||
32'h00254283, //0x00000040
|
||||
32'h00354283, //0x00000044
|
||||
32'h00051283, //0x00000048
|
||||
32'h00251283, //0x0000004c
|
||||
32'h00050283, //0x00000050
|
||||
32'h00250283, //0x00000054
|
||||
32'h123457b7, //0x00000058
|
||||
32'h67878793, //0x0000005c
|
||||
32'h00f51823, //0x00000060
|
||||
32'h01000293, //0x00000064
|
||||
32'h0107d813, //0x00000068
|
||||
32'h0057d8b3, //0x0000006c
|
||||
32'h01151923, //0x00000070
|
||||
32'h0000006f //0x00000074
|
||||
};
|
||||
|
||||
logic [11:0] instr_index;
|
||||
logic [31:0] data;
|
||||
|
||||
assign instr_index = i_addr[13:2];
|
||||
assign data = (instr_index>=INSTR_CNT) ? 0 : instr_rom_cell[instr_index];
|
||||
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n)
|
||||
o_data <= 0;
|
||||
else
|
||||
o_data <= data;
|
||||
|
||||
endmodule
|
54
ASM/recursive.S
Normal file
54
ASM/recursive.S
Normal file
@ -0,0 +1,54 @@
|
||||
.org 0x0
|
||||
.global _start
|
||||
_start:
|
||||
addi zero, zero, 0x123
|
||||
addi zero, zero, 0x456
|
||||
|
||||
lui sp, 0x00010
|
||||
ori sp, sp, 0x400 # stack pointer=0x400, stack size = 256 dwords
|
||||
|
||||
xori t0, zero, 6 # t0 = 6
|
||||
jal ra, fibonacci_recursive
|
||||
|
||||
xori a1, t1, 0 # 计算完成,结果在t1中,闲着没事干把它放到a1里好了
|
||||
jal zero, program_end # 跳到死循环程序
|
||||
|
||||
fibonacci_recursive: # 递归计算斐波那契数列的第n项,
|
||||
# n放在t0寄存器中
|
||||
# 结果放在t1寄存器中
|
||||
# 使用ra作为返回地址,并使用堆栈,堆栈指针为sp
|
||||
|
||||
ori a0, zero, 3 # a0 = 3
|
||||
bgeu t0, a0, tag # if t0>=a0(3), jmp to tag
|
||||
ori t1, t0, 0 # t1 = t0
|
||||
jalr zero, ra, 0 # pc = ra
|
||||
|
||||
tag:
|
||||
addi sp, sp, -4 # sp-=4 # push ra to stack
|
||||
sw ra, (sp) # mem[sp] = ra
|
||||
|
||||
addi t0, t0, -1 # t0-=1
|
||||
addi sp, sp, -4 # sp-=4 # push t0 to stack
|
||||
sw t0, (sp) # mem[sp] = t0
|
||||
|
||||
jal ra, fibonacci_recursive # fibonacci_recursive n-1
|
||||
|
||||
lw t0, 0(sp) # t0=mem[sp] # pop t0 from stack
|
||||
addi sp, sp, 4 # sp+=4
|
||||
addi t0, t0, -1 # t0-=1
|
||||
|
||||
addi sp, sp, -4 # sp-=4 # push t1 to stack
|
||||
sw t1, (sp) # mem[sp] = t1
|
||||
jal ra, fibonacci_recursive # fibonacci_recursive n-2
|
||||
lw t2, 0(sp) # ra=mem[sp] # pop t2 from stack
|
||||
addi sp, sp, 4 # sp+=4
|
||||
add t1, t1, t2 # t1+=t2
|
||||
|
||||
lw ra, 0(sp) # ra=mem[sp] # pop ra from stack
|
||||
addi sp, sp, 4 # sp+=4
|
||||
|
||||
jalr zero, ra,0 # pc = ra
|
||||
|
||||
program_end:
|
||||
jal zero, program_end # infinity loop
|
||||
|
55
ASM/recursive.sv
Normal file
55
ASM/recursive.sv
Normal file
@ -0,0 +1,55 @@
|
||||
// asm file name: recursive.S
|
||||
module instr_rom(
|
||||
input logic clk, rst_n,
|
||||
input logic [13:0] i_addr,
|
||||
output logic [31:0] o_data
|
||||
);
|
||||
localparam INSTR_CNT = 12'd31;
|
||||
|
||||
wire [0:INSTR_CNT-1] [31:0] instr_rom_cell = {
|
||||
32'h12300013, //0x00000000
|
||||
32'h45600013, //0x00000004
|
||||
32'h00010137, //0x00000008
|
||||
32'h40016113, //0x0000000c
|
||||
32'h00604293, //0x00000010
|
||||
32'h00c000ef, //0x00000014
|
||||
32'h00034593, //0x00000018
|
||||
32'h05c0006f, //0x0000001c
|
||||
32'h00306513, //0x00000020
|
||||
32'h00a2f663, //0x00000024
|
||||
32'h0002e313, //0x00000028
|
||||
32'h00008067, //0x0000002c
|
||||
32'hffc10113, //0x00000030
|
||||
32'h00112023, //0x00000034
|
||||
32'hfff28293, //0x00000038
|
||||
32'hffc10113, //0x0000003c
|
||||
32'h00512023, //0x00000040
|
||||
32'hfddff0ef, //0x00000044
|
||||
32'h00012283, //0x00000048
|
||||
32'h00410113, //0x0000004c
|
||||
32'hfff28293, //0x00000050
|
||||
32'hffc10113, //0x00000054
|
||||
32'h00612023, //0x00000058
|
||||
32'hfc5ff0ef, //0x0000005c
|
||||
32'h00012383, //0x00000060
|
||||
32'h00410113, //0x00000064
|
||||
32'h00730333, //0x00000068
|
||||
32'h00012083, //0x0000006c
|
||||
32'h00410113, //0x00000070
|
||||
32'h00008067, //0x00000074
|
||||
32'h0000006f //0x00000078
|
||||
};
|
||||
|
||||
logic [11:0] instr_index;
|
||||
logic [31:0] data;
|
||||
|
||||
assign instr_index = i_addr[13:2];
|
||||
assign data = (instr_index>=INSTR_CNT) ? 0 : instr_rom_cell[instr_index];
|
||||
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n)
|
||||
o_data <= 0;
|
||||
else
|
||||
o_data <= data;
|
||||
|
||||
endmodule
|
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-addr2line.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-addr2line.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-ar.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-ar.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-as.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-as.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-c++.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-c++.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-c++filt.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-c++filt.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-cpp.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-cpp.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-elfedit.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-elfedit.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-g++.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-g++.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcc-7.2.0.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcc-7.2.0.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcc-ar.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcc-ar.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcc-nm.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcc-nm.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcc-ranlib.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcc-ranlib.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcc.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcc.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcov-dump.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcov-dump.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcov-tool.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcov-tool.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcov.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-gcov.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-ld.bfd.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-ld.bfd.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-ld.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-ld.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-nm.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-nm.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-objcopy.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-objcopy.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-objdump.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-objdump.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-ranlib.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-ranlib.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-readelf.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-readelf.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-size.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-size.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-strings.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-strings.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-strip.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/mips-elf-strip.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-addr2line.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-addr2line.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-ar.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-ar.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-as.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-as.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-c++.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-c++.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-c++filt.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-c++filt.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-cpp.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-cpp.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-elfedit.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-elfedit.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-g++.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-g++.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcc-7.2.0.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcc-7.2.0.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcc-ar.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcc-ar.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcc-nm.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcc-nm.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcc-ranlib.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcc-ranlib.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcc.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcc.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcov-dump.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcov-dump.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcov-tool.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcov-tool.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcov.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gcov.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gprof.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-gprof.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-ld.bfd.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-ld.bfd.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-ld.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-ld.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-nm.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-nm.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-objcopy.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-objcopy.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-objdump.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-objdump.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-ranlib.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-ranlib.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-readelf.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-readelf.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-size.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-size.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-strings.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-strings.exe
Normal file
Binary file not shown.
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-strip.exe
Normal file
BIN
ASM/riscv32-gnu-toolchain-windows/riscv32-elf-strip.exe
Normal file
Binary file not shown.
9
ASM/simpletest.S
Normal file
9
ASM/simpletest.S
Normal file
@ -0,0 +1,9 @@
|
||||
.org 0x0
|
||||
.global _start
|
||||
_start:
|
||||
ori x1, x0, 0x210 # x1 = h210
|
||||
ori x2, x1, 0x021 # x2 = h231
|
||||
slli x3, x2, 1 # x3 = h462
|
||||
andi x4, x3, 0x568 # x4 = h460
|
||||
ori x5, x0, 0x68a # x5 = h68a
|
||||
|
29
ASM/simpletest.sv
Normal file
29
ASM/simpletest.sv
Normal file
@ -0,0 +1,29 @@
|
||||
// asm file name: test1.S
|
||||
module instr_rom(
|
||||
input logic clk, rst_n,
|
||||
input logic [13:0] i_addr,
|
||||
output logic [31:0] o_data
|
||||
);
|
||||
localparam INSTR_CNT = 12'd5;
|
||||
|
||||
wire [0:INSTR_CNT-1] [31:0] instr_rom_cell = {
|
||||
32'h21006093,
|
||||
32'h0210e113,
|
||||
32'h00111193,
|
||||
32'h5681f213,
|
||||
32'h68a06293
|
||||
};
|
||||
|
||||
logic [11:0] instr_index;
|
||||
logic [31:0] data;
|
||||
|
||||
assign instr_index = i_addr[13:2];
|
||||
assign data = (instr_index>=INSTR_CNT) ? 0 : instr_rom_cell[instr_index];
|
||||
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n)
|
||||
o_data <= 0;
|
||||
else
|
||||
o_data <= data;
|
||||
|
||||
endmodule
|
31
ASM/uart_print.S
Normal file
31
ASM/uart_print.S
Normal file
@ -0,0 +1,31 @@
|
||||
.org 0x0
|
||||
.global _start
|
||||
_start:
|
||||
# 第一步:令t0寄存器=0x00030000,即user_uart外设的地址
|
||||
or t0, zero,zero # t0 清零
|
||||
lui t0, 0x00030 # t0 寄存器的高20bit=0x00020
|
||||
|
||||
# 第二步:将hello!逐个字符写入user_uart外设,即打印hello!到uart
|
||||
print_hello:
|
||||
ori t1, zero, 0x068 # t1='h'的ASCII码
|
||||
sb t1, (t0) # t1写入t0地址
|
||||
ori t1, zero, 0x065 # t1='e'的ASCII码
|
||||
sb t1, (t0) # t1写入t0地址
|
||||
ori t1, zero, 0x06c # t1='l'的ASCII码
|
||||
sb t1, (t0) # t1写入t0地址
|
||||
ori t1, zero, 0x06c # t1='l'的ASCII码
|
||||
sb t1, (t0) # t1写入t0地址
|
||||
ori t1, zero, 0x06f # t1='o'的ASCII码
|
||||
sb t1, (t0) # t1写入t0地址
|
||||
ori t1, zero, 0x021 # t1='!'的ASCII码
|
||||
sb t1, (t0) # t1写入t0地址
|
||||
ori t1, zero, 0x00a # t1='\n'的ASCII码
|
||||
sb t1, (t0) # t1写入t0地址
|
||||
|
||||
# 第三步:延时,通过大空循环的方式
|
||||
lui t2, 0x00200 # t2 = 0x00800000
|
||||
big_loop:
|
||||
addi t2, t2, -1 # t2 = t2-1
|
||||
bne t2, zero, big_loop # if t2!=0, jmp to big_loop
|
||||
jal zero, print_hello # 大循环结束,跳到print_hello,重复打印
|
||||
|
8
ASM/uart_print.sv
Normal file
8
ASM/uart_print.sv
Normal file
@ -0,0 +1,8 @@
|
||||
// asm file name: uart_print.S
|
||||
module instr_rom(
|
||||
input logic clk, rst_n,
|
||||
naive_bus.slave bus
|
||||
);
|
||||
localparam INSTR_CNT = 30'd20;
|
||||
|
||||
wire [0:INSTR_CNT-1] [31:0] instr_rom_cell = {
|
49
RTL/core_alu.sv
Normal file
49
RTL/core_alu.sv
Normal file
@ -0,0 +1,49 @@
|
||||
module core_alu(
|
||||
input logic [ 6:0] i_opcode, i_funct7,
|
||||
input logic [ 2:0] i_funct3,
|
||||
input logic [31:0] i_num1u, i_num2u, i_immu,
|
||||
output logic [31:0] o_res
|
||||
);
|
||||
|
||||
logic [4:0] shamt_rs, shamt_imm;
|
||||
logic [31:0] shifted;
|
||||
logic signed [31:0] i_num1s, i_num2s, i_imms;
|
||||
|
||||
assign shamt_imm = i_immu[4:0];
|
||||
assign shamt_rs = i_num2u[4:0];
|
||||
assign i_num1s = i_num1u;
|
||||
assign i_num2s = i_num2u;
|
||||
assign i_imms = i_immu;
|
||||
|
||||
always_comb
|
||||
casex({i_funct7,i_funct3,i_opcode})
|
||||
// 算术类
|
||||
17'b0000000_000_0110011 : o_res <= i_num1u + i_num2u; // ADD
|
||||
17'bxxxxxxx_000_0010011 : o_res <= i_num1u + i_immu ; // ADDI
|
||||
17'b0100000_000_0110011 : o_res <= i_num1u - i_num2u; // SUB
|
||||
// LUI类
|
||||
17'bxxxxxxx_xxx_0110111 : o_res <= i_immu; // LUI
|
||||
// 逻辑类
|
||||
17'b0000000_100_0110011 : o_res <= i_num1u ^ i_num2u; // XOR
|
||||
17'bxxxxxxx_100_0010011 : o_res <= i_num1u ^ i_immu ; // XORI
|
||||
17'b0000000_110_0110011 : o_res <= i_num1u | i_num2u; // OR
|
||||
17'bxxxxxxx_110_0010011 : o_res <= i_num1u | i_immu ; // ORI
|
||||
17'b0000000_111_0110011 : o_res <= i_num1u & i_num2u; // AND
|
||||
17'bxxxxxxx_111_0010011 : o_res <= i_num1u & i_immu ; // ANDI
|
||||
// 位移类
|
||||
17'b0000000_001_0110011 : o_res <= i_num1u << shamt_rs ; // SLL
|
||||
17'b0000000_001_0010011 : o_res <= i_num1u << shamt_imm; // SLLI
|
||||
17'b0000000_101_0110011 : o_res <= i_num1u >> shamt_rs ; // SRL
|
||||
17'b0000000_101_0010011 : o_res <= i_num1u >> shamt_imm; // SRL
|
||||
17'b0100000_101_0110011 : o_res <= i_num1s >> shamt_rs ; // SRA
|
||||
17'b0100000_101_0010011 : o_res <= i_num1s >> shamt_imm; // SRAI
|
||||
// 比较类
|
||||
17'b0000000_010_0110011 : o_res <= (i_num1s < i_num2s) ? 1 : 0; // SLT
|
||||
17'bxxxxxxx_010_0010011 : o_res <= (i_num1s < i_imms ) ? 1 : 0; // SLTI
|
||||
17'b0000000_011_0110011 : o_res <= (i_num1u < i_num2u) ? 1 : 0; // SLTU
|
||||
17'bxxxxxxx_011_0010011 : o_res <= (i_num1u < i_immu ) ? 1 : 0; // SLTIU
|
||||
// 无操作
|
||||
default : o_res <= 0;
|
||||
endcase
|
||||
|
||||
endmodule
|
109
RTL/core_bus_wrapper.sv
Normal file
109
RTL/core_bus_wrapper.sv
Normal file
@ -0,0 +1,109 @@
|
||||
module core_bus_wrapper(
|
||||
input logic clk, rst_n,
|
||||
input logic i_re, i_we,
|
||||
output logic o_conflict, o_conflict_latch,
|
||||
input logic [ 2:0] i_funct3,
|
||||
input logic [31:0] i_addr,
|
||||
input logic [31:0] i_wdata,
|
||||
output logic [31:0] o_rdata,
|
||||
|
||||
naive_bus.master bus_master
|
||||
);
|
||||
|
||||
logic i_re_latch;
|
||||
logic [1:0] addr_lsb, rd_addr_lsb;
|
||||
logic [31:0] addr_bus, wdata, rdata, rdata_latch;
|
||||
logic [2:0] rd_funct3;
|
||||
logic [3:0] byte_enable;
|
||||
|
||||
assign addr_bus = {i_addr[31:2], 2'b0};
|
||||
assign addr_lsb = i_addr[1:0];
|
||||
|
||||
assign o_conflict = (bus_master.rd_req & ~bus_master.rd_gnt) | (bus_master.wr_req & ~bus_master.wr_gnt);
|
||||
|
||||
assign bus_master.rd_req = i_re;
|
||||
assign bus_master.rd_be = i_re ? byte_enable : 4'h0;
|
||||
assign bus_master.rd_addr = i_re ? addr_bus : 0;
|
||||
assign rdata = bus_master.rd_data;
|
||||
|
||||
assign bus_master.wr_req = i_we;
|
||||
assign bus_master.wr_be = i_we ? byte_enable : 4'h0;
|
||||
assign bus_master.wr_addr = i_we ? addr_bus : 0;
|
||||
assign bus_master.wr_data = i_we ? wdata : 0;
|
||||
|
||||
|
||||
always_comb
|
||||
casex(i_funct3)
|
||||
3'bx00 : if (addr_lsb==2'b00) byte_enable <= 4'b0001;
|
||||
else if(addr_lsb==2'b01) byte_enable <= 4'b0010;
|
||||
else if(addr_lsb==2'b10) byte_enable <= 4'b0100;
|
||||
else byte_enable <= 4'b1000;
|
||||
3'bx01 : if (addr_lsb==2'b00) byte_enable <= 4'b0011;
|
||||
else if(addr_lsb==2'b10) byte_enable <= 4'b1100;
|
||||
else byte_enable <= 4'b0000;
|
||||
3'b010 : if (addr_lsb==2'b00) byte_enable <= 4'b1111;
|
||||
else byte_enable <= 4'b0000;
|
||||
default : byte_enable <= 4'b0000;
|
||||
endcase
|
||||
|
||||
|
||||
always_comb
|
||||
case(i_funct3)
|
||||
3'b000 : if (addr_lsb==2'b00) wdata <= {24'b0, i_wdata[7:0]};
|
||||
else if(addr_lsb==2'b01) wdata <= {16'b0, i_wdata[7:0], 8'b0};
|
||||
else if(addr_lsb==2'b10) wdata <= {8'b0, i_wdata[7:0], 16'b0};
|
||||
else wdata <= {i_wdata[7:0], 24'b0};
|
||||
3'b001 : if (addr_lsb==2'b00) wdata <= {16'b0, i_wdata[15:0]};
|
||||
else if(addr_lsb==2'b10) wdata <= {i_wdata[15:0], 16'b0};
|
||||
else wdata <= 0;
|
||||
3'b010 : if (addr_lsb==2'b00) wdata <= i_wdata;
|
||||
else wdata <= 0;
|
||||
default : wdata <= 0;
|
||||
endcase
|
||||
|
||||
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n) begin
|
||||
i_re_latch <= 1'b0;
|
||||
rd_addr_lsb <= 2'b0;
|
||||
rd_funct3 <= 3'b0;
|
||||
o_conflict_latch <= 1'b0;
|
||||
rdata_latch <= 0;
|
||||
end else begin
|
||||
i_re_latch <= i_re;
|
||||
rd_addr_lsb <= addr_lsb;
|
||||
rd_funct3 <= i_funct3;
|
||||
o_conflict_latch <= o_conflict;
|
||||
rdata_latch <= o_rdata;
|
||||
end
|
||||
|
||||
// assign o_rdata
|
||||
always_comb
|
||||
if(i_re_latch) begin
|
||||
if(~o_conflict_latch)
|
||||
case(rd_funct3)
|
||||
3'b000 : if (rd_addr_lsb==2'b00) o_rdata <= {{24{rdata[ 7]}}, rdata[ 7: 0]};
|
||||
else if(rd_addr_lsb==2'b01) o_rdata <= {{24{rdata[15]}}, rdata[15: 8]};
|
||||
else if(rd_addr_lsb==2'b10) o_rdata <= {{24{rdata[23]}}, rdata[23:16]};
|
||||
else o_rdata <= {{24{rdata[31]}}, rdata[31:24]};
|
||||
3'b100 : if (rd_addr_lsb==2'b00) o_rdata <= { 24'b0, rdata[ 7: 0]};
|
||||
else if(rd_addr_lsb==2'b01) o_rdata <= { 24'b0, rdata[15: 8]};
|
||||
else if(rd_addr_lsb==2'b10) o_rdata <= { 24'b0, rdata[23:16]};
|
||||
else o_rdata <= { 24'b0, rdata[31:24]};
|
||||
3'b001 : if (rd_addr_lsb==2'b00) o_rdata <= {{16{rdata[15]}}, rdata[15: 0]};
|
||||
else if(rd_addr_lsb==2'b10) o_rdata <= {{16{rdata[31]}}, rdata[31:16]};
|
||||
else o_rdata <= 0;
|
||||
3'b101 : if (rd_addr_lsb==2'b00) o_rdata <= { 16'b0, rdata[15: 0]};
|
||||
else if(rd_addr_lsb==2'b10) o_rdata <= { 16'b0, rdata[31:16]};
|
||||
else o_rdata <= 0;
|
||||
3'b010 : if (rd_addr_lsb==2'b00) o_rdata <= rdata;
|
||||
else o_rdata <= 0;
|
||||
default : o_rdata <= 0;
|
||||
endcase
|
||||
else
|
||||
o_rdata <= 0;
|
||||
end else begin
|
||||
o_rdata <= rdata_latch;
|
||||
end
|
||||
|
||||
endmodule
|
26
RTL/core_ex_branch_judge.sv
Normal file
26
RTL/core_ex_branch_judge.sv
Normal file
@ -0,0 +1,26 @@
|
||||
module core_ex_branch_judge(
|
||||
input logic i_branch,
|
||||
input logic [31:0] i_num1u, i_num2u,
|
||||
input logic [ 2:0] i_funct3,
|
||||
output logic o_branch
|
||||
);
|
||||
|
||||
logic branch_judge_res;
|
||||
assign o_branch = i_branch & branch_judge_res;
|
||||
|
||||
logic signed [31:0] i_num1s, i_num2s;
|
||||
assign i_num1s = i_num1u;
|
||||
assign i_num2s = i_num2u;
|
||||
|
||||
always_comb
|
||||
case(i_funct3)
|
||||
3'b000 : branch_judge_res <= (i_num1u == i_num2u); // BEQ
|
||||
3'b001 : branch_judge_res <= (i_num1u != i_num2u); // BNE
|
||||
3'b100 : branch_judge_res <= (i_num1s < i_num2s); // BLT
|
||||
3'b101 : branch_judge_res <= (i_num1s >= i_num2s); // BGE
|
||||
3'b110 : branch_judge_res <= (i_num1u < i_num2u); // BLTU
|
||||
3'b111 : branch_judge_res <= (i_num1u >= i_num2u); // BGEU
|
||||
default: branch_judge_res <= 1'b0;
|
||||
endcase
|
||||
|
||||
endmodule
|
79
RTL/core_id_stage.sv
Normal file
79
RTL/core_id_stage.sv
Normal file
@ -0,0 +1,79 @@
|
||||
module core_id_stage(
|
||||
input logic [31:0] i_instr,
|
||||
input logic [31:0] i_pc,
|
||||
output logic [ 4:0] o_rs1_addr, o_rs2_addr,
|
||||
output logic o_rs1_en, o_rs2_en,
|
||||
output logic o_jal, o_jalr, o_branch_may,
|
||||
output logic o_nextpc2reg, o_alures2reg, o_memory2reg,
|
||||
output logic o_mem_write,
|
||||
output logic [31:0] o_pc_plus_imm, o_imm,
|
||||
output logic [4:0] o_dst_reg_addr,
|
||||
output logic [6:0] o_opcode, o_funct7,
|
||||
output logic [2:0] o_funct3,
|
||||
output logic [31:0] o_next_pc
|
||||
);
|
||||
|
||||
logic [31:0] instr;
|
||||
|
||||
enum {UKNOWN_TYPE, R_TYPE, I_TYPE, IZ_TYPE, S_TYPE, B_TYPE, U_TYPE, J_TYPE} instr_type;
|
||||
|
||||
localparam OPCODE_JAL = 7'b1101111, // rd=pc+4, pc= pc+imm*2,
|
||||
OPCODE_JALR = 7'b1100111, // rd=pc+4, pc= rs1+imm
|
||||
OPCODE_BXXX = 7'b1100011, // conditional branch, pc= pc+imm*2,
|
||||
OPCODE_LUI = 7'b0110111, // rd = imm;
|
||||
OPCODE_ALI = 7'b0010011, // arithmetic and logical I-TYPE, rd=alu_res
|
||||
OPCODE_ALR = 7'b0110011, // arithmetic and logical R-TYPE, rd=alu_res
|
||||
OPCODE_LOAD = 7'b0000011, // load
|
||||
OPCODE_STORE = 7'b0100011; // store
|
||||
|
||||
assign instr = i_instr;
|
||||
assign o_next_pc = i_pc + 4;
|
||||
assign o_pc_plus_imm = i_pc + o_imm;
|
||||
assign {o_funct7, o_rs2_addr, o_rs1_addr, o_funct3, o_dst_reg_addr, o_opcode} = instr;
|
||||
|
||||
assign o_jal = (o_opcode == OPCODE_JAL );
|
||||
assign o_jalr = (o_opcode == OPCODE_JALR );
|
||||
assign o_branch_may = (o_opcode == OPCODE_BXXX );
|
||||
assign o_nextpc2reg = (o_opcode == OPCODE_JAL || o_opcode == OPCODE_JALR );
|
||||
assign o_alures2reg = (o_opcode == OPCODE_LUI || o_opcode == OPCODE_ALI || o_opcode == OPCODE_ALR);
|
||||
assign o_memory2reg = (o_opcode == OPCODE_LOAD );
|
||||
assign o_mem_write = (o_opcode == OPCODE_STORE);
|
||||
|
||||
// calculate instruction type
|
||||
always_comb
|
||||
case(o_opcode)
|
||||
OPCODE_JAL : instr_type <= J_TYPE;
|
||||
OPCODE_JALR : instr_type <= I_TYPE;
|
||||
OPCODE_BXXX : instr_type <= B_TYPE;
|
||||
OPCODE_LUI : instr_type <= U_TYPE;
|
||||
OPCODE_ALI : instr_type <= (o_funct3==3'b011) ? IZ_TYPE : I_TYPE;
|
||||
OPCODE_ALR : instr_type <= R_TYPE;
|
||||
OPCODE_LOAD : instr_type <= I_TYPE;
|
||||
OPCODE_STORE: instr_type <= S_TYPE;
|
||||
default : instr_type <= UKNOWN_TYPE;
|
||||
endcase
|
||||
|
||||
always_comb
|
||||
case(instr_type)
|
||||
I_TYPE : o_imm <= {{20{instr[31]}} , instr[31:20]};
|
||||
IZ_TYPE: o_imm <= { 20'h0 , instr[31:20]};
|
||||
S_TYPE : o_imm <= {{20{instr[31]}} , instr[31:25], instr[11:7]};
|
||||
B_TYPE : o_imm <= {{20{instr[31]}} , instr[7], instr[30:25], instr[11:8], 1'b0};
|
||||
U_TYPE : o_imm <= { instr[31:12] , 12'h0 };
|
||||
J_TYPE : o_imm <= {{12{instr[31]}} , instr[19:12], instr[20], instr[30:21], 1'b0};
|
||||
default: o_imm <= 0;
|
||||
endcase
|
||||
|
||||
always_comb
|
||||
case(instr_type)
|
||||
R_TYPE : {o_rs2_en, o_rs1_en} <= 2'b11;
|
||||
I_TYPE : {o_rs2_en, o_rs1_en} <= 2'b01;
|
||||
IZ_TYPE: {o_rs2_en, o_rs1_en} <= 2'b01;
|
||||
S_TYPE : {o_rs2_en, o_rs1_en} <= 2'b11;
|
||||
B_TYPE : {o_rs2_en, o_rs1_en} <= 2'b11;
|
||||
U_TYPE : {o_rs2_en, o_rs1_en} <= 2'b00;
|
||||
J_TYPE : {o_rs2_en, o_rs1_en} <= 2'b00;
|
||||
default: {o_rs2_en, o_rs1_en} <= 2'b00;
|
||||
endcase
|
||||
|
||||
endmodule
|
84
RTL/core_regfile.sv
Normal file
84
RTL/core_regfile.sv
Normal file
@ -0,0 +1,84 @@
|
||||
// Priority : Write Port 1 > Write Port 2 > Write Port 3
|
||||
module core_regfile(
|
||||
input logic clk, rst_n,
|
||||
input logic rd_latch,
|
||||
// Read port 1
|
||||
input logic i_re1,
|
||||
input logic [4:0] i_raddr1,
|
||||
output logic [31:0] o_rdata1,
|
||||
// Read port 2
|
||||
input logic i_re2,
|
||||
input logic [4:0] i_raddr2,
|
||||
output logic [31:0] o_rdata2,
|
||||
// Write port 1
|
||||
input logic i_we1,
|
||||
input logic [4:0] i_waddr1,
|
||||
input logic [31:0] i_wdata1,
|
||||
// Write port 2
|
||||
input logic i_we2,
|
||||
input logic [4:0] i_waddr2,
|
||||
input logic [31:0] i_wdata2,
|
||||
// Write port 3
|
||||
input logic i_we3,
|
||||
input logic [4:0] i_waddr3,
|
||||
input logic [31:0] i_wdata3
|
||||
);
|
||||
|
||||
logic [31:1] [31:0] reg_file_cell = 992'h0;
|
||||
|
||||
// handle regwrite
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if(~rst_n)
|
||||
reg_file_cell <= 992'h0;
|
||||
else begin
|
||||
if(i_we3 && i_waddr3!=5'h0 && ~(i_we1 && i_waddr1==i_waddr3) && ~(i_we2 && i_waddr2==i_waddr3) )
|
||||
reg_file_cell[i_waddr3] <= i_wdata3;
|
||||
if(i_we2 && i_waddr2!=5'h0 && ~(i_we1 && i_waddr1==i_waddr2) )
|
||||
reg_file_cell[i_waddr2] <= i_wdata2;
|
||||
if(i_we1 && i_waddr1!=5'h0 )
|
||||
reg_file_cell[i_waddr1] <= i_wdata1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if(~rst_n)
|
||||
o_rdata1 <= 0;
|
||||
else begin
|
||||
if(rd_latch) begin
|
||||
o_rdata1 <= o_rdata1;
|
||||
end else if(i_re1 && i_raddr1!=5'h0) begin
|
||||
if (i_we1 && i_raddr1==i_waddr1)
|
||||
o_rdata1 <= i_wdata1;
|
||||
else if(i_we2 && i_raddr1==i_waddr2)
|
||||
o_rdata1 <= i_wdata2;
|
||||
else if(i_we3 && i_raddr1==i_waddr3)
|
||||
o_rdata1 <= i_wdata3;
|
||||
else
|
||||
o_rdata1 <= reg_file_cell[i_raddr1];
|
||||
end else
|
||||
o_rdata1 <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if(~rst_n)
|
||||
o_rdata2 <= 0;
|
||||
else begin
|
||||
if(rd_latch) begin
|
||||
o_rdata2 <= o_rdata2;
|
||||
end else if(i_re2 && i_raddr2!=5'h0) begin
|
||||
if (i_we1 && i_raddr2==i_waddr1)
|
||||
o_rdata2 <= i_wdata1;
|
||||
else if(i_we2 && i_raddr2==i_waddr2)
|
||||
o_rdata2 <= i_wdata2;
|
||||
else if(i_we3 && i_raddr2==i_waddr3)
|
||||
o_rdata2 <= i_wdata3;
|
||||
else
|
||||
o_rdata2 <= reg_file_cell[i_raddr2];
|
||||
end else
|
||||
o_rdata2 <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
256
RTL/core_top.sv
Normal file
256
RTL/core_top.sv
Normal file
@ -0,0 +1,256 @@
|
||||
module core_top(
|
||||
input logic clk, rst_n, i_stop,
|
||||
naive_bus.master instr_master, data_master
|
||||
);
|
||||
|
||||
// IF stage out
|
||||
logic [31:0] if_pc;
|
||||
|
||||
// ID stage
|
||||
logic [31:0] id_instr, id_pc;
|
||||
logic id_rs1_en, id_rs2_en;
|
||||
logic [4:0] id_rs1_addr, id_rs2_addr, id_dst_reg_addr;
|
||||
logic [31:0] id_next_pc;
|
||||
logic id_jal, id_jalr, id_branch_may;
|
||||
logic id_nextpc2reg, id_alures2reg, id_memory2reg;
|
||||
logic id_memwrite;
|
||||
logic [6:0] id_opcode, id_funct7;
|
||||
logic [2:0] id_funct3;
|
||||
logic [31:0] id_pc_plus_imm, id_imm;
|
||||
|
||||
// EX stage
|
||||
logic ex_jalr, ex_branch_may, ex_branch;
|
||||
logic ex_nextpc2reg, ex_alures2reg, ex_memory2reg;
|
||||
logic ex_memwrite;
|
||||
logic [31:0] ex_s1, ex_s2;
|
||||
logic [6:0] ex_opcode, ex_funct7;
|
||||
logic [2:0] ex_funct3;
|
||||
logic [31:0] ex_imm, ex_alu_res;
|
||||
logic [4:0] ex_dst_reg_addr;
|
||||
logic [31:0] ex_s1_plus_imm, ex_next_pc, ex_pc_plus_imm;
|
||||
|
||||
// MEM stage
|
||||
logic [2:0] mem_funct3;
|
||||
logic mem_memory2reg, mem_alures2reg, mem_memwrite;
|
||||
logic [31:0] mem_alu_res, mem_mem_wdata, mem_s1_plus_imm;
|
||||
logic [4:0] mem_dst_reg_addr;
|
||||
|
||||
// WB stage
|
||||
logic wb_memory2reg;
|
||||
logic [31:0] wb_reg_wdata;
|
||||
logic [4:0] wb_dst_reg_addr;
|
||||
|
||||
// write regfile conflict signal
|
||||
logic launch_nop, pc_stall, id_stall, ex_stall, mem_stall, wreg_conflict;
|
||||
logic id_data_bus_conflict, mem_data_bus_conflict;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// conflict - comb logic
|
||||
// -------------------------------------------------------------------------------
|
||||
assign pc_stall = id_stall | id_data_bus_conflict;
|
||||
assign id_stall = wreg_conflict | mem_data_bus_conflict | i_stop;
|
||||
assign ex_stall = mem_data_bus_conflict;
|
||||
assign mem_stall = mem_data_bus_conflict;
|
||||
assign launch_nop = ex_branch | ex_jalr | wreg_conflict;
|
||||
|
||||
assign wreg_conflict =
|
||||
(id_rs1_en & ex_alures2reg & (id_rs1_addr== ex_dst_reg_addr) ) |
|
||||
(id_rs2_en & ex_alures2reg & (id_rs2_addr== ex_dst_reg_addr) ) |
|
||||
(id_rs1_en & ex_memory2reg & (id_rs1_addr== ex_dst_reg_addr) ) |
|
||||
(id_rs2_en & ex_memory2reg & (id_rs2_addr== ex_dst_reg_addr) ) |
|
||||
(id_rs1_en &mem_memory2reg & (id_rs1_addr==mem_dst_reg_addr) ) |
|
||||
(id_rs2_en &mem_memory2reg & (id_rs2_addr==mem_dst_reg_addr) ) ;
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// IF stage - comb logic
|
||||
// -------------------------------------------------------------------------------
|
||||
always_comb
|
||||
if(ex_branch)
|
||||
if_pc <= ex_pc_plus_imm;
|
||||
else if(ex_jalr)
|
||||
if_pc <= ex_s1_plus_imm;
|
||||
else if(id_jal)
|
||||
if_pc <= id_pc_plus_imm;
|
||||
else if(pc_stall)
|
||||
if_pc <= id_pc;
|
||||
else
|
||||
if_pc <= id_next_pc;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// IF-ID stage - timing logic
|
||||
// -------------------------------------------------------------------------------
|
||||
core_bus_wrapper inst_bus_wrap_inst(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.i_re ( ~id_stall ),
|
||||
.i_we ( 1'b0 ),
|
||||
.o_conflict_latch ( id_data_bus_conflict ),
|
||||
.i_funct3 ( 3'b010 ),
|
||||
.i_addr ( if_pc ),
|
||||
.i_wdata ( 0 ),
|
||||
.o_rdata ( id_instr ),
|
||||
.bus_master ( instr_master )
|
||||
);
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n)
|
||||
id_pc <= 32'hffff_fffc;
|
||||
else
|
||||
id_pc <= if_pc;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// ID stage - comb logic
|
||||
// -------------------------------------------------------------------------------
|
||||
core_id_stage core_id_stage_inst(
|
||||
.i_instr ( id_instr ),
|
||||
.i_pc ( id_pc ),
|
||||
.o_rs1_addr ( id_rs1_addr ),
|
||||
.o_rs2_addr ( id_rs2_addr ),
|
||||
.o_rs1_en ( id_rs1_en ),
|
||||
.o_rs2_en ( id_rs2_en ),
|
||||
.o_jal ( id_jal ),
|
||||
.o_jalr ( id_jalr ),
|
||||
.o_branch_may ( id_branch_may ),
|
||||
.o_nextpc2reg ( id_nextpc2reg ),
|
||||
.o_alures2reg ( id_alures2reg ),
|
||||
.o_memory2reg ( id_memory2reg ),
|
||||
.o_mem_write ( id_memwrite ),
|
||||
.o_pc_plus_imm ( id_pc_plus_imm ),
|
||||
.o_imm ( id_imm ),
|
||||
.o_dst_reg_addr ( id_dst_reg_addr),
|
||||
.o_opcode ( id_opcode ),
|
||||
.o_funct7 ( id_funct7 ),
|
||||
.o_funct3 ( id_funct3 ),
|
||||
.o_next_pc ( id_next_pc )
|
||||
);
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// ID-EX stage - timing logic
|
||||
// -------------------------------------------------------------------------------
|
||||
core_regfile core_regfile_inst(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.rd_latch ( ex_stall ),
|
||||
.i_re1 ( id_rs1_en ),
|
||||
.i_raddr1 ( id_rs1_addr ),
|
||||
.o_rdata1 ( ex_s1 ),
|
||||
.i_re2 ( id_rs2_en ),
|
||||
.i_raddr2 ( id_rs2_addr ),
|
||||
.o_rdata2 ( ex_s2 ),
|
||||
.i_we1 ( ex_nextpc2reg ),
|
||||
.i_waddr1 ( ex_dst_reg_addr),
|
||||
.i_wdata1 ( ex_next_pc ),
|
||||
.i_we2 ( mem_alures2reg ),
|
||||
.i_waddr2 (mem_dst_reg_addr),
|
||||
.i_wdata2 ( mem_alu_res ),
|
||||
.i_we3 ( wb_memory2reg ),
|
||||
.i_waddr3 ( wb_dst_reg_addr),
|
||||
.i_wdata3 ( wb_reg_wdata )
|
||||
);
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n) begin
|
||||
ex_jalr <= 1'b0;
|
||||
ex_branch_may <= 1'b0;
|
||||
ex_nextpc2reg <= 1'b0;
|
||||
ex_alures2reg <= 1'b0;
|
||||
ex_memory2reg <= 1'b0;
|
||||
ex_memwrite <= 1'b0;
|
||||
ex_dst_reg_addr <= 5'h0;
|
||||
ex_imm <= 0;
|
||||
ex_opcode <= 7'h0;
|
||||
ex_funct3 <= 3'h0;
|
||||
ex_funct7 <= 7'h0;
|
||||
ex_next_pc <= 0;
|
||||
end else if(~ex_stall) begin
|
||||
ex_jalr <= launch_nop ? 1'b0 : id_jalr;
|
||||
ex_branch_may <= launch_nop ? 1'b0 : id_branch_may;
|
||||
ex_pc_plus_imm <= id_pc_plus_imm;
|
||||
ex_nextpc2reg <= launch_nop ? 1'b0 : id_nextpc2reg;
|
||||
ex_alures2reg <= launch_nop ? 1'b0 : id_alures2reg;
|
||||
ex_memory2reg <= launch_nop ? 1'b0 : id_memory2reg;
|
||||
ex_memwrite <= launch_nop ? 1'b0 : id_memwrite;
|
||||
ex_dst_reg_addr <= id_dst_reg_addr;
|
||||
ex_imm <= id_imm;
|
||||
ex_opcode <= id_opcode;
|
||||
ex_funct3 <= id_funct3;
|
||||
ex_funct7 <= id_funct7;
|
||||
ex_next_pc <= id_next_pc;
|
||||
end
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// EX stage - comb logic
|
||||
// -------------------------------------------------------------------------------
|
||||
core_alu core_alu_inst(
|
||||
.i_opcode ( ex_opcode ),
|
||||
.i_funct7 ( ex_funct7 ),
|
||||
.i_funct3 ( ex_funct3 ),
|
||||
.i_num1u ( ex_s1 ),
|
||||
.i_num2u ( ex_s2 ),
|
||||
.i_immu ( ex_imm ),
|
||||
.o_res ( ex_alu_res )
|
||||
);
|
||||
core_ex_branch_judge core_ex_branch_judge_inst(
|
||||
.i_branch ( ex_branch_may ),
|
||||
.i_num1u ( ex_s1 ),
|
||||
.i_num2u ( ex_s2 ),
|
||||
.i_funct3 ( ex_funct3 ),
|
||||
.o_branch ( ex_branch )
|
||||
);
|
||||
assign ex_s1_plus_imm = ex_s1 + ex_imm;
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// EX-MEM stage - timing logic
|
||||
// -------------------------------------------------------------------------------
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n) begin
|
||||
mem_memory2reg <= 1'b0;
|
||||
mem_alures2reg <= 1'b0;
|
||||
mem_alu_res <= 0;
|
||||
mem_dst_reg_addr<= 5'h0;
|
||||
mem_memwrite <= 1'b0;
|
||||
mem_mem_wdata <= 0;
|
||||
mem_s1_plus_imm <= 0;
|
||||
mem_funct3 <= 3'b0;
|
||||
end else if(~mem_stall) begin
|
||||
mem_memory2reg <= ex_memory2reg;
|
||||
mem_alures2reg <= ex_alures2reg;
|
||||
mem_alu_res <= ex_alu_res;
|
||||
mem_dst_reg_addr<= ex_dst_reg_addr;
|
||||
mem_memwrite <= ex_memwrite;
|
||||
mem_mem_wdata <= ex_s2;
|
||||
mem_s1_plus_imm <= ex_s1_plus_imm;
|
||||
mem_funct3 <= ex_funct3;
|
||||
end
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// MEM-WB stage - timing logic
|
||||
// -------------------------------------------------------------------------------
|
||||
core_bus_wrapper core_bus_wrapper_inst(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.i_re ( mem_memory2reg ),
|
||||
.i_we ( mem_memwrite ),
|
||||
.o_conflict ( mem_data_bus_conflict ),
|
||||
.i_funct3 ( mem_funct3 ),
|
||||
.i_addr ( mem_s1_plus_imm ),
|
||||
.i_wdata ( mem_mem_wdata ),
|
||||
.o_rdata ( wb_reg_wdata ),
|
||||
.bus_master ( data_master )
|
||||
);
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n) begin
|
||||
wb_memory2reg <= 1'b0;
|
||||
wb_dst_reg_addr <= 5'h0;
|
||||
end else begin
|
||||
wb_memory2reg <= mem_memory2reg;
|
||||
wb_dst_reg_addr <= mem_dst_reg_addr;
|
||||
end
|
||||
|
||||
endmodule
|
49
RTL/instr_rom.sv
Normal file
49
RTL/instr_rom.sv
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
module instr_rom(
|
||||
input logic clk, rst_n,
|
||||
naive_bus.slave bus
|
||||
);
|
||||
localparam INSTR_CNT = 12'd20;
|
||||
|
||||
wire [0:INSTR_CNT-1] [31:0] instr_rom_cell = {
|
||||
32'h000062b3, //0x00000000
|
||||
32'h000302b7, //0x00000004
|
||||
32'h06806313, //0x00000008
|
||||
32'h00628023, //0x0000000c
|
||||
32'h06506313, //0x00000010
|
||||
32'h00628023, //0x00000014
|
||||
32'h06c06313, //0x00000018
|
||||
32'h00628023, //0x0000001c
|
||||
32'h06c06313, //0x00000020
|
||||
32'h00628023, //0x00000024
|
||||
32'h06f06313, //0x00000028
|
||||
32'h00628023, //0x0000002c
|
||||
32'h02106313, //0x00000030
|
||||
32'h00628023, //0x00000034
|
||||
32'h00a06313, //0x00000038
|
||||
32'h00628023, //0x0000003c
|
||||
32'h002003b7, //0x00000040
|
||||
32'hfff38393, //0x00000044
|
||||
32'hfe039ee3, //0x00000048
|
||||
32'hfbdff06f //0x0000004c
|
||||
};
|
||||
|
||||
logic [29:0] cell_rd_addr;
|
||||
|
||||
assign bus.rd_gnt = bus.rd_req;
|
||||
assign bus.wr_gnt = bus.wr_req;
|
||||
assign cell_rd_addr = bus.rd_addr[31:2];
|
||||
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n)
|
||||
bus.rd_data <= 0;
|
||||
else begin
|
||||
if(bus.rd_req)
|
||||
bus.rd_data <= (cell_rd_addr>=INSTR_CNT) ? 0 : instr_rom_cell[cell_rd_addr];
|
||||
else
|
||||
bus.rd_data <= 0;
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
242
RTL/isp_uart.sv
Normal file
242
RTL/isp_uart.sv
Normal file
@ -0,0 +1,242 @@
|
||||
// 一个能作为naive bus 主设备的调试模块
|
||||
// 它接收用户从UART发来的命令,操控复位等信号,或对总线进行读写。用户可以使用UART命令复位整个SoC,上传程序,或者查看运行时的RAM数据。
|
||||
|
||||
// 命令列表(全部命令为ASCII,人类可读, 每个命令使用\r或\n或\r\n或\n\r结尾):
|
||||
// 1、复位命令
|
||||
// 发送: r\n
|
||||
// 效果: 将o_rst_n信号拉低若干个时钟周期
|
||||
// 返回: rst done\n
|
||||
// 2. w\n : o_run = 1 , return running \n
|
||||
// 3. s\n : o_run = 0 , return stoped \n
|
||||
// 4. addr=data\n : write [addr] = data , example: 00000100 928cd0f1\n , return : 00000100=928cd0f1 , note:automaticly align address to 4byte
|
||||
// 5. addr\n : read [addr] , example: 00000100\n return : 928cd0f1
|
||||
//
|
||||
|
||||
module isp_uart #(
|
||||
parameter UART_RX_CLK_DIV = 108, // 50MHz/4/115200Hz=108
|
||||
parameter UART_TX_CLK_DIV = 434 // 50MHz/1/115200Hz=434
|
||||
)(
|
||||
input logic clk,
|
||||
input logic i_uart_rx,
|
||||
output logic o_uart_tx,
|
||||
output logic o_rst_n, o_stop,
|
||||
naive_bus.master bus
|
||||
);
|
||||
|
||||
logic [ 5:0] rst_chain = 3'b0;
|
||||
logic rx_ready, rd_ok=1'b0, wr_ok=1'b0, tx_start=1'b0;
|
||||
logic [ 7:0] rx_data, rx_binary;
|
||||
logic [ 3:0] rx_binary_l;
|
||||
logic [31:0] addr=0, wr_data=0;
|
||||
logic [ 7:0][ 7:0] rd_data_ascii;
|
||||
logic [ 7:0][ 7:0] tx_data = 64'h0;
|
||||
enum {NONE, RST, RUN, STOP} cmd=NONE;
|
||||
enum {NEW, CMD, ADDR, EQUAL, DATA, FINAL, TRASH} fsm = NEW;
|
||||
|
||||
`define C (rx_data=="r" || rx_data=="w" || rx_data=="s")
|
||||
`define S (rx_data==" " || rx_data=="\t" )
|
||||
`define E (rx_data=="\n" || rx_data=="\r" )
|
||||
`define N ( (rx_data>="0" && rx_data<="9" ) || (rx_data>="a" && rx_data<="f" ) )
|
||||
|
||||
initial o_stop = 1'b0;
|
||||
assign o_rst_n = ~(|rst_chain);
|
||||
|
||||
initial begin bus.rd_req = 1'b0; bus.wr_req = 1'b0; bus.rd_addr = 0; bus.wr_addr = 0; bus.wr_data = 0; end
|
||||
assign bus.rd_be = 4'hf;
|
||||
assign bus.wr_be = 4'hf;
|
||||
|
||||
assign rx_binary_l = rx_binary[3:0];
|
||||
|
||||
always_comb
|
||||
if(rx_data>="0" && rx_data<="9" ) begin
|
||||
rx_binary = rx_data - "0";
|
||||
end else if(rx_data>="a" && rx_data<="f" ) begin
|
||||
rx_binary = rx_data - "a" + 8'd10;
|
||||
end else begin
|
||||
rx_binary = 8'h0;
|
||||
end
|
||||
|
||||
uart_rx #(
|
||||
.UART_RX_CLK_DIV (UART_RX_CLK_DIV)
|
||||
) uart_rx_inst (
|
||||
.clk ( clk ),
|
||||
.i_rx ( i_uart_rx ),
|
||||
.o_ready ( rx_ready ),
|
||||
.o_data ( rx_data )
|
||||
);
|
||||
|
||||
uart_tx_line #(
|
||||
.UART_TX_CLK_DIV (UART_TX_CLK_DIV)
|
||||
) uart_tx_line_inst (
|
||||
.clk ( clk ),
|
||||
.o_tx ( o_uart_tx ),
|
||||
.i_start ( tx_start ),
|
||||
.i_data ( tx_data )
|
||||
);
|
||||
|
||||
generate
|
||||
genvar i;
|
||||
for(i=0; i<8; i++) begin : convert_binary_to_ascii
|
||||
always_comb
|
||||
if(bus.rd_data[3+4*i:4*i]>4'h9)
|
||||
rd_data_ascii[i] = "a" - 8'd10 + bus.rd_data[3+4*i:4*i];
|
||||
else
|
||||
rd_data_ascii[i] = "0" + bus.rd_data[3+4*i:4*i];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always @ (posedge clk)
|
||||
rd_ok <= (bus.rd_req & bus.rd_gnt);
|
||||
|
||||
always @ (posedge clk)
|
||||
wr_ok <= (bus.wr_req & bus.wr_gnt);
|
||||
|
||||
always @ (posedge clk)
|
||||
if (rd_ok) begin
|
||||
tx_start<= 1'b1;
|
||||
tx_data <= rd_data_ascii;
|
||||
end else if(wr_ok) begin
|
||||
tx_start<= 1'b1;
|
||||
tx_data <= "wr done ";
|
||||
end else if(rx_ready && fsm==CMD && `E) begin
|
||||
tx_start<= 1'b1;
|
||||
if(cmd==RST)
|
||||
tx_data <= "rst done";
|
||||
else if(cmd==RUN)
|
||||
tx_data <= "running ";
|
||||
else if(cmd==STOP)
|
||||
tx_data <= "stoped ";
|
||||
else
|
||||
tx_data <= 64'h0;
|
||||
end else begin
|
||||
tx_start<= 1'b0;
|
||||
tx_data <= 64'h0;
|
||||
end
|
||||
|
||||
always @ (posedge clk)
|
||||
if(rx_ready && fsm==CMD && `E && cmd==RST)
|
||||
rst_chain <= 6'h0;
|
||||
else
|
||||
rst_chain <= {rst_chain[4:0],1'b0};
|
||||
|
||||
always @ (posedge clk)
|
||||
if(rx_ready && fsm==CMD && `E) begin
|
||||
if(cmd==RUN)
|
||||
o_stop <= 1'b0;
|
||||
else
|
||||
o_stop <= 1'b1;
|
||||
end
|
||||
|
||||
always @ (posedge clk)
|
||||
if (bus.rd_req) begin
|
||||
if(bus.rd_gnt)
|
||||
bus.rd_req <= 1'b0;
|
||||
end else if(bus.wr_req) begin
|
||||
if(bus.wr_gnt)
|
||||
bus.wr_req <= 1'b0;
|
||||
end else if( rx_ready ) begin
|
||||
case(fsm)
|
||||
NEW : if (`C) begin
|
||||
fsm <= CMD;
|
||||
if(rx_data=="r") begin // check rx_data to see which command it is
|
||||
cmd <= RST;
|
||||
end else if(rx_data=="w") begin
|
||||
cmd <= RUN;
|
||||
end else if(rx_data=="s") begin
|
||||
cmd <= STOP;
|
||||
end else begin
|
||||
cmd <= NONE;
|
||||
end
|
||||
end else if(`S || `E) begin
|
||||
fsm <= NEW;
|
||||
addr <= 0;
|
||||
wr_data <= 0;
|
||||
cmd <= NONE;
|
||||
end else if(`N) begin
|
||||
fsm <= ADDR;
|
||||
addr <= {addr[27:0], rx_binary_l}; // get a addr
|
||||
end else begin
|
||||
fsm <= TRASH;
|
||||
end
|
||||
CMD : if (`E) begin
|
||||
fsm <= NEW; // cmd ok!
|
||||
addr <= 0;
|
||||
wr_data <= 0;
|
||||
cmd <= NONE;
|
||||
end else if(`S) begin
|
||||
fsm <= CMD;
|
||||
end else begin
|
||||
fsm <= TRASH;
|
||||
end
|
||||
ADDR : if (`E) begin
|
||||
fsm <= NEW; // get a read command
|
||||
bus.rd_req <= 1'b1; // TODO : launch a bus read
|
||||
bus.rd_addr <= addr;
|
||||
addr <= 0;
|
||||
wr_data <= 0;
|
||||
cmd <= NONE;
|
||||
end else if(`N) begin
|
||||
fsm <= ADDR;
|
||||
addr <= {addr[27:0], rx_binary_l}; // get a addr
|
||||
end else if(`S) begin
|
||||
fsm <= EQUAL; // get addr down, waiting for data, maybe a write command
|
||||
end else begin
|
||||
fsm <= TRASH;
|
||||
end
|
||||
EQUAL : if (`E) begin
|
||||
fsm <= NEW; // get a read command
|
||||
bus.rd_req <= 1'b1; // TODO : launch a bus read
|
||||
bus.rd_addr <= addr;
|
||||
addr <= 0;
|
||||
wr_data <= 0;
|
||||
cmd <= NONE;
|
||||
end else if(`N) begin
|
||||
fsm <= DATA; // get a data
|
||||
wr_data <= {wr_data[27:0], rx_binary_l}; // get a data
|
||||
end else if(`S) begin
|
||||
fsm <= EQUAL;
|
||||
end else begin
|
||||
fsm <= TRASH;
|
||||
end
|
||||
DATA : if (`E) begin
|
||||
fsm <= NEW; // get a write command
|
||||
bus.wr_req <= 1'b1; // TODO : launch a bus write
|
||||
bus.wr_addr <= addr;
|
||||
bus.wr_data <= wr_data;
|
||||
addr <= 0;
|
||||
wr_data <= 0;
|
||||
cmd <= NONE;
|
||||
end else if(`N) begin
|
||||
fsm <= DATA; // get a data
|
||||
wr_data <= {wr_data[27:0], rx_binary_l}; // get a data
|
||||
end else if(`S) begin
|
||||
fsm <= FINAL; // get data down, waiting for \r or \n
|
||||
end else begin
|
||||
fsm <= TRASH;
|
||||
end
|
||||
FINAL : if (`E) begin
|
||||
fsm <= NEW; // get a write command
|
||||
bus.wr_req <= 1'b1; // TODO : launch a bus write
|
||||
bus.wr_addr <= addr;
|
||||
bus.wr_data <= wr_data;
|
||||
addr <= 0;
|
||||
wr_data <= 0;
|
||||
cmd <= NONE;
|
||||
end else if(`S) begin
|
||||
fsm <= FINAL; // get addr down, waiting for \r or \n
|
||||
end else begin
|
||||
fsm <= TRASH;
|
||||
end
|
||||
default : if (`E) begin
|
||||
// get a syntax error
|
||||
fsm <= NEW;
|
||||
addr <= 0;
|
||||
wr_data <= 0;
|
||||
cmd <= NONE;
|
||||
end else begin
|
||||
fsm <= TRASH;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
30
RTL/naive_bus.sv
Normal file
30
RTL/naive_bus.sv
Normal file
@ -0,0 +1,30 @@
|
||||
`ifndef NAIVE_BUS_SV
|
||||
`define NAIVE_BUS_SV
|
||||
|
||||
interface naive_bus();
|
||||
// read interface
|
||||
logic rd_req, rd_gnt;
|
||||
logic [3:0] rd_be;
|
||||
logic [31:0] rd_addr, rd_data;
|
||||
// write interface
|
||||
logic wr_req, wr_gnt;
|
||||
logic [3:0] wr_be;
|
||||
logic [31:0] wr_addr, wr_data;
|
||||
|
||||
modport master(
|
||||
output rd_req, rd_be, rd_addr,
|
||||
input rd_data, rd_gnt,
|
||||
output wr_req, wr_be, wr_addr, wr_data,
|
||||
input wr_gnt
|
||||
);
|
||||
|
||||
modport slave(
|
||||
input rd_req, rd_be, rd_addr,
|
||||
output rd_data, rd_gnt,
|
||||
input wr_req, wr_be, wr_addr, wr_data,
|
||||
output wr_gnt
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
||||
`endif
|
118
RTL/naive_bus_router.sv
Normal file
118
RTL/naive_bus_router.sv
Normal file
@ -0,0 +1,118 @@
|
||||
module naive_bus_router #(
|
||||
parameter [7:0] N_MASTER = 2,
|
||||
parameter [7:0] N_SLAVE = 3,
|
||||
parameter [0:N_SLAVE-1][31:0] SLAVES_MASK = { 32'h0000_3fff , 32'h0000_3fff , 32'h0000_3fff },
|
||||
parameter [0:N_SLAVE-1][31:0] SLAVES_BASE = { 32'h0000_0000 , 32'h0001_0000 , 32'h0002_0000 }
|
||||
)(
|
||||
input logic clk, rst_n,
|
||||
naive_bus.slave masters [N_MASTER-1:0] ,
|
||||
naive_bus.master slaves [ N_SLAVE-1:0]
|
||||
);
|
||||
|
||||
`define SLAVE_ADDRESS(master_addr, slave_index) (master_addr) & ( SLAVES_MASK[slave_index] )
|
||||
`define SLAVE_INRANGE(master_addr, slave_index) ( ((master_addr) & (~SLAVES_MASK[slave_index]))==(SLAVES_BASE[slave_index]) )
|
||||
|
||||
logic [N_MASTER-1:0] masters_rd_req;
|
||||
logic [N_MASTER-1:0][ 3:0] masters_rd_be;
|
||||
logic [N_MASTER-1:0][31:0] masters_rd_addr;
|
||||
logic [N_MASTER-1:0] masters_wr_req;
|
||||
logic [N_MASTER-1:0][ 3:0] masters_wr_be;
|
||||
logic [N_MASTER-1:0][31:0] masters_wr_addr;
|
||||
logic [N_MASTER-1:0][31:0] masters_wr_data;
|
||||
logic [N_MASTER-1:0] masters_rd_gnt = 1'b0;
|
||||
logic [N_MASTER-1:0][ 7:0] master_rd_slv_index = {N_MASTER{N_SLAVE}};
|
||||
logic [N_MASTER-1:0][ 7:0] master_rd_slv_index_latch = {N_MASTER{N_SLAVE}};
|
||||
logic [N_MASTER-1:0][ 7:0] slv = {N_MASTER{N_SLAVE}};
|
||||
|
||||
logic [N_SLAVE-1:0] slaves_wr_gnt, slaves_rd_gnt;
|
||||
logic [N_SLAVE-1:0][ 7:0] mst = {N_SLAVE{N_MASTER}};
|
||||
logic [N_SLAVE-1:0][ 7:0] slaves_wr_mst_index = {N_SLAVE{N_MASTER}};
|
||||
logic [N_SLAVE-1:0][ 7:0] slaves_rd_mst_index = {N_SLAVE{N_MASTER}};
|
||||
logic [N_SLAVE :0][31:0] slaves_rd_data;
|
||||
|
||||
|
||||
assign slaves_rd_data[N_SLAVE] = 0;
|
||||
|
||||
generate
|
||||
genvar slv_i_assign;
|
||||
for(slv_i_assign=0; slv_i_assign<N_SLAVE; slv_i_assign++) begin: assign_slaves
|
||||
assign slaves_wr_gnt[slv_i_assign] = slaves[slv_i_assign].wr_gnt;
|
||||
assign slaves_rd_gnt[slv_i_assign] = slaves[slv_i_assign].rd_gnt;
|
||||
assign slaves_rd_data[slv_i_assign]= slaves[slv_i_assign].rd_data;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
generate
|
||||
genvar mst_i_assign;
|
||||
for(mst_i_assign=0; mst_i_assign<N_MASTER; mst_i_assign++) begin: assign_masters
|
||||
assign masters_rd_req [mst_i_assign] = masters[mst_i_assign].rd_req;
|
||||
assign masters_rd_be [mst_i_assign] = masters[mst_i_assign].rd_be;
|
||||
assign masters_rd_addr[mst_i_assign] = masters[mst_i_assign].rd_addr;
|
||||
assign masters_wr_req [mst_i_assign] = masters[mst_i_assign].wr_req;
|
||||
assign masters_wr_be [mst_i_assign] = masters[mst_i_assign].wr_be;
|
||||
assign masters_wr_addr[mst_i_assign] = masters[mst_i_assign].wr_addr;
|
||||
assign masters_wr_data[mst_i_assign] = masters[mst_i_assign].wr_data;
|
||||
assign masters[mst_i_assign].rd_gnt = masters_rd_gnt[mst_i_assign];
|
||||
assign masters[mst_i_assign].rd_data = slaves_rd_data[master_rd_slv_index_latch[mst_i_assign]];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
generate
|
||||
genvar slv_i;
|
||||
for(slv_i=0; slv_i<N_SLAVE; slv_i++) begin: generate_slave_loop
|
||||
always_comb begin
|
||||
slaves[slv_i].rd_req = 1'b0;
|
||||
slaves[slv_i].rd_be = 4'h0;
|
||||
slaves[slv_i].rd_addr = 0;
|
||||
slaves_rd_mst_index[slv_i] = N_MASTER;
|
||||
slaves[slv_i].wr_req = 1'b0;
|
||||
slaves[slv_i].wr_be = 4'h0;
|
||||
slaves[slv_i].wr_addr = 0;
|
||||
slaves[slv_i].wr_data = 0;
|
||||
slaves_wr_mst_index[slv_i] = N_MASTER;
|
||||
for(mst[slv_i]=0; mst[slv_i]<N_MASTER; mst[slv_i]+=1) begin
|
||||
if( `SLAVE_INRANGE(masters_rd_addr[mst[slv_i]], slv_i) & masters_rd_req[mst[slv_i]] ) begin
|
||||
slaves[slv_i].rd_req = 1'b1;
|
||||
slaves[slv_i].rd_be = masters_rd_be[mst[slv_i]];
|
||||
slaves[slv_i].rd_addr = `SLAVE_ADDRESS(masters_rd_addr[mst[slv_i]], slv_i);
|
||||
slaves_rd_mst_index[slv_i] = mst[slv_i];
|
||||
end
|
||||
if( `SLAVE_INRANGE(masters_wr_addr[mst[slv_i]], slv_i) & masters_wr_req[mst[slv_i]] ) begin
|
||||
slaves[slv_i].wr_req = 1'b1;
|
||||
slaves[slv_i].wr_be = masters_wr_be[mst[slv_i]];
|
||||
slaves[slv_i].wr_addr = `SLAVE_ADDRESS(masters_wr_addr[mst[slv_i]], slv_i);
|
||||
slaves[slv_i].wr_data = masters_wr_data[mst[slv_i]];
|
||||
slaves_wr_mst_index[slv_i] = mst[slv_i];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
generate
|
||||
genvar mst_i;
|
||||
for(mst_i=0; mst_i<N_MASTER; mst_i++) begin: generate_master_loop
|
||||
always_comb begin
|
||||
masters[mst_i].wr_gnt = 1'b1;
|
||||
masters_rd_gnt[mst_i] = 1'b1;
|
||||
master_rd_slv_index[mst_i] = N_SLAVE;
|
||||
for(slv[mst_i]=0; slv[mst_i]<N_SLAVE; slv[mst_i]+=1) begin
|
||||
if( `SLAVE_INRANGE(masters_rd_addr[mst_i], slv[mst_i]) ) begin
|
||||
masters_rd_gnt[mst_i] = (slaves_rd_mst_index[slv[mst_i]]==mst_i) ? slaves_rd_gnt[slv[mst_i]] : 1'b0;
|
||||
master_rd_slv_index[mst_i] = masters_rd_gnt[mst_i] ? slv[mst_i] : N_SLAVE;
|
||||
end
|
||||
if( `SLAVE_INRANGE(masters_wr_addr[mst_i], slv[mst_i]) ) begin
|
||||
masters[mst_i].wr_gnt = (slaves_wr_mst_index[slv[mst_i]]==mst_i) ? slaves_wr_gnt[slv[mst_i]] : 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n)
|
||||
master_rd_slv_index_latch <= {N_MASTER{N_SLAVE}};
|
||||
else
|
||||
master_rd_slv_index_latch <= master_rd_slv_index;
|
||||
|
||||
endmodule
|
30
RTL/ram.sv
Normal file
30
RTL/ram.sv
Normal file
@ -0,0 +1,30 @@
|
||||
module ram( // 1024B
|
||||
input logic clk, rst_n,
|
||||
input logic i_we,
|
||||
input logic [ 9:0] i_waddr, i_raddr, i_raddr2,
|
||||
input logic [ 7:0] i_wdata,
|
||||
output logic [ 7:0] o_rdata, o_rdata2
|
||||
);
|
||||
|
||||
initial begin o_rdata = 8'h0; o_rdata2 = 8'h0; end
|
||||
|
||||
localparam SIZE = 1024;
|
||||
logic [SIZE-1:0] [7:0] data_ram_cell;
|
||||
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n)
|
||||
o_rdata <= 0;
|
||||
else
|
||||
o_rdata <= data_ram_cell[i_raddr];
|
||||
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n)
|
||||
o_rdata2 <= 0;
|
||||
else
|
||||
o_rdata2 <= data_ram_cell[i_raddr2];
|
||||
|
||||
always @ (posedge clk)
|
||||
if(i_we)
|
||||
data_ram_cell[i_waddr] <= i_wdata;
|
||||
|
||||
endmodule
|
51
RTL/ram_bus_wrapper.sv
Normal file
51
RTL/ram_bus_wrapper.sv
Normal file
@ -0,0 +1,51 @@
|
||||
module ram_bus_wrapper( // 4kB, valid address: 0x0000_0000 ~ 0x0000_0fff
|
||||
input logic clk, rst_n,
|
||||
naive_bus.slave bus
|
||||
);
|
||||
|
||||
logic [9:0] cell_rd_addr, cell_wr_addr;
|
||||
|
||||
assign cell_rd_addr = bus.rd_addr[11:2];
|
||||
assign cell_wr_addr = bus.wr_addr[11:2];
|
||||
|
||||
assign bus.rd_gnt = bus.rd_req;
|
||||
assign bus.wr_gnt = bus.wr_req;
|
||||
|
||||
ram ram_block_inst_0(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.i_we ( bus.wr_req & bus.wr_be[0] ),
|
||||
.i_waddr ( cell_wr_addr ),
|
||||
.i_raddr ( cell_rd_addr ),
|
||||
.i_wdata ( bus.wr_data[ 7: 0] ),
|
||||
.o_rdata ( bus.rd_data[ 7: 0] )
|
||||
);
|
||||
ram ram_block_inst_1(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.i_we ( bus.wr_req & bus.wr_be[1] ),
|
||||
.i_waddr ( cell_wr_addr ),
|
||||
.i_raddr ( cell_rd_addr ),
|
||||
.i_wdata ( bus.wr_data[15: 8] ),
|
||||
.o_rdata ( bus.rd_data[15: 8] )
|
||||
);
|
||||
ram ram_block_inst_2(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.i_we ( bus.wr_req & bus.wr_be[2] ),
|
||||
.i_waddr ( cell_wr_addr ),
|
||||
.i_raddr ( cell_rd_addr ),
|
||||
.i_wdata ( bus.wr_data[23:16] ),
|
||||
.o_rdata ( bus.rd_data[23:16] )
|
||||
);
|
||||
ram ram_block_inst_3(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.i_we ( bus.wr_req & bus.wr_be[3] ),
|
||||
.i_waddr ( cell_wr_addr ),
|
||||
.i_raddr ( cell_rd_addr ),
|
||||
.i_wdata ( bus.wr_data[31:24] ),
|
||||
.o_rdata ( bus.rd_data[31:24] )
|
||||
);
|
||||
|
||||
endmodule
|
99
RTL/soc_top.sv
Normal file
99
RTL/soc_top.sv
Normal file
@ -0,0 +1,99 @@
|
||||
module soc_top (
|
||||
// 时钟,要求50MHz
|
||||
input logic clk,
|
||||
// 调试器UART信号
|
||||
input logic isp_uart_rx,
|
||||
output logic isp_uart_tx,
|
||||
// 用户UART信号
|
||||
input logic user_uart_rx,
|
||||
output logic user_uart_tx,
|
||||
// VGA显示输出信号
|
||||
output logic vga_hsync, vga_vsync,
|
||||
output logic [15:0] vga_pixel
|
||||
);
|
||||
|
||||
logic rst_n, core_stop;
|
||||
|
||||
naive_bus bus_masters[3]();
|
||||
naive_bus bus_slaves[4]();
|
||||
|
||||
// 一个能作为naive bus 主设备的调试器
|
||||
// 它接收用户从UART发来的命令,操控复位等信号,或对总线进行读写。用户可以使用UART命令复位整个SoC,上传程序,或者查看运行时的RAM数据。
|
||||
isp_uart isp_uart_inst(
|
||||
.clk ( clk ),
|
||||
.i_uart_rx ( isp_uart_rx ),
|
||||
.o_uart_tx ( isp_uart_tx ),
|
||||
.o_rst_n ( rst_n ),
|
||||
.o_stop ( core_stop ),
|
||||
.bus ( bus_masters[0] )
|
||||
);
|
||||
|
||||
// RV32I 核
|
||||
core_top core_top_inst(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.i_stop ( core_stop ),
|
||||
.instr_master ( bus_masters[1] ),
|
||||
.data_master ( bus_masters[2] )
|
||||
);
|
||||
|
||||
// 指令ROM
|
||||
instr_rom instr_ram_inst(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.bus ( bus_slaves[0] )
|
||||
);
|
||||
|
||||
// 数据RAM
|
||||
|
||||
ram_bus_wrapper data_ram_inst(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.bus ( bus_slaves[1] )
|
||||
);
|
||||
|
||||
// 显存
|
||||
video_ram video_ram_inst(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.bus ( bus_slaves[2] ),
|
||||
.o_vsync ( vga_vsync ),
|
||||
.o_hsync ( vga_hsync ),
|
||||
.o_pixel ( vga_pixel )
|
||||
);
|
||||
|
||||
// 用户UART
|
||||
user_uart_tx user_uart_tx_inst(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.o_uart_tx ( user_uart_tx ),
|
||||
.bus ( bus_slaves[3] )
|
||||
);
|
||||
|
||||
|
||||
// 3主4从总线仲裁器
|
||||
//
|
||||
// 主(越靠前优先级越高):
|
||||
// 0. UART调试器
|
||||
// 1. Core Instr Master
|
||||
// 2. Core Data Master
|
||||
//
|
||||
// 从:
|
||||
// 1. 指令ROM, 地址空间 00000000~00000fff
|
||||
// 2. 数据RAM, 地址空间 00010000~00010fff
|
||||
// 3. 显存RAM, 地址空间 00020000~00020fff
|
||||
// 4. 用户UART,地址空间 00030000~00030003
|
||||
naive_bus_router #(
|
||||
.N_MASTER ( 3 ),
|
||||
.N_SLAVE ( 4 ),
|
||||
.SLAVES_MASK ( { 32'h0000_0003 , 32'h0000_0fff , 32'h0000_0fff , 32'h0000_0fff } ),
|
||||
.SLAVES_BASE ( { 32'h0003_0000 , 32'h0002_0000 , 32'h0001_0000 , 32'h0000_0000 } )
|
||||
) soc_bus_router_inst (
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.masters ( bus_masters ),
|
||||
.slaves ( bus_slaves )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
53
RTL/uart_rx.sv
Normal file
53
RTL/uart_rx.sv
Normal file
@ -0,0 +1,53 @@
|
||||
module uart_rx #(
|
||||
parameter UART_RX_CLK_DIV = 108 // 50MHz/4/115200Hz=108
|
||||
)(
|
||||
input logic clk,
|
||||
input logic i_rx,
|
||||
output logic o_ready,
|
||||
output logic [7:0] o_data
|
||||
);
|
||||
|
||||
logic rx_bit, busy, last_busy=1'b0;
|
||||
logic [ 5:0] shift = 6'h0, status = 6'h0;
|
||||
logic [ 7:0] databuf = 8'h0;
|
||||
logic [31:0] cnt = 0;
|
||||
|
||||
initial o_ready = 1'b0;
|
||||
initial o_data = 8'h0;
|
||||
|
||||
assign busy = (status!=6'h0);
|
||||
assign rx_bit = (shift[0]&shift[1]) | (shift[0]&i_rx) | (shift[1]&i_rx);
|
||||
|
||||
always @ (posedge clk)
|
||||
last_busy <= busy;
|
||||
|
||||
always @ (posedge clk)
|
||||
o_ready <= (~busy & last_busy);
|
||||
|
||||
always @ (posedge clk)
|
||||
cnt <= (cnt<UART_RX_CLK_DIV-1) ? cnt+1 : 0;
|
||||
|
||||
always @ (posedge clk)
|
||||
if(cnt==0) begin
|
||||
if(~busy) begin
|
||||
if(shift == 6'b111000)
|
||||
status <= 6'h1;
|
||||
end else begin
|
||||
if(status[5] == 1'b0) begin
|
||||
if(status[1:0] == 2'b11)
|
||||
databuf <= {rx_bit, databuf[7:1]};
|
||||
status <= status + 6'h1;
|
||||
end else begin
|
||||
if(status<62) begin
|
||||
status <= 6'd62;
|
||||
o_data <= databuf;
|
||||
end else begin
|
||||
status <= status + 6'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
shift <= shift<<1;
|
||||
shift[0] <= i_rx;
|
||||
end
|
||||
|
||||
endmodule
|
47
RTL/uart_tx_line.sv
Normal file
47
RTL/uart_tx_line.sv
Normal file
@ -0,0 +1,47 @@
|
||||
|
||||
module uart_tx_line #(
|
||||
parameter UART_TX_CLK_DIV = 434 // 50MHz/1/115200Hz=434
|
||||
)(
|
||||
input logic clk,
|
||||
output logic o_tx,
|
||||
input logic i_start,
|
||||
input logic [7:0][7:0] i_data
|
||||
);
|
||||
|
||||
logic [31:0] cnt = 0;
|
||||
logic [ 6:0] tx_cnt = 0;
|
||||
logic [90:0] tx_buffer, tx_shift;
|
||||
initial tx_shift = 91'h0;
|
||||
initial o_tx = 1'b1;
|
||||
|
||||
assign tx_buffer = {2'b11, 8'h0A , // 0x0A = \n , a end of line
|
||||
2'b01, i_data[0],
|
||||
2'b01, i_data[1],
|
||||
2'b01, i_data[2],
|
||||
2'b01, i_data[3],
|
||||
2'b01, i_data[4],
|
||||
2'b01, i_data[5],
|
||||
2'b01, i_data[6],
|
||||
2'b01, i_data[7],
|
||||
1'b0};
|
||||
|
||||
always @ (posedge clk)
|
||||
cnt <= (cnt<UART_TX_CLK_DIV-1) ? cnt+1 : 0;
|
||||
|
||||
always @ (posedge clk)
|
||||
if(tx_cnt>7'd0) begin
|
||||
if(cnt==0) begin
|
||||
{tx_shift, o_tx} <= {1'b1, tx_shift};
|
||||
tx_cnt <= tx_cnt - 7'd1;
|
||||
end
|
||||
end else begin
|
||||
o_tx <= 1'b1;
|
||||
if(i_start) begin
|
||||
tx_cnt <= 7'd93;
|
||||
tx_shift <= tx_buffer;
|
||||
end else begin
|
||||
tx_cnt <= 7'd0;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
99
RTL/user_uart_tx.sv
Normal file
99
RTL/user_uart_tx.sv
Normal file
@ -0,0 +1,99 @@
|
||||
|
||||
module user_uart_tx #(
|
||||
parameter UART_TX_CLK_DIV = 434 // 50MHz/1/115200Hz=434
|
||||
)(
|
||||
input logic clk, rst_n,
|
||||
output logic o_uart_tx,
|
||||
naive_bus.slave bus
|
||||
);
|
||||
localparam TX_CNT = 5'd19;
|
||||
|
||||
logic [ 7:0] fifo_rd_pointer=8'h0, fifo_wr_pointer=8'h0, fifo_len;
|
||||
logic fifo_full, fifo_empty;
|
||||
logic rd_addr_valid, wr_addr_valid;
|
||||
logic [31:0] cnt = 0;
|
||||
logic [ 4:0] tx_cnt = 0;
|
||||
logic [ 7:0] tx_shift = 8'h0;
|
||||
logic [ 7:0] fifo_rd_data;
|
||||
|
||||
initial o_uart_tx = 1'b1;
|
||||
|
||||
assign rd_addr_valid = (bus.rd_addr[31:2] == 30'h0);
|
||||
assign wr_addr_valid = (bus.wr_addr[31:2] == 30'h0);
|
||||
|
||||
assign fifo_len = fifo_wr_pointer - fifo_rd_pointer;
|
||||
assign fifo_empty = (fifo_len==8'h00);
|
||||
assign fifo_full = (fifo_len==8'hff);
|
||||
|
||||
assign bus.rd_gnt = bus.rd_req;
|
||||
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n)
|
||||
bus.rd_data <= 0;
|
||||
else begin
|
||||
if(bus.rd_req & rd_addr_valid)
|
||||
bus.rd_data <= {24'h0, fifo_len};
|
||||
else
|
||||
bus.rd_data <= 0;
|
||||
end
|
||||
|
||||
always_comb
|
||||
if(bus.wr_req) begin
|
||||
if(wr_addr_valid && bus.wr_be[0]) begin
|
||||
bus.wr_gnt <= ~fifo_full;
|
||||
end else begin
|
||||
bus.wr_gnt <= 1'b1;
|
||||
end
|
||||
end else begin
|
||||
bus.wr_gnt <= 1'b0;
|
||||
end
|
||||
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n) begin
|
||||
fifo_wr_pointer <= 8'h0;
|
||||
end else begin
|
||||
if(bus.wr_req & wr_addr_valid & bus.wr_be[0] & ~fifo_full) begin
|
||||
fifo_wr_pointer <= fifo_wr_pointer + 8'h1;
|
||||
end
|
||||
end
|
||||
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n)
|
||||
cnt <= 0;
|
||||
else
|
||||
cnt <= (cnt<UART_TX_CLK_DIV-1) ? cnt+1 : 0;
|
||||
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n) begin
|
||||
fifo_rd_pointer <= 8'h0;
|
||||
o_uart_tx <= 1'b1;
|
||||
tx_shift <= 8'hff;
|
||||
tx_cnt <= 5'h0;
|
||||
end else begin
|
||||
if(tx_cnt>5'd0) begin
|
||||
if(cnt==0) begin
|
||||
if(tx_cnt==TX_CNT) begin
|
||||
{tx_shift, o_uart_tx} <= {fifo_rd_data, 1'b0};
|
||||
fifo_rd_pointer <= fifo_rd_pointer + 8'h1;
|
||||
end else begin
|
||||
{tx_shift, o_uart_tx} <= {1'b1, tx_shift};
|
||||
end
|
||||
tx_cnt <= tx_cnt - 5'd1;
|
||||
end
|
||||
end else begin
|
||||
o_uart_tx <= 1'b1;
|
||||
tx_cnt <= fifo_empty ? 5'd0 : TX_CNT;
|
||||
end
|
||||
end
|
||||
|
||||
ram ram_for_uart_tx_fifo_inst(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.i_we ( bus.wr_req & wr_addr_valid & bus.wr_be[0] & ~fifo_full ),
|
||||
.i_waddr ( {2'h0,fifo_wr_pointer} ),
|
||||
.i_wdata ( bus.wr_data[7:0] ),
|
||||
.i_raddr ( {2'h0,fifo_rd_pointer} ),
|
||||
.o_rdata ( fifo_rd_data )
|
||||
);
|
||||
|
||||
endmodule
|
318
RTL/video_ram.sv
Normal file
318
RTL/video_ram.sv
Normal file
@ -0,0 +1,318 @@
|
||||
|
||||
module video_ram(
|
||||
input logic clk, rst_n,
|
||||
output logic o_hsync, o_vsync,
|
||||
output logic [15:0] o_pixel,
|
||||
naive_bus.slave bus
|
||||
);
|
||||
|
||||
logic [ 9:0] vga_addr_h;
|
||||
logic [ 1:0] vga_addr_l, vga_addr_l_latch = 2'b00;
|
||||
logic [ 7:0] vga_ascii;
|
||||
logic [ 9:0] cell_rd_addr, cell_wr_addr;
|
||||
logic [ 7:0] vga_rdata [4];
|
||||
|
||||
assign cell_rd_addr = bus.rd_addr[11:2];
|
||||
assign cell_wr_addr = bus.wr_addr[11:2];
|
||||
|
||||
assign bus.rd_gnt = bus.rd_req;
|
||||
assign bus.wr_gnt = bus.wr_req;
|
||||
|
||||
always @ (posedge clk or negedge rst_n)
|
||||
if(~rst_n)
|
||||
vga_addr_l_latch <= 2'b00;
|
||||
else
|
||||
vga_addr_l_latch <= vga_addr_l;
|
||||
|
||||
ram ram_block_inst_0(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.i_we ( bus.wr_req & bus.wr_be[0] ),
|
||||
.i_waddr ( cell_wr_addr ),
|
||||
.i_raddr ( cell_rd_addr ),
|
||||
.i_wdata ( bus.wr_data[ 7: 0] ),
|
||||
.o_rdata ( bus.rd_data[ 7: 0] ),
|
||||
.i_raddr2 ( vga_addr_h ),
|
||||
.o_rdata2 ( vga_rdata[0] )
|
||||
);
|
||||
ram ram_block_inst_1(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.i_we ( bus.wr_req & bus.wr_be[1] ),
|
||||
.i_waddr ( cell_wr_addr ),
|
||||
.i_raddr ( cell_rd_addr ),
|
||||
.i_wdata ( bus.wr_data[15: 8] ),
|
||||
.o_rdata ( bus.rd_data[15: 8] ),
|
||||
.i_raddr2 ( vga_addr_h ),
|
||||
.o_rdata2 ( vga_rdata[1] )
|
||||
);
|
||||
ram ram_block_inst_2(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.i_we ( bus.wr_req & bus.wr_be[2] ),
|
||||
.i_waddr ( cell_wr_addr ),
|
||||
.i_raddr ( cell_rd_addr ),
|
||||
.i_wdata ( bus.wr_data[23:16] ),
|
||||
.o_rdata ( bus.rd_data[23:16] ),
|
||||
.i_raddr2 ( vga_addr_h ),
|
||||
.o_rdata2 ( vga_rdata[2] )
|
||||
);
|
||||
ram ram_block_inst_3(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.i_we ( bus.wr_req & bus.wr_be[3] ),
|
||||
.i_waddr ( cell_wr_addr ),
|
||||
.i_raddr ( cell_rd_addr ),
|
||||
.i_wdata ( bus.wr_data[31:24] ),
|
||||
.o_rdata ( bus.rd_data[31:24] ),
|
||||
.i_raddr2 ( vga_addr_h ),
|
||||
.o_rdata2 ( vga_rdata[3] )
|
||||
);
|
||||
|
||||
always_comb
|
||||
case(vga_addr_l_latch)
|
||||
2'b00 : vga_ascii <= vga_rdata[0];
|
||||
2'b01 : vga_ascii <= vga_rdata[1];
|
||||
2'b10 : vga_ascii <= vga_rdata[2];
|
||||
2'b11 : vga_ascii <= vga_rdata[3];
|
||||
endcase
|
||||
|
||||
vgaChar98x36 vga_char_inst(
|
||||
.clk ( clk ),
|
||||
.hsync ( o_hsync ),
|
||||
.vsync ( o_vsync ),
|
||||
.pixel ( o_pixel ),
|
||||
//.req ( vga_req ),
|
||||
.addr ( {vga_addr_h,vga_addr_l} ),
|
||||
.ascii ( vga_ascii )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
module vgaChar98x36(
|
||||
// clock
|
||||
input clk,
|
||||
// vga interfaces
|
||||
output hsync, vsync,
|
||||
output [15:0] pixel,
|
||||
// user interface
|
||||
output req,
|
||||
output [11:0] addr,
|
||||
input [7:0] ascii
|
||||
);
|
||||
wire b;
|
||||
wire [15:0] req_pixel;
|
||||
reg [15:0] border;
|
||||
|
||||
wire [2:0] x_l;
|
||||
wire [3:0] y_l;
|
||||
wire [6:0] x_h;
|
||||
wire [5:0] y_h;
|
||||
wire [9:0] x, y;
|
||||
|
||||
assign {x_h, x_l} = x - 10'd8;
|
||||
assign {y_h, y_l} = y - 10'd12;
|
||||
|
||||
assign addr = y_h * 12'd98 + x_h;
|
||||
|
||||
vga vga_inst(
|
||||
.clk (clk),
|
||||
.hsync (hsync),
|
||||
.vsync (vsync),
|
||||
.pixel (pixel),
|
||||
.req (req),
|
||||
.x (x),
|
||||
.y (y),
|
||||
.req_pixel (req_pixel)
|
||||
);
|
||||
|
||||
assign req_pixel = ( x>=8 && x<(800-8) && y>=12 && y<(600-12) ) ? {16{b}} : border;
|
||||
|
||||
always @ (posedge clk)
|
||||
if(req)
|
||||
border <= ( x<5 || x>(800-5) || y<5 || y>(600-5) ) ? 16'hff00 : 16'h0000;
|
||||
|
||||
char8x16 char_8x16_inst(
|
||||
.ascii (ascii),
|
||||
.x (x_l),
|
||||
.y (y_l),
|
||||
.b (b)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module vga(
|
||||
// clock
|
||||
input clk,
|
||||
// vga interface
|
||||
output reg hsync, vsync,
|
||||
output reg [15:0] pixel,
|
||||
// user interface
|
||||
output req,
|
||||
output [ 9:0] x, y,
|
||||
input [15:0] req_pixel
|
||||
);
|
||||
localparam H_END = 800,
|
||||
H_SYNCSTART = H_END + 8,
|
||||
H_SYNCEND = H_SYNCSTART + 128,
|
||||
H_PERIOD = H_SYNCEND + 72,
|
||||
|
||||
V_END = 600,
|
||||
V_SYNCSTART = V_END + 8,
|
||||
V_SYNCEND = V_SYNCSTART + 4,
|
||||
V_PERIOD = V_SYNCEND + 36;
|
||||
|
||||
reg [31:0] hcnt,vcnt;
|
||||
|
||||
always @ (posedge clk)
|
||||
hcnt <= (hcnt<H_PERIOD) ? hcnt + 1 : 0;
|
||||
|
||||
always @ (posedge clk)
|
||||
hsync <= ~(hcnt>=H_SYNCSTART && hcnt<H_SYNCEND);
|
||||
|
||||
always @ (posedge hsync)
|
||||
vcnt <= (vcnt<V_PERIOD) ? vcnt + 1 : 0;
|
||||
|
||||
always @ (posedge hsync)
|
||||
vsync <= ~(vcnt>=V_SYNCSTART && vcnt<V_SYNCEND);
|
||||
|
||||
wire h_range = hcnt<H_END;
|
||||
wire v_range = vcnt<V_END;
|
||||
wire range = (h_range & v_range);
|
||||
|
||||
assign x = range ? hcnt[9:0] : 10'h0;
|
||||
assign y = range ? vcnt[9:0] : 10'h0;
|
||||
|
||||
assign req = range;
|
||||
|
||||
always @ (posedge clk)
|
||||
if(hcnt>0 && hcnt<=H_END && v_range)
|
||||
pixel <= req_pixel;
|
||||
else
|
||||
pixel <= 16'h0;
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ASCII when ascii<128, user code when ascii>=128
|
||||
module char8x16(
|
||||
input [7:0] ascii,
|
||||
input [2:0] x,
|
||||
input [3:0] y,
|
||||
output b
|
||||
);
|
||||
wire [6:0] addr = ~{y,x};
|
||||
assign b = char[addr];
|
||||
|
||||
reg [127:0] char;
|
||||
always @ (*)
|
||||
case(ascii)
|
||||
33: char <= 128'h00000018181818181808000818000000; //!0
|
||||
34: char <= 128'h00000034242424000000000000000000; //"1
|
||||
35: char <= 128'h0000000016247F2424247E2424000000; //#2
|
||||
36: char <= 128'h000000083E6848681C1612127C101000; //$3
|
||||
37: char <= 128'h00000061D296740810162949C6000000; //%4
|
||||
38: char <= 128'h000000003C646438724ACE467F000000; //&5
|
||||
39: char <= 128'h00000018181818000000000000000000; //'6
|
||||
40: char <= 128'h00000004081810303030301010180C04; //(7
|
||||
41: char <= 128'h000000201008080C0404040C08181020; //)8
|
||||
42: char <= 128'h000000080A341C6A0800000000000000; //*9
|
||||
43: char <= 128'h0000000000001818187F181818000000; //+10
|
||||
44: char <= 128'h00000000000000000000001818083000; //,11
|
||||
45: char <= 128'h0000000000000000003C000000000000; //-12
|
||||
46: char <= 128'h00000000000000000000001818000000; //.13
|
||||
47: char <= 128'h0000000206040C080810102020400000; ///14
|
||||
48: char <= 128'h000000003C6642475B7342663C000000; //015
|
||||
49: char <= 128'h0000000018784808080808087E000000; //116
|
||||
50: char <= 128'h000000003C460606040810207E000000; //217
|
||||
51: char <= 128'h000000007C0606043C0202067C000000; //318
|
||||
52: char <= 128'h000000000C1C14246444FF0404000000; //419
|
||||
53: char <= 128'h000000007E6060607E0202067C000000; //520
|
||||
54: char <= 128'h000000001E306048764242623C000000; //621
|
||||
55: char <= 128'h000000007E0206040C08181030000000; //722
|
||||
56: char <= 128'h000000003C6242361C6642423C000000; //823
|
||||
57: char <= 128'h000000003C664242661A020478000000; //924
|
||||
58: char <= 128'h00000000000018180000001818000000; //:25
|
||||
59: char <= 128'h00000000000018180000001818083000; //;26
|
||||
60: char <= 128'h00000000000004183060100C06000000; //<27
|
||||
61: char <= 128'h00000000000000007E007E0000000000; //=28
|
||||
62: char <= 128'h000000000000301804060C1020000000; //>29
|
||||
63: char <= 128'h000000301C0606061810001010000000; //?30
|
||||
64: char <= 128'h0000001C224141DDB5A5A5AF94C0403C; //@31
|
||||
65: char <= 128'h00000000181C342426627E43C1000000; //A32
|
||||
66: char <= 128'h000000007C4642467C4242427C000000; //B33
|
||||
67: char <= 128'h000000001E204040404040603E000000; //C34
|
||||
68: char <= 128'h000000007C4642434343424678000000; //D35
|
||||
69: char <= 128'h000000007E6060607E6060607E000000; //E36
|
||||
70: char <= 128'h000000007E6060607E60606060000000; //F37
|
||||
71: char <= 128'h000000001E604040CE4242623E000000; //G38
|
||||
72: char <= 128'h00000000424242427E42424242000000; //H39
|
||||
73: char <= 128'h000000007E181818181818187E000000; //I40
|
||||
74: char <= 128'h000000007C0404040404044478000000; //J41
|
||||
75: char <= 128'h000000004244485070584C4442000000; //K42
|
||||
76: char <= 128'h0000000020202020202020203E000000; //L43
|
||||
77: char <= 128'h000000006266675F5B5BC1C1C1000000; //M44
|
||||
78: char <= 128'h00000000626272525A4A4E4646000000; //N45
|
||||
79: char <= 128'h000000003C6243C3C3C343623C000000; //O46
|
||||
80: char <= 128'h000000007C4642424678404040000000; //P47
|
||||
81: char <= 128'h000000003C6243C3C3C343623C180F00; //Q48
|
||||
82: char <= 128'h000000007C6662667C6C646662000000; //R49
|
||||
83: char <= 128'h000000003E6040601C0602027C000000; //S50
|
||||
84: char <= 128'h000000007F1818181818181818000000; //T51
|
||||
85: char <= 128'h0000000042424242424242623C000000; //U52
|
||||
86: char <= 128'h00000000C14342622624341C18000000; //V53
|
||||
87: char <= 128'h00000000C1C141495B5B766666000000; //W54
|
||||
88: char <= 128'h0000000043663418181C2466C3000000; //X55
|
||||
89: char <= 128'h00000000C14266341C18181818000000; //Y56
|
||||
90: char <= 128'h000000007E02040C181020607E000000; //Z57
|
||||
91: char <= 128'h0000001C10101010101010101010101C; //[58
|
||||
92: char <= 128'h000000402020101008080C0406020000; //\59
|
||||
93: char <= 128'h0000003C0C0C0C0C0C0C0C0C0C0C0C3C; //]60
|
||||
94: char <= 128'h00000000181C24620000000000000000; //^61
|
||||
95: char <= 128'h000000000000000000000000000000FF; //_62
|
||||
96: char <= 128'h00000020100000000000000000000000; //`63
|
||||
97: char <= 128'h0000000000003C06023E42467A000000; //a64
|
||||
98: char <= 128'h0000004040405C62424242427C000000; //b65
|
||||
99: char <= 128'h0000000000001E20604060203E000000; //c66
|
||||
100: char <= 128'h0000000202023E62424242663A000000; //d67
|
||||
101: char <= 128'h0000000000003C62427E40603E000000; //e68
|
||||
102: char <= 128'h0000000F1810107E1010101010000000; //f69
|
||||
103: char <= 128'h0000000000003F66426658403E43423C; //g70
|
||||
104: char <= 128'h0000004040405C624242424242000000; //h71
|
||||
105: char <= 128'h0000001818007808080808087E000000; //i72
|
||||
106: char <= 128'h000000040C007C040404040404040C78; //j73
|
||||
107: char <= 128'h000000606060626C7870686462000000; //k74
|
||||
108: char <= 128'h0000007808080808080808087E000000; //l75
|
||||
109: char <= 128'h000000000000764B4B4B4B4B4B000000; //m76
|
||||
110: char <= 128'h0000000000005C624242424242000000; //n77
|
||||
111: char <= 128'h0000000000003C62424342623C000000; //o78
|
||||
112: char <= 128'h0000000000005C62424242427C404040; //p79
|
||||
113: char <= 128'h0000000000003E62424242663A020202; //q80
|
||||
114: char <= 128'h0000000000006E726360606060000000; //r81
|
||||
115: char <= 128'h0000000000003E20203C06027C000000; //s82
|
||||
116: char <= 128'h000000001010FE10101010101E000000; //t83
|
||||
117: char <= 128'h0000000000004242424242663A000000; //u84
|
||||
118: char <= 128'h00000000000043426624341818000000; //v85
|
||||
119: char <= 128'h000000000000C1C15B5A5E6666000000; //w86
|
||||
120: char <= 128'h00000000000062261C181C2662000000; //x87
|
||||
121: char <= 128'h00000000000043426624341C181830E0; //y88
|
||||
122: char <= 128'h0000000000007E060C1810207E000000; //z89
|
||||
123: char <= 128'h0000000E18101010307010101010180E; //{90
|
||||
124: char <= 128'h00000808080808080808080808080808; //|91
|
||||
125: char <= 128'h00000030180808080C0E080808081830; //}92
|
||||
126: char <= 128'h0000000000000000714B060000000000; //~93
|
||||
default char <= 128'h0;
|
||||
endcase
|
||||
|
||||
endmodule
|
Loading…
x
Reference in New Issue
Block a user