`timescale 1ns / 1ps module DSP(CLK,RST,A,B,OPCODE,DATA_id,REQUEST_COUNTER,PROCESS_COUNTER,OUTA,OUT_MAC,OUT_SHIFT_ID); input [15:0]A,B; input CLK,RST; input [3:0]OPCODE; input [4:0]DATA_id; output reg[31:0]OUTA, OUT_MAC; output reg[15:0]OUT_SHIFT_ID; reg [40:0]STACK_in; wire [31:0]OUT_a,OUT_mac; wire [15:0]OUT_sid; wire [40:0]CONTROL_out, RAM_out, EX_out, STACK_out; wire [48:0]ADDRESS_out; wire [7:0]wr_add, rd_add; wire [3:0]DSP_in, DSP_sel; wire [2:0]ALU_sel, ALU_in; wire [4:0]PROCESS_COMPLETE_ALU, PROCESS_COMPLETE_DSP, DATA_WRITE_COMPLETE; wire wr_en, rd_en; reg [4:0]PROCESS_COMPLETE; output reg [4:0] REQUEST_COUNTER,PROCESS_COUNTER; reg [4:0]DATA_id_old,PROCESS_old; reg STATE; reg COUNT; reg CLK_2; always @(posedge CLK) begin if(RST) begin {COUNT,STATE} <=0; CLK_2<=CLK; end else begin case(STATE) 1'b0:begin if(COUNT<1) begin COUNT<=COUNT+1'b1; CLK_2<=1'b1; STATE<=1'b0; end else begin CLK_2<=1'b0; STATE<=1; COUNT<=0; end end 1'b1:begin if(COUNT<1) begin COUNT<=COUNT+1'b1; CLK_2<=1'b0; STATE<=1'b1; end else begin CLK_2<=1'b1; STATE<=0; COUNT<=0; end end endcase end end always @(posedge CLK) begin if(RST) begin {DATA_id_old,PROCESS_old,REQUEST_COUNTER,PROCESS_COUNTER} = 0; end else begin if(DATA_id_old!=DATA_id) begin REQUEST_COUNTER = REQUEST_COUNTER + 5'b00001; DATA_id_old = DATA_id; end else begin REQUEST_COUNTER = REQUEST_COUNTER; DATA_id_old = DATA_id_old; end if(PROCESS_old!=PROCESS_COMPLETE) begin PROCESS_COUNTER = PROCESS_COUNTER + 5'b00001; PROCESS_old = PROCESS_COMPLETE; end else begin PROCESS_COUNTER = PROCESS_COUNTER; PROCESS_old = PROCESS_old; end end end always @ (posedge CLK) begin if(RST) {OUTA,OUT_MAC,OUT_SHIFT_ID,STACK_in,PROCESS_COMPLETE} = 0; else begin STACK_in = {A,B,OPCODE,DATA_id}; OUTA=OUT_a; OUT_MAC=OUT_mac; OUT_SHIFT_ID=OUT_sid; PROCESS_COMPLETE = PROCESS_COMPLETE_ALU + PROCESS_COMPLETE_DSP; end end STACK ST(CLK, RST, STACK_in, STACK_out); ADD_GEN ADGN(CLK, RST, STACK_out, ADDRESS_out); CONTROL CTRL(CLK, RST, ADDRESS_out, CONTROL_out, wr_en, wr_add, DATA_WRITE_COMPLETE); RAM_BLOCK RB( CLK, CLK_2, RST, CONTROL_out, RAM_out, rd_en, wr_en, rd_add, wr_add, DATA_WRITE_COMPLETE); EXECUTE EX(CLK_2, RST, RAM_out, PROCESS_COMPLETE, EX_out, DSP_sel, DSP_in, ALU_sel, ALU_in, rd_en, rd_add); PROGRAM_MEMORY1 PM(CLK_2, RST, EX_out[8:5], ALU_sel, DSP_sel); ALU A16(EX_out[40:25],EX_out[24:9],EX_out[4:0],OUT_a,PROCESS_COMPLETE_ALU,ALU_in,CLK_2,RST); DSP_UNIT DSP(EX_out[40:25],EX_out[24:9],OUT_mac,OUT_sid,EX_out[4:0],PROCESS_COMPLETE_DSP,DSP_in,CLK_2,RST); endmodule module STACK(CLK,RST,OPCODE_id,STACK_out); input CLK,RST; input [40:0]OPCODE_id; parameter MEMSIZE = 16, WORDSIZE = 41; integer i; output reg [40:0]STACK_out; reg [WORDSIZE-1:0]STACK[MEMSIZE-1:0]; reg [4:0]OPCODE_id_old; reg [4:0]OPCODE_id_new; reg [3:0]j; always @(posedge CLK) begin if (RST) begin for(i=15;i>=0;i=i-1) begin STACK[i]=0; end OPCODE_id_old = 0; STACK_out=0; j=0; OPCODE_id_new=0; end else OPCODE_id_new = OPCODE_id[4:0]; begin if(OPCODE_id_old != OPCODE_id_new) begin for(i=0;i<15;i=i+1) begin STACK[i]=STACK[i+1]; end STACK[15]=OPCODE_id; OPCODE_id_old = OPCODE_id_new; end else OPCODE_id_old = OPCODE_id_old; end if(STACK[j]== 41'h0000) j=j+4'b0001; else begin STACK_out=STACK[j]; end end endmodule module ADD_GEN(CLK,RST,OPCODE_id,ADD_out); input CLK,RST; input [40:0]OPCODE_id; output reg [48:0]ADD_out; integer i; reg [40:0]OPCODE_id_old; reg [255:0]ADD_id; reg pointer; initial begin {OPCODE_id_old, ADD_id, ADD_out}=0; end always @ (posedge CLK) begin if(RST) begin {OPCODE_id_old, ADD_id, ADD_out}=0; end else if (OPCODE_id_old != OPCODE_id) begin pointer=1'b0; for(i=0;i<=255;i=i+1) begin if((ADD_id[i]==1'b0)&&(pointer==1'b0)) begin ADD_out ={OPCODE_id,i[7:0]}; ADD_id[i] = 1'b1; OPCODE_id_old = OPCODE_id; pointer=1'b1; end else begin OPCODE_id_old = OPCODE_id_old; end end end end endmodule module CONTROL(CLK,RST,DATA_in,DATA_out,wr_en,wr_add,DATA_WRITE_COMPLETE); input CLK,RST; input [48:0]DATA_in; output reg wr_en; output reg[40:0]DATA_out; output reg[7:0]wr_add; reg [4:0]OPCODE_id_old; input [4:0]DATA_WRITE_COMPLETE; always @ (posedge CLK) begin if (RST) begin OPCODE_id_old = 0; wr_en = 0; wr_add = 0; DATA_out = 0; end else begin if(OPCODE_id_old != DATA_in[12:8]) begin wr_en = 1; wr_add = DATA_in[7:0]; DATA_out = DATA_in[48:8]; OPCODE_id_old = DATA_in[12:8]; end else if(DATA_WRITE_COMPLETE == DATA_in[12:8]) begin wr_en = 0; end else begin wr_add = wr_add; DATA_out = DATA_out; OPCODE_id_old = OPCODE_id_old; end end end endmodule module RAM_BLOCK(CLK, CLK_2, RST, DATA_in, DATA_out, rd_en, wr_en, rd_add, wr_add,DATA_WRITE_COMPLETE); input CLK, CLK_2, RST, rd_en, wr_en; input wire [7:0]rd_add, wr_add; input [40:0] DATA_in; output reg [40:0] DATA_out; output reg [4:0] DATA_WRITE_COMPLETE; reg [15:0]A_in, B_in; wire [15:0]a,b; reg [3:0] OPCODE_in; wire [3:0] op; reg [4:0] OPCODE_id_in; wire [4:0] op_id,DATA_WRITE_COMPLETE_a; always @ (posedge CLK) begin if(RST) DATA_WRITE_COMPLETE<=0; else begin DATA_WRITE_COMPLETE<=DATA_WRITE_COMPLETE_a; {A_in, B_in, OPCODE_in, OPCODE_id_in} <= DATA_in; end end always @ (posedge CLK_2) begin if(RST) DATA_out <=0; else begin DATA_out <= {a,b,op,op_id}; end end RAM256 RAM_A(CLK, CLK_2, RST, A_in, a, rd_en, wr_en, rd_add, wr_add); RAM256 RAM_B(CLK, CLK_2, RST, B_in, b, rd_en, wr_en, rd_add, wr_add); RAM256_OP RAM_OPCODE(CLK, CLK_2, RST, OPCODE_in, op, rd_en, wr_en, rd_add, wr_add); RAM256_OP_id RAM_OPCODE_id(CLK, CLK_2, RST, OPCODE_id_in, op_id, rd_en, wr_en, rd_add, wr_add,DATA_WRITE_COMPLETE_a); endmodule module RAM256(clk, CLK_2, rst, data_in, data_out, rd_en, wr_en, rd_add, wr_add); input CLK_2, rst, clk, rd_en, wr_en; input [7:0]rd_add, wr_add; input [15:0] data_in; output reg [15:0] data_out; parameter WORDSIZE = 16, MEMSIZE = 256 ; reg[WORDSIZE-1:0]RAM[MEMSIZE-1:0]; integer i; always @(posedge clk) begin if(rst) begin for(i=0;i<=255;i=i+1) begin RAM[i]=0; end end else begin if(wr_en==1'b1) RAM[wr_add]=data_in; else RAM[wr_add]=RAM[wr_add]; end end always @ (posedge CLK_2) begin if (rst) data_out=0; else begin if(rd_en==1'b1) data_out=RAM[rd_add]; else data_out=data_out; end end endmodule module RAM256_OP_id(clk, CLK_2, rst, data_in, data_out, rd_en, wr_en, rd_add, wr_add,DATA_WRITE_COMPLETE); input CLK_2, rst, clk, rd_en, wr_en; input [7:0]rd_add, wr_add; input [4:0] data_in; output reg [4:0] data_out; parameter WORDSIZE = 5, MEMSIZE = 256 ; reg[WORDSIZE-1:0]RAM[MEMSIZE-1:0]; integer i; output reg [4:0]DATA_WRITE_COMPLETE; always @(posedge clk) begin if(rst) begin DATA_WRITE_COMPLETE =0; for(i=0;i<=255;i=i+1) begin RAM[i]=0; end end else begin if(wr_en==1'b1) begin RAM[wr_add]=data_in; DATA_WRITE_COMPLETE= RAM[wr_add]; end else RAM[wr_add] = RAM[wr_add]; end end always @ (posedge CLK_2) begin if(rst) data_out = 0; else begin if(rd_en==1'b1) begin data_out=RAM[rd_add]; end else data_out=data_out; end end endmodule module RAM256_OP(clk, CLK_2, rst, data_in, data_out, rd_en, wr_en, rd_add, wr_add); input CLK_2, rst, clk, rd_en, wr_en; input [7:0]rd_add, wr_add; input [3:0] data_in; output reg [3:0] data_out; parameter WORDSIZE = 4, MEMSIZE = 256 ; reg[WORDSIZE-1:0]RAM[MEMSIZE-1:0]; integer i; always @(posedge clk) begin if(rst) begin for(i=0;i<=255;i=i+1) begin RAM[i]=0; end end else begin if(wr_en==1'b1) RAM[wr_add]=data_in; else RAM[wr_add]=RAM[wr_add]; end end always @ (posedge CLK_2) begin if (rst) data_out=0; else begin if(rd_en==1'b1) data_out=RAM[rd_add]; else data_out=data_out; end end endmodule module EXECUTE(CLK, RST, DATA_in, PROCESS_COMPLETE, DATA_out, SEQ_in, DSP_in, SEL_in, ALU_in, rd_en, rd_add); input CLK,RST; input [40:0]DATA_in; input [3:0]SEQ_in; input [2:0]SEL_in; input [4:0]PROCESS_COMPLETE; output reg [40:0]DATA_out; output reg [3:0]DSP_in; output reg [2:0]ALU_in; output reg rd_en; output reg [7:0]rd_add; reg [7:0]i; reg [2:0]STATE; reg [4:0]DATA_in_old; always @ (posedge CLK) begin if (RST) begin {i,DATA_out,ALU_in,DSP_in,rd_en,rd_add,DATA_in_old,STATE} = 0; end else begin case (STATE) 3'b000 : begin rd_en = 1'b1; rd_add = i; if(DATA_in_old != DATA_in[4:0]) begin DATA_in_old = DATA_in[4:0]; STATE = 3'b001; end else STATE = 3'b000; end 3'b001 : begin rd_en = 1'b0; DATA_out = DATA_in; ALU_in = SEL_in; DSP_in = SEQ_in; if(PROCESS_COMPLETE == DATA_in_old) begin i=i+8'b00000001; STATE = 3'b010; end else STATE = 3'b001; end 3'b010 : begin rd_en = 1'b1; rd_add=i; if((DATA_in[4:0] != DATA_in_old)&&(DATA_in[4:0] != 5'b0)) begin DATA_in_old=DATA_in[4:0]; STATE = 3'b001; end else STATE = 3'b010; end endcase end end endmodule module ALU(A,B,OP_id,OUT,PROCESS_COMPLETE,SELECT,CLK,RST); input CLK,RST; input [2:0]SELECT; input [15:0]A,B; output reg[31:0]OUT; input [4:0]OP_id; output reg[4:0]PROCESS_COMPLETE; wire [20:0]OUTa,OUTs,OUTd; wire [36:0]OUTm,OUTx; reg [20:0]A_in; reg [15:0]B_in; always @ (posedge CLK) begin if(RST) begin A_in<=0; B_in<=0; PROCESS_COMPLETE<=0; OUT<=0; end else begin A_in<={A,OP_id}; B_in<=B; OUT<=OUTx[36:5]; if(SELECT==0) PROCESS_COMPLETE <= 0; else PROCESS_COMPLETE<=OUTx[4:0]; end end ADDER16 ALUA32(A_in,B_in,OUTa); SUBTRACTOR16 ALUSUB16(A_in,B_in,OUTs); MULTIPLIER16 ALUM16(A_in,B_in,OUTm); DIVIDE16 ALUDIV16(A_in,B_in,OUTd); MUX MUXALU(OUTa,OUTs,OUTd,OUTm,OUTx,SELECT,CLK,RST); endmodule module MULTIPLIER16(A,B,OUT); input [20:0]A; input [15:0]B; wire [31:0]OUTx; output [36:0]OUT; assign OUTx = A[20:5] * B; assign OUT = {OUTx,A[4:0]}; endmodule module ADDER16(A,B,OUT); input [20:0]A; input [15:0]B; wire [15:0]OUTx; output [20:0]OUT; assign OUTx = A[20:5] + B; assign OUT = {OUTx,A[4:0]}; endmodule module SUBTRACTOR16(A,B,OUT); input [20:0]A; input [15:0]B; wire [15:0]OUTx; output [20:0]OUT; assign OUTx = A[20:5] - B; assign OUT = {OUTx,A[4:0]}; endmodule module DIVIDE16(A,B,OUT); input [20:0]A; input [15:0]B; wire [15:0]OUTx; output [20:0]OUT; assign OUTx = A[20:5] / B; assign OUT = {OUTx,A[4:0]}; endmodule module MUX(OUTa,OUTs,OUTd,OUTm,OUT,SELECT,CLK,RST); input CLK,RST; input [2:0]SELECT; input [20:0]OUTa,OUTs,OUTd; input [36:0]OUTm; output reg [36:0]OUT; always @ (posedge CLK) begin if(RST) begin OUT[36:0]<=0; end else begin case (SELECT) 3'b101: begin OUT[20:0]<=OUTa; OUT[36:21]<=0; end 3'b110: begin OUT[20:0]<=OUTs; OUT[36:21]<=0; end 3'b011: begin OUT<=OUTm; end 3'b111: begin OUT[20:0]<=OUTd; OUT[36:21]<=0; end default: OUT<=OUT; endcase end end endmodule module DSP_UNIT(A,B,OUT_M,OUT_S_ID,OP_id,PROCESS_COMPLETE,SELECT,CLK,RST); input [15:0]A,B; input [4:0]OP_id; input CLK,RST; input [3:0]SELECT; output reg[31:0]OUT_M; output reg[15:0]OUT_S_ID; output reg[4:0]PROCESS_COMPLETE; reg [15:0]Am,Bm,As,Ai; wire [15:0]OUT_S,OUT_ID; wire [31:0]OUT_MAC; reg [3:0]STATE; always @ (posedge CLK) begin if(RST) {OUT_M,OUT_S_ID,PROCESS_COMPLETE,Am,Bm,As,Ai,STATE}=0; else begin OUT_M=OUT_MAC; case(STATE) 4'b1100: begin {As,Ai}=0; {Am,Bm}={A,B}; OUT_S_ID=0; PROCESS_COMPLETE = OP_id; STATE=4'b0; end 4'b0010,4'b0011, 4'b0100,4'b0101, 4'b0110,4'b0111: begin {Am,Bm,Ai}=0; As=A; OUT_M=0; OUT_S_ID=OUT_S; PROCESS_COMPLETE = OP_id; STATE=4'b0; end 4'b1010,4'b1011 : begin {Am,Bm,As}=0; Ai=A; OUT_M=0; OUT_S_ID=OUT_ID; PROCESS_COMPLETE = OP_id; STATE=4'b0; end 4'b0000: begin STATE=SELECT; if(SELECT==0) PROCESS_COMPLETE = 0; else PROCESS_COMPLETE = PROCESS_COMPLETE; end default: begin OUT_M=0; OUT_S_ID=0; end endcase end end MAC16 MA(Am, Bm, OUT_MAC, CLK, RST); INT_DEC ID(CLK, RST, Ai, SELECT, B[7:0], OUT_ID); SHIFTER SH(CLK, RST, As, OUT_S, SELECT); endmodule module MAC16(A,B,OUT,CLK,RST); input CLK,RST; input [15:0]A,B; output [31:0]OUT; wire [31:0]OUT1,OUT2; MULTIPLIER16M M16(A,B,OUT1); ADDER32 A32(OUT1,OUT,OUT2); ACCUMULATOR32 AC32(OUT2,OUT,CLK,RST); endmodule module MULTIPLIER16M(A,B,OUT); input [15:0]A,B; output [31:0]OUT; assign OUT = A * B; endmodule module ADDER32(A,B,OUT); input [31:0]A,B; output [31:0]OUT; assign OUT = A + B; endmodule module ACCUMULATOR32(IN,OUT,CLK,RST); input CLK,RST; input [31:0]IN; output reg[31:0]OUT; always @ (posedge CLK) begin if(RST) OUT <= 32'b0; else OUT <= IN; end endmodule module SHIFTER(CLK,RST,DATA_in,A,MODE); input [15:0]DATA_in; input CLK,RST; input [3:0]MODE; output reg [15:0]A; integer i; always @(posedge CLK) begin if(RST) begin {A,i}= 0; end else begin case(MODE) 4'b0010:begin //ARITHMETIC RIGHT SHIFT A=DATA_in; for(i=0;i<15;i=i+1) A[i]=A[i+1]; if(A[14]==1'b1) A[15]=1'b1; else A[15]=1'b0; end 4'b0011:begin //ARITHMETIC LEFT SHIFT A=DATA_in; for(i=15;i>=1;i=i-1) A[i]=A[i-1]; A[0]=1'b0; end 4'b0100:begin //LOGICAL RIGHT SHIFT A=DATA_in; for(i=0;i<15;i=i+1) A[i]=A[i+1]; A[15]=1'b0; end 4'b0101:begin //LOGICAL LEFT SHIFT A=DATA_in; for(i=15;i>=1;i=i-1) A[i]=A[i-1]; A[0]=1'b0; end 4'b0110:begin //BARREL RIGHT SHIFT A=DATA_in; for(i=0;i<15;i=i+1) A[i]=A[i+1]; A[15]=DATA_in[0]; end 4'b0111:begin //BARREL RIGHT SHIFT A=DATA_in; for(i=15;i>=1;i=i-1) A[i]=A[i-1]; A[0]=DATA_in[15]; end default:begin A=0; end endcase end end endmodule module INT_DEC(CLK,RST,DATA_in,MODE,SAMPLE_RATE,DATA_out); input [15:0]DATA_in; input [3:0]MODE; input CLK,RST; input [7:0]SAMPLE_RATE; output reg [15:0] DATA_out; reg [3:0]STATE; reg [7:0]A; reg [15:0]B; always @(posedge CLK) begin if(RST) begin {DATA_out,A,B,STATE} = 0; end else begin case(STATE) 4'b0:begin STATE=MODE; end 4'b1011:begin DATA_out = DATA_in; STATE=4'b0011; A=8'b0; end 4'b0011:begin DATA_out = 0; A=A+8'b00000001; if(A<SAMPLE_RATE) STATE=4'b0011; else STATE=4'b0; end 4'b1010:begin DATA_out = DATA_in; STATE=4'b1111; A=8'b0; B=DATA_in; end 4'b1111:begin DATA_out = B; A=A+8'b00000001; if(A<SAMPLE_RATE) STATE=4'b1111; else STATE=4'b0; end default:begin DATA_out = 0; end endcase end end endmodule module PROGRAM_MEMORY1(CLK,RST,PROM_in,ALU_sel,DSP_sel); input CLK,RST; input [3:0]PROM_in; output reg [3:0]DSP_sel; output reg [2:0]ALU_sel; always @ (posedge CLK) begin if (RST) {ALU_sel,DSP_sel}<=0; else begin case (PROM_in[3:0]) 4'b0000 : begin ALU_sel[2:0]<=3'b101; DSP_sel<=0; end //ADDER 4'b0001 : begin ALU_sel[2:0]<=3'b110; DSP_sel<=0; end //SUBTRACTOR 4'b0010 : begin ALU_sel[2:0]<=3'b011; DSP_sel<=0; end //MULTIPLICATION 4'b0011 : begin ALU_sel[2:0]<=3'b111; DSP_sel<=0; end //DIVIDER 4'b0100 : begin DSP_sel[3:0]<=4'b0010; ALU_sel<=0; end //SHIFTER_AR 4'b0101 : begin DSP_sel[3:0]<=4'b0011; ALU_sel<=0; end //SHIFTER_AL 4'b0110 : begin DSP_sel[3:0]<=4'b0100; ALU_sel<=0; end //SHIFTER_LR 4'b0111 : begin DSP_sel[3:0]<=4'b0101; ALU_sel<=0; end //SHIFTER_LL 4'b1000 : begin DSP_sel[3:0]<=4'b0110; ALU_sel<=0; end //BARREL_SHIFTER_R 4'b1001 : begin DSP_sel[3:0]<=4'b0111; ALU_sel<=0; end //BARREL_SHIFTER_L 4'b1010 : begin DSP_sel[3:0]<=4'b1010; ALU_sel<=0; end //INTERPOLATOR 4'b1011 : begin DSP_sel[3:0]<=4'b1011; ALU_sel<=0; end //DECIMATOR 4'b1100 : begin DSP_sel[3:0]<=4'b1100; ALU_sel<=0; end //MAC default : begin DSP_sel[3:0]<=0; ALU_sel<=0; end endcase end end endmodule