blob: e03a76c6deb83814f6acc9cc2542e00ae9043201 [file] [log] [blame]
`timescale 1ns / 1ps
module turbo_enc_agu (
//inputs
i_clk,
i_rstn,
i_block_size,
i_mode,
i_ea,
i_p0,
i_q0,
i_q1,
i_q2,
i_q3,
i_start,
i_ib_data_ab,
//outputs
o_ib_adx_ab,
o_siso_data_ab,
o_siso_buf_wr,
o_read_done
);
parameter MAX_BLOCK_WIDTH = 10,
P_WIDTH = 10,
MAX_DATA_WIDTH = MAX_BLOCK_WIDTH + 2;
input i_clk;
input i_rstn;
input[MAX_BLOCK_WIDTH-1:0] i_block_size;
input i_mode;
input[MAX_DATA_WIDTH-1:0] i_ea;
input[P_WIDTH-1:0] i_p0;
input[MAX_DATA_WIDTH-1:0] i_q0;
input[MAX_DATA_WIDTH-1:0] i_q1;
input[MAX_DATA_WIDTH-1:0] i_q2;
input[MAX_DATA_WIDTH-1:0] i_q3;
input i_start;
input[1:0] i_ib_data_ab;
output[MAX_DATA_WIDTH-1:0] o_ib_adx_ab;
output[1:0] o_siso_data_ab;
output reg o_siso_buf_wr;
output o_read_done;
reg addr_state; // state machine for addr_states
parameter wait_start = 0, addr_generate = 1;
reg mode;
reg[MAX_DATA_WIDTH-1:0] lin_adx;
reg[MAX_DATA_WIDTH-1:0] lin_adx_d;
reg[MAX_DATA_WIDTH-1:0] pi_d;
reg[MAX_DATA_WIDTH-1:0] lambda_d;
reg toggle_d;
reg valid;
reg valid_d;
reg read_done;
reg read_done_d;
wire[MAX_DATA_WIDTH-1:0] n;
wire[MAX_DATA_WIDTH-1:0] q0_d;
wire[MAX_DATA_WIDTH-1:0] q1_d;
wire[MAX_DATA_WIDTH-1:0] q2_d;
wire[MAX_DATA_WIDTH-1:0] q3_d;
reg[MAX_DATA_WIDTH-1:0] q_mux;
wire[MAX_DATA_WIDTH-1:0] lambda;
wire[MAX_DATA_WIDTH-1:0] pi;
wire[(MAX_DATA_WIDTH+1)-1:0] lambda_mod_1;
wire signed[(MAX_DATA_WIDTH+1)-1:0] lambda_mod_2;
wire[(MAX_DATA_WIDTH+1)-1:0] pi_mod_1;
wire signed[(MAX_DATA_WIDTH+1)-1:0] pi_mod_2;
wire siso_buf_wr;
assign q0_d = i_q0;
assign q1_d = i_q1;
assign q2_d = i_q2;
assign q3_d = i_q3;
always @(posedge i_clk) //address_generation_process
begin
if(i_rstn == 0) begin
addr_state <= wait_start;
mode <= 0;
lin_adx <= 0;
lin_adx_d <= 0;
lambda_d <= 0;
pi_d <= 0;
valid <= 0;
read_done <= 0;
end
else begin
case(addr_state)
wait_start:
begin
valid <= 0;
read_done <= 0;
if (i_start == 1) begin
mode <= i_mode;
lin_adx <= 0;
lambda_d <= 0;
addr_state <= addr_generate;
end
end
addr_generate:
begin
valid <= 1;
lin_adx <= lin_adx + 1;
lin_adx_d <= lin_adx;
lambda_d <= lambda;
pi_d <= pi;
if (lin_adx == i_ea) begin
read_done <= 1;
addr_state <= wait_start;
end
end
endcase
end
end
assign siso_buf_wr = valid_d;
always @(posedge i_clk) // siso_buffer_write_process
begin
if (i_rstn == 0) begin
valid_d <= 0;
toggle_d <= 0;
read_done_d <= 0;
end
else begin
valid_d <= valid;
if (mode == 1)begin
toggle_d <= ~pi_d[0];
end
else begin
toggle_d <= 0;
end
read_done_d <= read_done;
end
end
assign n = {i_block_size,2'b00};
// ACC Unit 1
assign lambda_mod_1 = {1'b0,lambda_d} + i_p0;
assign lambda_mod_2 = lambda_mod_1 - {1'b0,n};
assign lambda = (lambda_mod_2[MAX_DATA_WIDTH]) ? lambda_mod_1[MAX_DATA_WIDTH-1:0] : lambda_mod_2[MAX_DATA_WIDTH-1:0];
// ACC Unit 2
always@(*)
begin
case (lin_adx[1:0])
1: q_mux = q1_d;
2: q_mux = q2_d;
3: q_mux = q3_d;
default: q_mux = q0_d;
endcase
end
assign pi_mod_1 = {1'b0,lambda_d} + {1'b0,q_mux};
assign pi_mod_2 = pi_mod_1 - {1'b0,n};
assign pi = (pi_mod_2[MAX_DATA_WIDTH]) ? pi_mod_1[MAX_DATA_WIDTH-1:0] : pi_mod_2[MAX_DATA_WIDTH-1:0];
// read data from input buffer
assign o_ib_adx_ab = (mode) ? pi_d : lin_adx_d;
// send data to encoder
assign o_siso_data_ab = (toggle_d) ? {i_ib_data_ab[0],i_ib_data_ab[1]} : i_ib_data_ab;
always @(posedge i_clk)
begin
if (i_rstn == 0)
o_siso_buf_wr <= 0;
else
o_siso_buf_wr <= siso_buf_wr;
end
// Send feedback to controller
assign o_read_done = read_done_d;
endmodule