mirror of
https://github.com/MPSU/APS.git
synced 2025-09-15 17:20:10 +00:00
335 lines
8.3 KiB
Systemverilog
335 lines
8.3 KiB
Systemverilog
/* -----------------------------------------------------------------------------
|
|
* Project Name : Architectures of Processor Systems (APS) lab work
|
|
* Organization : National Research University of Electronic Technology (MIET)
|
|
* Department : Institute of Microdevices and Control Systems
|
|
* Author(s) : Alexander Kharlamov
|
|
* Email(s) : sasha_xarlamov@org.miet.ru
|
|
|
|
See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
|
|
* ------------------------------------------------------------------------------
|
|
*/
|
|
typedef enum {
|
|
INSTR_ALU , // branch and computational
|
|
INSTR_LI , // const load
|
|
INSTR_IN , // periphery load
|
|
INSTR_JUMP ,
|
|
INSTR_NOP // ws == 3
|
|
} Instruction_type;
|
|
|
|
typedef enum {
|
|
CH_0 = 0,
|
|
CH_1,
|
|
CH_2,
|
|
CH_3,
|
|
CH_4,
|
|
CH_5,
|
|
CH_6,
|
|
CH_7,
|
|
CH_8,
|
|
CH_9,
|
|
CH_A,
|
|
CH_b,
|
|
CH_c,
|
|
CH_d,
|
|
CH_E,
|
|
CH_F,
|
|
CH_G,
|
|
CH_L,
|
|
CH_n,
|
|
CH_o,
|
|
CH_r,
|
|
CH_S,
|
|
CH_t,
|
|
CH_u,
|
|
CH_X,
|
|
CH_P,
|
|
CH_J,
|
|
CH_q,
|
|
CH_i,
|
|
CH_m,
|
|
CH_y,
|
|
CH_h,
|
|
|
|
CH_SPACE
|
|
} Char;
|
|
|
|
typedef struct {
|
|
logic ca;
|
|
logic cb;
|
|
logic cc;
|
|
logic cd;
|
|
logic ce;
|
|
logic cf;
|
|
logic cg;
|
|
logic dp;
|
|
} Semseg;
|
|
|
|
module nexys_riscv_unit(
|
|
input logic clk_i,
|
|
input logic arstn_i,
|
|
input logic btnd_i,
|
|
output logic ca_o,
|
|
output logic cb_o,
|
|
output logic cc_o,
|
|
output logic cd_o,
|
|
output logic ce_o,
|
|
output logic cf_o,
|
|
output logic cg_o,
|
|
output logic dp_o,
|
|
output logic [ 7:0] an_o
|
|
);
|
|
|
|
logic btnd_sync;
|
|
sync sync (
|
|
.clk_i ,
|
|
.data_i (btnd_i ),
|
|
.data_o (btnd_sync)
|
|
);
|
|
logic btnd_debounce;
|
|
debounce debounce (
|
|
.clk_i ,
|
|
.arstn_i (1'b1 ),
|
|
.data_i (btnd_sync ),
|
|
.data_o (btnd_debounce)
|
|
);
|
|
logic bufg_clk;
|
|
BUFG dut_bufg(
|
|
.I (btnd_debounce),
|
|
.O (bufg_clk )
|
|
);
|
|
|
|
processor_system unit(
|
|
.clk_i (bufg_clk),
|
|
.rst_i (!arstn_i)
|
|
);
|
|
|
|
logic [31:0] instr_addr;
|
|
logic [31:0] instr;
|
|
assign instr_addr = unit.core.instr_addr_o;
|
|
assign instr = unit.core.instr_i;
|
|
|
|
import alu_opcodes_pkg::*;
|
|
|
|
logic illegal_instr;
|
|
|
|
logic [6:0] opcode;
|
|
assign opcode = instr[6:0];
|
|
|
|
Char op_chars[0:3];
|
|
import decoder_pkg::*;
|
|
always_comb begin
|
|
op_chars = '{4{CH_SPACE}};
|
|
|
|
case (opcode)
|
|
{LOAD_OPCODE , 2'b11}: op_chars = '{CH_L, CH_o, CH_A, CH_d};
|
|
{MISC_MEM_OPCODE, 2'b11}: op_chars = '{CH_m, CH_i, CH_S, CH_c};
|
|
{OP_IMM_OPCODE , 2'b11}: op_chars = '{CH_o, CH_P, CH_i, CH_m};
|
|
{AUIPC_OPCODE , 2'b11}: op_chars = '{CH_A, CH_u, CH_i, CH_P};
|
|
{STORE_OPCODE , 2'b11}: op_chars = '{CH_S, CH_t, CH_o, CH_r};
|
|
{OP_OPCODE , 2'b11}: op_chars[0:1] = '{CH_o, CH_P};
|
|
{LUI_OPCODE , 2'b11}: op_chars[0:2] = '{CH_L, CH_u, CH_i};
|
|
{BRANCH_OPCODE , 2'b11}: op_chars = '{CH_b, CH_r, CH_c, CH_h};
|
|
{JALR_OPCODE , 2'b11}: op_chars = '{CH_J, CH_A, CH_L, CH_r};
|
|
{JAL_OPCODE , 2'b11}: op_chars[0:2] = '{CH_J, CH_A, CH_L};
|
|
{SYSTEM_OPCODE , 2'b11}: op_chars[0:2] = '{CH_S, CH_y, CH_S};
|
|
|
|
default : op_chars[0:2] = '{CH_i, CH_L, CH_L};
|
|
endcase
|
|
end
|
|
|
|
Char all_chars[0:7];
|
|
assign all_chars[0:3] = {
|
|
Char'(instr_addr[15:12]),
|
|
Char'(instr_addr[11: 8]),
|
|
Char'(instr_addr[ 7: 4]),
|
|
Char'(instr_addr[ 3: 0])
|
|
};
|
|
assign all_chars[4:7] = op_chars;
|
|
|
|
Char current_char;
|
|
logic [7:0] an;
|
|
semseg_one2many #(
|
|
.DATA_T (Char)
|
|
) semseg_one2many (
|
|
.clk100m_i (clk_i ),
|
|
.arstn_i (arstn_i ),
|
|
.all_semsegs_i (all_chars ),
|
|
.current_semseg_o (current_char),
|
|
.an_o (an )
|
|
);
|
|
|
|
Semseg current_semseg;
|
|
char2semseg char2semseg (
|
|
.char_i (current_char ),
|
|
.semseg_o (current_semseg)
|
|
);
|
|
|
|
assign ca_o = current_semseg.ca;
|
|
assign cb_o = current_semseg.cb;
|
|
assign cc_o = current_semseg.cc;
|
|
assign cd_o = current_semseg.cd;
|
|
assign ce_o = current_semseg.ce;
|
|
assign cf_o = current_semseg.cf;
|
|
assign cg_o = current_semseg.cg;
|
|
assign dp_o = current_semseg.dp;
|
|
|
|
assign an_o = an;
|
|
|
|
endmodule
|
|
|
|
module char2semseg #(
|
|
parameter bit HEX_ONLY = 1'b0
|
|
) (
|
|
input Char char_i,
|
|
output Semseg semseg_o
|
|
);
|
|
|
|
localparam bit [6:0] BLANK = '1;
|
|
|
|
logic [6:0] semseg;
|
|
always_comb begin
|
|
case (char_i)
|
|
CH_0 : semseg = ~7'h3F;
|
|
CH_1 : semseg = ~7'h06;
|
|
CH_2 : semseg = ~7'h5B;
|
|
CH_3 : semseg = ~7'h4F;
|
|
CH_4 : semseg = ~7'h66;
|
|
CH_5 : semseg = ~7'h6D;
|
|
CH_6 : semseg = ~7'h7D;
|
|
CH_7 : semseg = ~7'h07;
|
|
CH_8 : semseg = ~7'h7F;
|
|
CH_9 : semseg = ~7'h6F;
|
|
CH_A : semseg = ~7'h5F;
|
|
CH_b : semseg = ~7'h7C;
|
|
CH_c : semseg = ~7'h58;
|
|
CH_d : semseg = ~7'h5E;
|
|
CH_E : semseg = ~7'h79;
|
|
CH_F : semseg = ~7'h71;
|
|
CH_G : semseg = ~7'h3D;
|
|
CH_L : semseg = ~7'h38;
|
|
CH_n : semseg = ~7'h54;
|
|
CH_o : semseg = ~7'h5C;
|
|
CH_r : semseg = ~7'h50;
|
|
CH_S : semseg = ~7'h64;
|
|
CH_t : semseg = ~7'h78;
|
|
CH_u : semseg = ~7'h1C;
|
|
CH_X : semseg = ~7'h76;
|
|
CH_P : semseg = ~7'h73;
|
|
CH_J : semseg = ~7'h1E;
|
|
CH_q : semseg = ~7'h67;
|
|
CH_i : semseg = ~7'h30;
|
|
CH_m : semseg = ~7'h77;
|
|
CH_y : semseg = ~7'h6E;
|
|
CH_h : semseg = ~7'h74;
|
|
default : semseg = BLANK;
|
|
endcase
|
|
end
|
|
|
|
assign semseg_o.ca = semseg[0];
|
|
assign semseg_o.cb = semseg[1];
|
|
assign semseg_o.cc = semseg[2];
|
|
assign semseg_o.cd = semseg[3];
|
|
assign semseg_o.ce = semseg[4];
|
|
assign semseg_o.cf = semseg[5];
|
|
assign semseg_o.cg = semseg[6];
|
|
assign semseg_o.dp = 1'b1;
|
|
|
|
endmodule
|
|
|
|
module semseg_one2many #(
|
|
parameter int unsigned SEMSEGS_NUM = 8,
|
|
parameter type DATA_T
|
|
) (
|
|
input DATA_T all_semsegs_i[0:SEMSEGS_NUM-1],
|
|
input logic clk100m_i,
|
|
input logic arstn_i,
|
|
output DATA_T current_semseg_o,
|
|
output logic [7:0] an_o
|
|
);
|
|
logic clk_i;
|
|
assign clk_i = clk100m_i;
|
|
|
|
localparam int COUNTER_WIDTH = 10;
|
|
logic [COUNTER_WIDTH-1:0] counter_next;
|
|
logic [COUNTER_WIDTH-1:0] counter_ff;
|
|
assign counter_next = counter_ff + COUNTER_WIDTH'('b1);
|
|
always_ff @(posedge clk_i or negedge arstn_i) begin
|
|
if (!arstn_i) counter_ff <= '0;
|
|
else counter_ff <= counter_next;
|
|
end
|
|
|
|
logic [7:0] an_ff;
|
|
logic [7:0] an_next;
|
|
logic an_en;
|
|
assign an_next = {an_ff[$left(an_ff)-1:0], an_ff[$left(an_ff)]};
|
|
assign an_en = ~|counter_ff;
|
|
always_ff @(posedge clk_i or negedge arstn_i) begin
|
|
if (!arstn_i) an_ff <= ~8'b1;
|
|
else if (an_en) an_ff <= an_next;
|
|
end
|
|
|
|
DATA_T current_semseg;
|
|
always_comb begin
|
|
unique case (1'b0)
|
|
an_ff[0]: current_semseg = all_semsegs_i[7];
|
|
an_ff[1]: current_semseg = all_semsegs_i[6];
|
|
an_ff[2]: current_semseg = all_semsegs_i[5];
|
|
an_ff[3]: current_semseg = all_semsegs_i[4];
|
|
an_ff[4]: current_semseg = all_semsegs_i[3];
|
|
an_ff[5]: current_semseg = all_semsegs_i[2];
|
|
an_ff[6]: current_semseg = all_semsegs_i[1];
|
|
an_ff[7]: current_semseg = all_semsegs_i[0];
|
|
endcase
|
|
end
|
|
|
|
assign current_semseg_o = current_semseg;
|
|
|
|
assign an_o = an_ff;
|
|
|
|
endmodule
|
|
|
|
module debounce #(
|
|
parameter int unsigned MAX_COUNT = 10000
|
|
) (
|
|
input logic clk_i,
|
|
input logic arstn_i,
|
|
input logic data_i,
|
|
output logic data_o
|
|
);
|
|
|
|
localparam int COUNTER_WIDTH = $clog2(MAX_COUNT);
|
|
logic [COUNTER_WIDTH-1:0] counter_next;
|
|
logic [COUNTER_WIDTH-1:0] counter_ff;
|
|
assign counter_next = (data_o != data_i) ? counter_ff - COUNTER_WIDTH'('b1) :
|
|
COUNTER_WIDTH'(MAX_COUNT);
|
|
always_ff @(posedge clk_i or negedge arstn_i) begin
|
|
if (!arstn_i) counter_ff <= COUNTER_WIDTH'(MAX_COUNT);
|
|
else counter_ff <= counter_next;
|
|
end
|
|
|
|
always_ff @(posedge clk_i or negedge arstn_i) begin
|
|
if (!arstn_i) data_o <= '0;
|
|
else if (~|counter_ff) data_o <= data_i;
|
|
end
|
|
|
|
endmodule
|
|
|
|
module sync #(
|
|
parameter int unsigned SYNC_STAGES = 3
|
|
) (
|
|
input logic clk_i,
|
|
input logic data_i,
|
|
output logic data_o
|
|
);
|
|
|
|
logic [SYNC_STAGES-1:0] sync_buffer_ff;
|
|
logic [SYNC_STAGES-1:0] sync_buffer_next;
|
|
assign sync_buffer_next = {sync_buffer_ff[$left(sync_buffer_ff)-1:0], data_i};
|
|
always_ff @(posedge clk_i) begin
|
|
sync_buffer_ff <= sync_buffer_next;
|
|
end
|
|
|
|
assign data_o = sync_buffer_ff[$left(sync_buffer_ff)];
|
|
|
|
endmodule
|