■ Datapath 설계
module datapath_unit (clk, start, rw, sa, sb, dr, fs, pc, mb, md, mm, data_in, vflg, cflg, nflg, zflg, data_out, addr_out);
parameter BW = 16;
input clk, start, rw;
input [2:0] sa, sb, dr;
input [4:0] fs;
input [7:0] pc; // 9비트여야 하니깐 나중에 결합연산자로 0을 넣어
input mb, md, mm;
input [BW-1:0] data_in;
output reg vflg, cflg, nflg, zflg;
output wire [BW-1:0] data_out;
output wire [9:0] addr_out;
wire [BW-1:0] opra, oprb, r_oprb;
wire [BW-1:0] r_din;
wire [BW-1:0] din;
wire s_vflg, s_cflg, s_nflg, s_zflg;
register_file R1 (.clk(clk), .st(start), .rw(rw), .sel_sa(sa), .sel_sb(sb), .sel_d(dr), .din(din), .opra(opra), .oprb(r_oprb));
func_unit F1 (.opra(opra), .oprb(oprb), .sa(sa), .fs(fs), .f_out(r_din), .v_flag(s_vflg), .c_flag(s_cflg), .n_flag(s_nflg), .z_flag(s_zflg));
always @(posedge clk)
begin
if (start==1'b0) begin
vflg <= 1'b0;
cflg <= 1'b0;
nflg <= 1'b0;
zflg <= 1'b0;
end
else if (rw) begin
vflg <= s_vflg;
cflg <= s_cflg;
nflg <= s_nflg;
zflg <= s_zflg;
end
end
assign oprb = (mb) ? {13'b0, sb} : r_oprb;
assign data_out = oprb;
assign addr_out = (mm) ? {1'b0, pc} : opra[8:0];
assign din = (md) ? data_in : r_din;
endmodule
module tb_datapath;
reg clk=1'b1, start, rw;
reg [2:0] sa, sb, dr;
reg mb, md, mm;
reg [15:0] data_in;
reg [4:0] fs;
reg [7:0] pc;
wire vflg, cflg, nflg, zflg;
wire [15:0] data_out;
wire [8:0] addr_out;
always #100 clk = ~clk;
datapath_unit D1 (clk, start, rw, sa, sb, dr, fs, pc, mb, md, mm, data_in, vflg, cflg, nflg, zflg, data_out, addr_out);
initial
begin
start = 1'b0;
#40 start = 1'b1;
#40 sa = 3'b101; sb = 3'b111; data_in = 16'b1100_0011_1100_0011; fs = 5'b00000; mb =1'b0; rw = 1'b1; md = 1'b1; dr = 3'b111;
#230 dr = 3'b101;
#230 md = 1'b0;
#230 dr = 3'b011;
#230 dr = 3'b100;
#230 dr = 3'b101;
#230 dr = 3'b110;
#230 dr = 3'b111;
#230 fs = 5'b00000;
#230 fs = 5'b00001;
#230 fs = 5'b00010;
#230 fs = 5'b00011;
#230 fs = 5'b00100;
#230 fs = 5'b00101;
#230 fs = 5'b00111;
#230 fs = 5'b01000;
#230 fs = 5'b01010;
#230 fs = 5'b01100;
#230 fs = 5'b01110;
#230 fs = 5'b10000;
#230 fs = 5'b10010;
#230 fs = 5'b10100;
#230 fs = 5'b10110;
#230 fs = 5'b11000;
#230 fs = 5'b11010;
#230 fs = 5'b11100;
#230 fs = 5'b11100;
#230 fs = 5'b11111;
#230 fs = 5'b11111;
#200;
$stop;
// start = 1'b0;
// #40 start = 1'b1;
// #40 sa = 3'b101; sb = 3'b111; data_in = 16'b1100_0011_1100_0011; fs = 5'b00000; mb =1'b0; rw = 1'b1; md = 1'b1; dr = 3'b111;
// #80;
// $stop;
end
endmodule
module up_control (clk, start, sa, sb, dr, fs, pc, rw, mw, mb, md, mm, data_in, vflg, cflg, nflg, zflg);
parameter BW = 16;
parameter S_ADDR = 8'h0;
parameter IF_ADDR = 8'hFE;
input clk, start;
//output ta, tb, td;
output reg [2:0] sa, sb, dr;
output reg [4:0] fs;
output wire [7:0] pc; //512-words LPM_RAM_DQ
output reg rw, mw, mb, md, mm;
input [BW-1:0] data_in;
input vflg, cflg, nflg, zflg;
wire ta, tb, td;
reg [6:0] ir_ca_opr;
wire [27:0] cm_out;
reg pc_ctrl;
reg pl;
reg pi;
reg il;
reg mc;
reg [2:0] ms;
reg [7:0] na;
reg [7:0] t_pc;
reg [7:0] s_pc;
reg [7:0] t_ca_reg;
reg [7:0] s_ca_reg;
wire [7:0] ca_reg;
always @(start, pc_ctrl, pl, pi, s_pc, dr[1:0], sa, sb, t_pc)
begin
if (!start)
t_pc = S_ADDR;
else if (pl) begin
if (pc_ctrl) begin
if (pi)
t_pc = s_pc+{dr[1:0],sa,sb};
else
t_pc = {dr[1:0],sa,sb};
end
else
t_pc = s_pc;
end
else
t_pc = s_pc + pi;
end
always @(posedge clk, negedge start)
begin
if (!start)
s_pc <= 8'b0;
else if (pl | pi)
s_pc <= t_pc;
end
assign pc = t_pc;//s_pc;//
always @(posedge clk, negedge start)
begin
if (!start) begin
sb <= 3'b0;
sa <= 3'b0;
dr <= 3'b0;
end
else if (il) begin
sb <= data_in[2:0];
sa <= data_in[5:3];
dr <= data_in[8:6];
end
end
always @(data_in[15:9])
begin
ir_ca_opr = data_in[15:9];
end
always @(posedge clk, negedge start)
begin
if (!start)
pc_ctrl <= 1'b0;
else begin
case (ms)
3'h0 : pc_ctrl <= 1'b0;
3'h1 : pc_ctrl <= 1'b1;
3'h2 : pc_ctrl <= cflg;
3'h3 : pc_ctrl <= vflg;
3'h4 : pc_ctrl <= zflg;
3'h5 : pc_ctrl <= nflg;
3'h6 : pc_ctrl <= ~cflg;
default : pc_ctrl = ~zflg; //3'h7
endcase
end
end
always @(start ,mc, ir_ca_opr, na)
begin
if (!start)
t_ca_reg = IF_ADDR;
else begin
if (mc==1'b1)
t_ca_reg = {1'b0,ir_ca_opr};
else
t_ca_reg = na;
end
end
assign ca_reg = t_ca_reg;
//ram_256x28b inst_ram_256x28b (.address(ca_reg), .clock(clk), .data(28'b0), .wren(1'b0), .q(cm_out));
rom_28x256b inst_rom_28x256b (.clka(clk), .ena(1'b1), .addra(ca_reg), .douta(cm_out));
/*
rw, mw, mb, md, mm;
assign mw = start & cm_out[0];
assign mm = start & cm_out[1];
assign rw = start & cm_out[2];
assign md = start & cm_out[3];
assign mb = start & cm_out[9];
assign fs = {5{start}} & cm_out[8:4];
*/
assign tb = start & cm_out[10];
assign ta = start & cm_out[11];
assign td = start & cm_out[12];
always @(posedge clk, negedge start)
begin
if (!start) begin
il <= 1'b0;
pl <= 1'b0;
pi <= 1'b0;
fs <= 5'b0;
// mw <= 1'b0;
rw <= 1'b0;
// mm <= 1'b0;
md <= 1'b0;
mb <= 1'b0;
//ms <= 3'b0;
end
else begin
il <= cm_out[15];
pl <= cm_out[13];
pi <= cm_out[14];
fs <= cm_out[8:4];
// mw <= cm_out[0];
rw <= cm_out[2];
// mm <= cm_out[1];
md <= cm_out[3];
mb <= cm_out[9];
//ms <= cm_out[19:17];
end
end
always @(start, cm_out[27:16])
begin
if (!start) begin
mc = 1'b0;
ms = 3'b0;
na = 8'b0;
mw = 1'b0;
//rw = 1'b0;
mm = 1'b0;
//md = 1'b0;
//mb = 1'b0;
end
else begin
mc = cm_out[16];
ms = cm_out[19:17];
na = cm_out[27:20];
mw = cm_out[0];
//rw = cm_out[2];
mm = cm_out[1];
//md = cm_out[3];
//mb = cm_out[9];
end
end
endmodule
`timescale 1ns / 1ps
module cpu(clk, start);
input clk;
input start;
wire [2:0] sa, sb, dr;
wire [4:0] fs;
wire [7:0] pc;
wire rw, mw, mb, md, mm;
wire vflg, cflg, nflg, zflg;
wire [15:0] data_in, data_out;
wire [8:0] addr_out;
wire r0_reg;
up_control up1 (clk, start, sa, sb, dr, fs, pc, rw, mw, mb, md, mm, data_in, vflg, cflg, nflg, zflg);
datapath_unit dp1 (clk, start, rw, sa, sb, dr, fs, pc, mb, md, mm, data_in, vflg, cflg, nflg, zflg, data_out, addr_out, r0_reg);
ram_512x16b inst_ram_512x16b (.clka(clk), .ena(1'b1), .wea(mw), .addra(addr_out), .dina(data_out), .douta(data_in));
endmodule