first commit

This commit is contained in:
WangXuan95 2019-02-05 16:19:46 +08:00
commit d12408b6d7
80 changed files with 2092 additions and 0 deletions

79
ASM/asm2verilogrom.py Normal file
View 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
View 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
View 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
View 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 # t1a1
jal zero, program_end #
fibonacci_recursive: # n
# nt0
# 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
View 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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

9
ASM/simpletest.S Normal file
View 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
View 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
View File

@ -0,0 +1,31 @@
.org 0x0
.global _start
_start:
# t0=0x00030000user_uart
or t0, zero,zero # t0
lui t0, 0x00030 # t0 20bit=0x00020
# hello!user_uarthello!uart
print_hello:
ori t1, zero, 0x068 # t1='h'ASCII
sb t1, (t0) # t1t0
ori t1, zero, 0x065 # t1='e'ASCII
sb t1, (t0) # t1t0
ori t1, zero, 0x06c # t1='l'ASCII
sb t1, (t0) # t1t0
ori t1, zero, 0x06c # t1='l'ASCII
sb t1, (t0) # t1t0
ori t1, zero, 0x06f # t1='o'ASCII
sb t1, (t0) # t1t0
ori t1, zero, 0x021 # t1='!'ASCII
sb t1, (t0) # t1t0
ori t1, zero, 0x00a # t1='\n'ASCII
sb t1, (t0) # t1t0
#
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
View 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 = {

1
README.md Normal file
View File

@ -0,0 +1 @@
# USTCRVSoC

49
RTL/core_alu.sv Normal file
View 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
View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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