|
- `timescale 1ns/1ps
-
- `define BITS 8
- module sc_decoder_fsm #(parameter BITS=8, N=11'd32)(
- input clk, rst,
- input in_valid,
- input signed [N-1:0][BITS-1:0] y,
- input [N-1:0] f,
- output wire [N-1:0] u_cap,
- output wire [N-1:0] v_final,
- output wire out_valid
- );
-
-
- //function for fminsum calculation
- function void fminsum_calc;
- input signed [`BITS-1:0] a;
- input signed [`BITS-1:0] b;
- output signed [`BITS-1:0] c;
-
- logic [`BITS-2:0] abs_a;
- logic [`BITS-2:0] abs_b;
- logic [`BITS-2:0] abs_c;
-
- abs_a = (a[`BITS-1]) ? ~a[`BITS-2:0] + 1'b1 : a[`BITS-2:0];
- abs_b = (b[`BITS-1]) ? ~b[`BITS-2:0] + 1'b1 : b[`BITS-2:0];
- abs_c = (abs_b < abs_a) ? abs_b : abs_a;
-
- c[`BITS-1] = a[`BITS-1] ^ b[`BITS-1];
- c[`BITS-2:0] = (c[`BITS-1]) ? ~abs_c + 1'b1 : abs_c;
-
- endfunction
-
- //function for g-value calculation
-
- function void g_calc;
- input signed [`BITS-1:0] a;
- input signed [`BITS-1:0] b;
- input u;
- output signed [`BITS:0] c;
-
- c = (u == 0) ? (b + a) : (b + (~a+1'b1));
-
- endfunction
-
- // Parameter
- localparam d = $clog2(N);
-
- // Internal Signals
- logic [N-1:0][BITS-1:0] L_in, L_out;
- logic [d :0] temp_index_f,temp_index_g;
- logic [N-1:0] v_in, v_out;
- logic [11 :0] jL1,jL2,
- jU1,jU2,
- jR1,jR2,jR3;
- logic ena_v,enb_v,wea_v;
- logic ena_L,enb_L,wea_L;
- logic [N-1:0]u;
- reg signed [BITS-1:0] LRU[2];
- reg [N-1:0]v;
-
- // State Variables
- logic [4:0] c_state, n_state;
-
- //Auxiliary registers declarations
- logic [d:0] depth,depth_reg;
- logic [d:0] node,node_reg;
- logic [11:0] tmp_L, tmp_L_reg,
- tmp_R, tmp_R_reg,
- tmp_U, tmp_U_reg;
-
- //FSM States
- localparam idle = 5'd0 , root = 5'd1 , wait_L_logic = 5'd2,
- wait_L = 5'd3 , state_L = 5'd4 , wait_R_logic = 5'd5,
- wait_R = 5'd6 , state_R = 5'd7 , wait_U_logic = 5'd8,
- wait_U = 5'd9 , state_U = 5'd10, wait_LRU_logic = 5'd11,
- wait_LRU = 5'd12, state_LRU = 5'd13, wait_lnode_logic = 5'd14,
- wait_lnode = 5'd15, state_lnode = 5'd16, wait_lstate_logic = 5'd17,
- wait_lstate = 5'd18, state_last = 5'd19;
-
- //BlockRAM Instantiations
- bram_v #( .ADDR_WIDTH(d-1),
- .DATA_WIDTH(N),
- .DEPTH(2**(d-1)))
- bram_v_i (
- .clk(clk),.ena(ena_v),.enb(enb_v),
- .addra(depth_reg-1'b1),
- .addrb(depth_reg),
- .wea(wea_v),
- .dia(v_in),
- .dob(v_out));
-
- bram_L #( .ADDR_WIDTH(d-1),
- .DATA_WIDTH(N*BITS),
- .DEPTH(2**(d-1)),
- .N(N))
- bram_L_i (
- .clk(clk),.ena(ena_L),.enb(enb_L),
- .addra(depth_reg),
- .addrb(depth_reg-1'b1),
- .wea(wea_L),
- .dia(L_in),
- .dob(L_out));
-
- //output assignment
- for(genvar i=0; i<N; i++)
- assign u_cap[i] = u[i];
-
-
- assign v_final = v;
- assign out_valid = (n_state == state_lnode) ? 1'b1 : 1'b0;
-
-
- // Sequential Logic - FSM State and Data Registers
- always_ff@(posedge clk)
- begin
- if(rst)
- begin
- c_state <= idle;
- depth_reg <= 0;
- node_reg <= 0;
- tmp_L_reg <= 0;
- tmp_R_reg <= 0;
- tmp_U_reg <= 0;
- end
- else
- begin
- c_state <= n_state;
- depth_reg <= depth;
- node_reg <= node;
- tmp_L_reg <= tmp_L;
- tmp_R_reg <= tmp_R;
- tmp_U_reg <= tmp_U;
- end
- end
-
- //Combinational Logic - FSM Next State Logic
- always_comb
- begin
- u = 0;
- v = 0;
- // depth = 0;
- if(in_valid)
- case(c_state)
- idle:
- begin
- depth = 0; node = 0;
- tmp_L = 0; tmp_R = 0; tmp_U = 0;
- ena_L = 0; wea_L = 0; enb_L = 0;
- ena_v = 0; wea_v = 0; enb_v = 0;
- u = 0; v = 0;
- if(out_valid)
- n_state = idle;
- else
- n_state = root;
- end
-
- root:
- begin
- depth = depth_reg;
- node = node_reg;
- ena_L = 1'b1; wea_L = 1'b1;
- enb_L = 0; ena_v = 0;
- wea_v = 0; enb_v = 0;
-
- u = u;
- v = v;
- for(int k = 0; k < N; k++)
- L_in[k] = y[k];
-
- n_state = wait_L_logic;
- end
-
- wait_L_logic:
- begin
- depth = depth_reg + 1'b1; node = ((2*node_reg) + 1'b1);
- ena_L = 0; wea_L = 0;
- tmp_L = 0; enb_L = 1'b1;
- ena_v = 0; wea_v = 0;
- enb_v = 0;
-
- u = u;
- v = v;
- if(depth < d)
- n_state = wait_L;
- else
- n_state = wait_LRU_logic;
- end
-
- wait_L:
- begin
- u = u;
- // depth = depth_reg;
- n_state = state_L;
- end
-
- state_L:
- begin
- u = u;
- v = v;
- // depth = depth_reg;
- ena_L = 1'b1; wea_L = 1'b1; enb_L = 0;
- ena_v = 0; wea_v = 0; enb_v = 0;
-
- tmp_L = tmp_L_reg + 1'b1;
-
- temp_index_f = ((N/(2**(depth+1'b1))) * ((2*(node) + 1'b1) - ((2**(depth + 1'b1)) - 1'b1)));
-
- jL1 = (tmp_L_reg) + temp_index_f;
- jL2 = (tmp_L_reg) + temp_index_f + (N/(2**depth));
-
- fminsum_calc(L_out[jL1],L_out[jL2],L_in[jL1]);
-
- if(tmp_L< (N/(2**depth)))
- n_state = state_L;
- else if(depth < d)
- n_state = wait_L_logic;
- else
- n_state = wait_LRU_logic;
- end
-
- wait_R_logic:
- begin
- u = u;
- v = v;
- depth = depth_reg - 1'b1;
- node = node_reg + 1'b1;
- tmp_R = 0;
- n_state = wait_R;
- end
-
- wait_R:
- begin
- // depth = depth_reg;
- ena_L = 0;wea_L = 0; enb_L = 1'b1;
- ena_v = 0;wea_v = 0; enb_v = 1'b1;
- u = u;
- v = v;
- n_state = state_R;
- end
-
- state_R:
- begin
- // depth = depth_reg;
- u = u;
- v = v;
- ena_L = 1'b1; wea_L = 1'b1; enb_L = 0;
- ena_v = 0; wea_v = 0; enb_v = 0;
-
- tmp_R = tmp_R_reg + 1'b1;
- temp_index_f = ((N/(2**(depth + 1'b1))) * ((2*(node) + 1'b1) -((2**(depth + 1'b1)) - 1'b1)));
- temp_index_g = ((N/(2**(depth + 1'b1))) * ((2*(node - 1'b1) + 1'b1)-((2**(depth + 1'b1)) - 1'b1)));
-
- jR1 = (tmp_R_reg) + temp_index_g;
- jR2 = (tmp_R_reg) + temp_index_g + (N/(2**depth));
- jR3 = (tmp_R_reg) + temp_index_f;
-
- g_calc(L_out[jR1],L_out[jR2],v_out[jR1],L_in[jR3]);
-
- if(tmp_R < (N/(2**depth)))
- n_state = state_R;
- else if(node == ((2**d) - 2))
- n_state = wait_lnode_logic;
- else if(depth == d)
- n_state = wait_LRU_logic;
- else
- n_state = wait_L_logic;
- end
-
- wait_U_logic:
- begin
- depth = depth_reg - 1'b1;
- node = (node_reg - 2) >> 1;
- tmp_U = 0;
- u = u;
- v = v;
- n_state = wait_U;
- end
-
- wait_U:
- begin
- // depth = depth_reg;
- ena_L = 0; wea_L = 0; enb_L = 0;
- ena_v = 0; wea_v = 0; enb_v = 1'b1;
-
- n_state = state_U;
- end
-
- state_U:
- begin
- // depth = depth_reg;
- ena_L = 0; ena_v =1'b1; enb_L = 0;
- wea_L = 0; wea_v =1'b1; enb_v = 0;
- u = u;
- v = v;
- tmp_U = tmp_U_reg+1'b1;
- temp_index_f = ((N/(2**(depth))) * ((2*node + 1'b1) - ((2**(depth)) - 1'b1)));
-
- jU1 = (tmp_U_reg) + temp_index_f;
- jU2 = (tmp_U_reg) + temp_index_f + (N/(2**(depth)));
-
- v_in[jU1] = v_out[jU1] ^ v_out[jU2];
- v_in[jU2] = v_out[jU2];
-
- if(tmp_U < (N/(2**(depth))))
- n_state = state_U;
- else if(depth > 0 && ~node[0])
- n_state = wait_U_logic;
- else if(depth > 0 && node!=0)
- n_state = wait_R_logic;
- else
- n_state = wait_lstate_logic;
- end
-
- wait_LRU_logic:
- begin
- u = u;
- v = v;
- // depth = depth_reg;
- node = (node_reg - 1'b1) >> 1;
-
- n_state = wait_LRU;
- end
-
- wait_LRU:
- begin
- // depth = depth_reg;
- u = u;
- v = v;
- ena_L = 0; wea_L = 0; enb_L = 1'b1;
- ena_v = 0; wea_v = 0; enb_v = 0;
-
- n_state = state_LRU;
- end
-
- state_LRU:
- begin
- // depth = depth_reg;
- ena_L = 0; ena_v = 1'b1;
- enb_v = 0; wea_v = 1'b1;
- wea_L = 0; enb_L = 0;
- v = v;
- temp_index_f = ((N/(2**(depth))) * ((2*node + 1'b1) - ((2**(depth)) - 1'b1)));
-
- fminsum_calc(L_out[temp_index_f],L_out[temp_index_f + 1],LRU[0]);
-
- u[(2*node)+2-N] = (f[(2*node)+2-N]) ? 0 : ((LRU[0][BITS-1]) ? 1 : 0);
-
- g_calc(L_out[temp_index_f],L_out[temp_index_f+1],u[(2*node)+2-N],LRU[1]);
-
- u[(2*node)+3-N] = (f[(2*node)+3-N]) ? 0 : ((LRU[1][BITS-1]) ? 1 : 0);
-
- v_in[temp_index_f] = u[(2*node)+2-N] ^ u[(2*node)+3-N];
- v_in[temp_index_f+1] = u[(2*node)+3-N];
-
- if(node[0])
- n_state = wait_R_logic;
- else
- n_state = wait_U_logic;
- end
-
- wait_lnode_logic:
- begin
- u = u;
- v = v;
- depth = depth_reg + 1'b1; node = node_reg;
-
- n_state = wait_lnode;
- end
-
- wait_lnode:
- begin
- // depth = depth_reg;
- u = u;
- v = v;
- ena_L = 0; wea_L = 0; enb_L = 1'b1;
- ena_v = 0; wea_v = 0; enb_v = 0;
-
- n_state = state_lnode;
- end
-
- state_lnode:
- begin
- // depth = depth_reg;
- u = u;
- v = v;
- ena_L = 0; wea_L = 0; enb_L = 0;
- ena_v = 1'b1; wea_v = 1'b1; enb_v = 0;
-
- temp_index_f = ((N/(2**(depth))) * ((2*node + 1'b1) - ((2**(depth)) - 1'b1)));
-
- fminsum_calc(L_out[temp_index_f],L_out[temp_index_f+1],LRU[0]);
-
- u[(2*node)+2-N] = (f[(2*node)+2-N]) ? 0 : ((LRU[0][BITS-1]) ? 1'b1 : 0);
-
- g_calc(L_out[temp_index_f],L_out[temp_index_f+1],u[(2*node)+2-N],LRU[1]);
-
- u[(2*node)+3-N] = (f[(2*node)+3-N]) ? 0 : ((LRU[1][BITS-1]) ? 1'b1 : 0);
-
- v_in[temp_index_f] = u[(2*node)+2-N] ^ u[(2*node)+3-N];
- v_in[temp_index_f+1] = u[(2*node)+3-N];
-
- n_state = wait_U_logic;
- end
-
- wait_lstate_logic:
- begin
- u = u;
- v = v;
- // depth = depth_reg;
- node = node_reg;
-
- n_state = wait_lstate;
- end
-
- wait_lstate:
- begin
- // depth = depth_reg;
- u = u;
- v = v;
- ena_L = 0; wea_L = 0; enb_L = 1'b1;
- ena_v = 0; wea_v = 0; enb_v = 0;
-
- n_state = state_last;
- end
-
- state_last:
- begin
- // depth = depth_reg;
- u = u;
- ena_L = 0; wea_L = 0; enb_L = 0;
- ena_v = 1'b1; wea_v = 1'b1; enb_v = 0;
-
- v = v_out;
-
- n_state = idle;
- end
- default:
- begin
- u = 0;
- v = 0;
- depth = 0; node = 0;
- tmp_L = 0; tmp_R = 0; tmp_U = 0;
- ena_L = 0; wea_L = 0; enb_L = 0;
- ena_v = 0; wea_v = 0; enb_v = 0;
-
- n_state = idle;
- end
- endcase
- else
- begin
- u = 0;
- v = 0;
- depth = 0; node = 0;
- tmp_L = 0; tmp_R = 0; tmp_U = 0;
- ena_L = 0; wea_L = 0; enb_L = 0;
- ena_v = 0; wea_v = 0; enb_v = 0;
- n_state = idle;
- end
- end
- endmodule
|