// sm_rom.v
module sm_rom
#(
parameter SIZE = 64
)
(
input [31:0] a,
output [31:0] rd
);
reg [31:0] rom [SIZE - 1:0];
assign rd = rom [a];
initial begin
$readmemh ("program.hex", rom);
end
endmodule
// sm_top.v
sm_rom reset_rom(imAddr, imData);
// sr_cpu.v
module sr_decode
(
input [31:0] instr,
output [ 6:0] cmdOp,
output [ 4:0] rd,
output [ 2:0] cmdF3,
output [ 4:0] rs1,
output [ 4:0] rs2,
output [ 6:0] cmdF7,
output reg [31:0] immI,
output reg [31:0] immB,
output reg [31:0] immU
);
assign cmdOp = instr[ 6: 0];
assign rd = instr[11: 7];
assign cmdF3 = instr[14:12];
assign rs1 = instr[19:15];
assign rs2 = instr[24:20];
assign cmdF7 = instr[31:25];
// I-immediate
always @ (*) begin
immI[10: 0] = instr[30:20];
immI[31:11] = { 21 {instr[31]} };
end
// B-immediate
always @ (*) begin
immB[ 0] = 1'b0;
immB[ 4: 1] = instr[11:8];
immB[10: 5] = instr[30:25];
immB[31:11] = { 21 {instr[31]} };
end
// U-immediate
always @ (*) begin
immU[11: 0] = 12'b0;
immU[31:12] = instr[31:12];
end
endmodule
// sr_cpu.v
module sm_register_file
(
input clk,
input [ 4:0] a0,
input [ 4:0] a1,
input [ 4:0] a2,
input [ 4:0] a3,
output [31:0] rd0,
output [31:0] rd1,
output [31:0] rd2,
input [31:0] wd3,
input we3
);
reg [31:0] rf [31:0];
assign rd0 = (a0 != 0) ? rf [a0] : 32'b0;
assign rd1 = (a1 != 0) ? rf [a1] : 32'b0;
assign rd2 = (a2 != 0) ? rf [a2] : 32'b0;
always @ (posedge clk)
if(we3) rf [a3] <= wd3;
endmodule
// sr_cpu.vh
`define ALU_ADD 3'b000 // A + B
`define ALU_OR 3'b001 // A | B
`define ALU_SRL 3'b010 // A >> B
`define ALU_SLTU 3'b011 // A < B ? 1 : 0
`define ALU_SUB 3'b100 // A - B
// sr_cpu.v
module sr_alu
(
input [31:0] srcA,
input [31:0] srcB,
input [ 2:0] oper,
output zero,
output reg [31:0] result
);
always @ (*) begin
case (oper)
default : result = srcA + srcB;
`ALU_ADD : result = srcA + srcB;
`ALU_OR : result = srcA | srcB;
`ALU_SRL : result = srcA >> srcB [4:0];
`ALU_SLTU : result = (srcA < srcB) ? 1 : 0;
`ALU_SUB : result = srcA - srcB;
endcase
end
assign zero = (result == 0);
endmodule
// sr_cpu.v
wire [31:0] srcB = aluSrc ? immI : rd2;
// sr_cpu.v
assign wd3 = wdSrc ? immU : aluResult;
// sr_cpu.vh
// instruction opcode
`define RVOP_ADDI 7'b0010011
`define RVOP_BEQ 7'b1100011
...
// instruction funct3
`define RVF3_ADDI 3'b000
`define RVF3_BEQ 3'b000
`define RVF3_BNE 3'b001
`define RVF3_ADD 3'b000
...
`define RVF3_ANY 3'b???
// instruction funct7
`define RVF7_ADD 7'b0000000
...
`define RVF7_ANY 7'b???????
// sr_cpu.v
module sr_control
(
input [ 6:0] cmdOp,
input [ 2:0] cmdF3,
input [ 6:0] cmdF7,
input aluZero,
output pcSrc,
output reg regWrite,
output reg aluSrc,
output reg wdSrc,
output reg [2:0] aluControl
);
reg branch;
reg condZero;
assign pcSrc = branch & (aluZero == condZero);
// sr_cpu.v
always @ (*) begin
branch = 1'b0;
condZero = 1'b0;
regWrite = 1'b0;
aluSrc = 1'b0;
wdSrc = 1'b0;
aluControl = `ALU_ADD;
casez( {cmdF7, cmdF3, cmdOp} )
{ `RVF7_ADD, `RVF3_ADD, `RVOP_ADD } : begin regWrite = 1'b1; aluControl = `ALU_ADD; end
{ `RVF7_OR, `RVF3_OR, `RVOP_OR } : begin regWrite = 1'b1; aluControl = `ALU_OR; end
{ `RVF7_SRL, `RVF3_SRL, `RVOP_SRL } : begin regWrite = 1'b1; aluControl = `ALU_SRL; end
{ `RVF7_SLTU, `RVF3_SLTU, `RVOP_SLTU } : begin regWrite = 1'b1; aluControl = `ALU_SLTU; end
{ `RVF7_SUB, `RVF3_SUB, `RVOP_SUB } : begin regWrite = 1'b1; aluControl = `ALU_SUB; end
{ `RVF7_ANY, `RVF3_ADDI, `RVOP_ADDI } : begin regWrite = 1'b1; aluSrc = 1'b1; aluControl = `ALU_ADD; end
{ `RVF7_ANY, `RVF3_ANY, `RVOP_LUI } : begin regWrite = 1'b1; wdSrc = 1'b1; end
{ `RVF7_ANY, `RVF3_BEQ, `RVOP_BEQ } : begin branch = 1'b1; condZero = 1'b1; aluControl = `ALU_SUB; end
{ `RVF7_ANY, `RVF3_BNE, `RVOP_BNE } : begin branch = 1'b1; aluControl = `ALU_SUB; end
endcase
end
Цифровая схемотехника и архитектура компьютера
David Harris & Sarah Harris
ДМК Пресс
Цифровой синтез: практический курс
Александр Романов & Юрий Панчул
ДМК Пресс
Syntacore SCR1
https://github.com/syntacore/scr1