Hi guys, I'm a newbie in learning Verilog, I have written a simple FSM below, and now I wanna change it using pipeline to increase the performance, but I'm so confused because I haven't learnt pipeline since I finished this FSM, can anyone help me to rewrite it using pipeline and tell me the difference between them, thanks in advance:
module processor (
input wire clk,
input wire rst
);
localparam FETCH = 3'b000, LOAD_INS = 3'b001, LOAD_MEM = 3'b010, STORE_RF = 3'b011, EXECUTE = 3'b100, STORE_RF_ALU = 3'b101, STORE_MEM = 3'b110;
wire [1:0] rf_readaddr1, rf_readaddr2, rf_write_addr;
wire [7:0] rf_write_data, rf_read_data1, rf_read_data2;
wire rf_we;
register_file RF (
.clk(clk),
.we(rf_we),
.read_addr1(rf_readaddr1),
.read_addr2(rf_readaddr2),
.write_addr(rf_write_addr),
.write_data(rf_write_data),
.read_data1(rf_read_data1),
.read_data2(rf_read_data2)
);
wire [7:0] alu_x, alu_y, alu_out;
wire alu_sl;
alu alu (
.clk(clk),
.x(alu_x),
.y(alu_y),
.alu_sl(alu_sl),
.alu_out(alu_out)
);
wire dm_we;
wire [1:0] dm_addr;
wire [7:0] dm_write_data, dm_read_data;
data_memory DM (
.clk(clk),
.we(dm_we),
.addr(dm_addr),
.write_data(dm_write_data),
.read_data(dm_read_data)
);
wire [3:0] pm_addr;
wire [7:0] pm_instr;
program_memory PM (
.clk(clk),
.addr(pm_addr),
.instr(pm_instr)
);
// State change
reg [2:0] state, next;
always @(*) begin
next = 2'bx;
case (state)
FETCH: begin
next = LOAD_INS;
end
LOAD_INS: begin
if (pm_instr[7:6] == 2'b10)
next = LOAD_MEM;
else if (pm_instr[7:6] == 2'b11)
next = STORE_MEM;
else next = EXECUTE;
end
LOAD_MEM: begin
next = STORE_RF;
end
STORE_RF: begin
next = FETCH;
end
EXECUTE: begin
next = STORE_RF_ALU;
end
STORE_RF_ALU: begin
next = FETCH;
end
STORE_MEM: begin
next = FETCH;
end
endcase
end
always @(posedge clk) begin
if (rst) begin
state <= FETCH;
end else begin
state <= next;
end
end
// fetch instruction
reg [3:0] pc;
reg [7:0] temp_ins;
always @(posedge clk) begin
if (rst) begin
pc <= 0;
end else begin
if (state == FETCH) pc <= pc + 1;
end
end
assign pm_addr = pc;
// load instruction
always @(posedge clk) begin
if (state == LOAD_INS) temp_ins <= pm_instr;
end
// state EXE
reg op;
always @(*) begin
op = 1'bx;
if (state == EXECUTE) begin
case(temp_ins[7:6])
2'b00: begin // ADD
op = 1'b0;
end
2'b01: begin // SUB
op = 1'b1;
end
endcase
end
end
assign alu_sl = op;
assign rf_readaddr1 = temp_ins[5:4];
assign rf_readaddr2 = temp_ins[3:2];
assign alu_x = rf_read_data1;
assign alu_y = rf_read_data2;
// memory signal assign
assign dm_we = (state == STORE_MEM);
assign dm_write_data = (state == STORE_MEM) ? rf_read_data1:0;
assign dm_addr = (state == LOAD_MEM || state == STORE_MEM) ? temp_ins[3:2]:2'b0;
// register file store
reg [7:0] write_data_rf;
always @(*) begin
write_data_rf = 8'bx;
case(state)
STORE_RF: begin
write_data_rf = dm_read_data;
end
STORE_RF_ALU: begin
write_data_rf = alu_out;
end
endcase
end
assign rf_write_data = write_data_rf;
assign rf_write_addr = (state == STORE_RF || state == STORE_RF_ALU) ? temp_ins[1:0]:2'b0;
assign rf_we = (state == STORE_RF || state == EXECUTE || state == STORE_RF_ALU);
endmodule
//Change it into pipeline by the simplest way (just add some blocks and register)