@@ -0,0 +1,234 @@ | |||||
`timescale 1 ns / 1 ps | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
// Company: BITSILICA PRIVATE LIMITED | |||||
// Design Name: AXI4_STREAM_MASTER_INTERFACE | |||||
// Module Name: DOUT_M_AXIS | |||||
// Project Name: POLAR ENCODER-DECODER | |||||
// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) | |||||
// Tool Versions: VIVADO 2020.1 | |||||
// Description: AXI4 Stream Master Interface is used to stream out output data from | |||||
// the polar Encoder. | |||||
// | |||||
//////////////////////////////////////////////////////////////////////////////////// | |||||
module DOUT_M_AXIS # | |||||
( | |||||
// Width of S_AXIS address bus. The slave accepts the read and write addresses of width C_M_AXIS_TDATA_WIDTH. | |||||
parameter integer C_M_AXIS_TDATA_WIDTH = 32, | |||||
parameter integer C_S_AXIS_TDATA_WIDTH = 512, | |||||
parameter integer DEPTH = 16, | |||||
// Start count is the numeber of clock cycles the master will wait before initiating/issuing any transaction. | |||||
parameter integer C_M_START_COUNT = 2 | |||||
) | |||||
( | |||||
// Global ports | |||||
input logic M_AXIS_ACLK, | |||||
// | |||||
input logic M_AXIS_ARESETN, | |||||
// Master Stream Ports. TVALID indicates that the master is driving a valid transfer, A transfer takes place when both TVALID and TREADY are asserted. | |||||
output logic M_AXIS_TVALID, | |||||
// TDATA is the primary payload that is used to provide the data that is passing across the interface from the master. | |||||
output logic [C_M_AXIS_TDATA_WIDTH-1 : 0] M_AXIS_TDATA, | |||||
// TLAST indicates the boundary of a packet. | |||||
output logic M_AXIS_TLAST, | |||||
// TREADY indicates that the slave can accept a transfer in the current cycle. | |||||
input logic M_AXIS_TREADY, | |||||
// Input from PBCH Encoder Core of Width 864 bits | |||||
input logic [C_S_AXIS_TDATA_WIDTH-1:0]S_AXIS_TDATA, | |||||
// Input from PBCH Encoder Core | |||||
input logic DONE | |||||
); | |||||
//Total number of output data. | |||||
// Total number of output data | |||||
localparam NUMBER_OF_OUTPUT_WORDS = 27; | |||||
// function called clogb2 that returns an integer which has the | |||||
// value of the ceiling of the log base 2. | |||||
function integer clogb2 (input integer bit_depth); | |||||
begin | |||||
for(clogb2=0; bit_depth>0; clogb2=clogb2+1) | |||||
bit_depth = bit_depth >> 1; | |||||
end | |||||
endfunction | |||||
// WAIT_COUNT_BITS is the width of the wait counter. | |||||
localparam integer WAIT_COUNT_BITS = clogb2(C_M_START_COUNT-1); | |||||
// bit_num gives the minimum number of bits needed to address 'depth' size of FIFO. | |||||
localparam bit_num = clogb2(NUMBER_OF_OUTPUT_WORDS); | |||||
// Define the states of state machine | |||||
// The control state machine oversees the writing of input streaming data to the FIFO, | |||||
// and outputs the streaming data from the FIFO | |||||
parameter [1:0] IDLE = 2'b00, // This is the initial/idle state | |||||
INIT_COUNTER = 2'b01, // This state initializes the counter, ones | |||||
// the counter reaches C_M_START_COUNT count, | |||||
// the state machine changes state to INIT_WRITE | |||||
SEND_STREAM = 2'b10; // In this state the | |||||
// stream data is output through M_AXIS_TDATA | |||||
// State variable | |||||
logic [1:0] mst_exec_state; | |||||
// FIFO read pointer | |||||
logic [bit_num-1:0] read_pointer; | |||||
// AXI Stream internal signals | |||||
//wait counter. The master waits for the user defined number of clock cycles before initiating a transfer. | |||||
logic [WAIT_COUNT_BITS-1 : 0] count; | |||||
//streaming data valid | |||||
logic axis_tvalid; | |||||
//streaming data valid delayed by one clock cycle | |||||
logic axis_tvalid_delay; | |||||
//Last of the streaming data | |||||
logic axis_tlast; | |||||
//Last of the streaming data delayed by one clock cycle | |||||
logic axis_tlast_delay; | |||||
//FIFO implementation signals | |||||
logic [C_M_AXIS_TDATA_WIDTH-1 : 0] stream_data_out; | |||||
logic tx_en; | |||||
//The master has issued all the streaming data stored in FIFO | |||||
logic tx_done; | |||||
(* ram_style="register" *) | |||||
logic [C_M_AXIS_TDATA_WIDTH-1:0] slv_reg0 [0:DEPTH-1]; | |||||
// I/O Connections assignments | |||||
assign M_AXIS_TVALID = axis_tvalid_delay; | |||||
assign M_AXIS_TDATA = stream_data_out; | |||||
assign M_AXIS_TLAST = axis_tlast_delay; | |||||
integer i; | |||||
integer byte_index; | |||||
always_ff @( posedge M_AXIS_ACLK ) | |||||
begin | |||||
if (!M_AXIS_ARESETN ) | |||||
begin | |||||
stream_data_out <= 0; | |||||
for(i = 0; i <= DEPTH - 1 ; i = i+1) | |||||
slv_reg0[i] <= 0; | |||||
end | |||||
else | |||||
begin | |||||
if (DONE) | |||||
for ( byte_index = 0; byte_index <= DEPTH - 1; byte_index = byte_index+1 ) | |||||
slv_reg0[byte_index] <= S_AXIS_TDATA[(byte_index*C_M_AXIS_TDATA_WIDTH) +: C_M_AXIS_TDATA_WIDTH]; | |||||
else if (tx_en) | |||||
begin | |||||
stream_data_out <= slv_reg0[read_pointer]; | |||||
end | |||||
end | |||||
end | |||||
// Control state machine implementation | |||||
always_ff @(posedge M_AXIS_ACLK) | |||||
begin | |||||
// Synchronous reset (active low) | |||||
if (!M_AXIS_ARESETN) | |||||
begin | |||||
mst_exec_state <= IDLE; | |||||
count <= 0; | |||||
end | |||||
else | |||||
case (mst_exec_state) | |||||
IDLE: | |||||
// The slave starts accepting tdata when | |||||
// there tvalid is asserted to mark the | |||||
// presence of valid streaming data | |||||
mst_exec_state <= INIT_COUNTER; | |||||
INIT_COUNTER: | |||||
// The slave starts accepting tdata when | |||||
// there tvalid is asserted to mark the | |||||
// presence of valid streaming data | |||||
if ( count == C_M_START_COUNT - 1 ) | |||||
begin | |||||
mst_exec_state <= SEND_STREAM; | |||||
end | |||||
else | |||||
begin | |||||
count <= count + 1; | |||||
mst_exec_state <= INIT_COUNTER; | |||||
end | |||||
SEND_STREAM: | |||||
// The example design streaming master functionality starts | |||||
// when the master drives output tdata from the FIFO and the slave | |||||
// has finished storing the S_AXIS_TDATA | |||||
if (tx_done) | |||||
begin | |||||
mst_exec_state <= IDLE; | |||||
end | |||||
else | |||||
begin | |||||
mst_exec_state <= SEND_STREAM; | |||||
end | |||||
endcase | |||||
end | |||||
//tvalid generation | |||||
//axis_tvalid is asserted when the control state machine's state is SEND_STREAM and | |||||
//number of output streaming data is less than the NUMBER_OF_OUTPUT_WORDS. | |||||
assign axis_tvalid = ((mst_exec_state == SEND_STREAM) && (read_pointer < NUMBER_OF_OUTPUT_WORDS)); | |||||
// AXI tlast generation | |||||
// axis_tlast is asserted number of output streaming data is NUMBER_OF_OUTPUT_WORDS-1 | |||||
// (0 to NUMBER_OF_OUTPUT_WORDS-1) | |||||
assign axis_tlast = (read_pointer == NUMBER_OF_OUTPUT_WORDS-1); | |||||
// Delay the axis_tvalid and axis_tlast signal by one clock cycle | |||||
// to match the latency of M_AXIS_TDATA | |||||
always_ff @(posedge M_AXIS_ACLK) | |||||
begin | |||||
if (!M_AXIS_ARESETN) | |||||
begin | |||||
axis_tvalid_delay <= 1'b0; | |||||
axis_tlast_delay <= 1'b0; | |||||
end | |||||
else | |||||
begin | |||||
axis_tvalid_delay <= axis_tvalid; | |||||
axis_tlast_delay <= axis_tlast; | |||||
end | |||||
end | |||||
//read_pointer pointer | |||||
always_ff@(posedge M_AXIS_ACLK) | |||||
begin | |||||
if(!M_AXIS_ARESETN) | |||||
begin | |||||
read_pointer <= 0; | |||||
tx_done <= 1'b0; | |||||
end | |||||
else | |||||
if (read_pointer <= NUMBER_OF_OUTPUT_WORDS-1) | |||||
begin | |||||
if (tx_en) | |||||
// read pointer is incremented after every read from the FIFO | |||||
// when FIFO read signal is enabled. | |||||
begin | |||||
read_pointer <= read_pointer + 1; | |||||
tx_done <= 1'b0; | |||||
end | |||||
end | |||||
else if (read_pointer == NUMBER_OF_OUTPUT_WORDS) | |||||
begin | |||||
// tx_done is asserted when NUMBER_OF_OUTPUT_WORDS numbers of streaming data | |||||
// has been out. | |||||
tx_done <= 1'b1; | |||||
if(DONE)read_pointer <= 0; | |||||
end | |||||
end | |||||
//FIFO read enable generation | |||||
assign tx_en = M_AXIS_TREADY && axis_tvalid; | |||||
endmodule |
@@ -0,0 +1,159 @@ | |||||
`timescale 1 ns / 1 ps | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
// Company: BITSILICA PRIVATE LIMITED | |||||
// Design Name: AXI4_STREAM_SLAVE_INTERFACE | |||||
// Module Name: S_AXIS | |||||
// Project Name: POLAR ENCODER-DECODER | |||||
// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) | |||||
// Tool Versions: VIVADO 2020.1 | |||||
// Description: AXI4 Stream Slave Interface is used to stream input data to the | |||||
// polar Encoder. | |||||
// | |||||
//////////////////////////////////////////////////////////////////////////////////// | |||||
module S_AXIS # | |||||
( // AXI4Stream sink: Data Width | |||||
parameter integer C_S_AXIS_TDATA_WIDTH = 32 | |||||
) | |||||
( // AXI4Stream sink: Clock | |||||
input wire S_AXIS_ACLK, | |||||
// AXI4Stream sink: Reset | |||||
input wire S_AXIS_ARESETN, | |||||
// Ready to accept data in | |||||
output wire S_AXIS_TREADY, | |||||
// Data out | |||||
output [C_S_AXIS_TDATA_WIDTH-1 : 0] M_AXIS_TDATA, | |||||
// Data in | |||||
input wire [C_S_AXIS_TDATA_WIDTH-1 : 0] S_AXIS_TDATA, | |||||
// Indicates boundary of last packet | |||||
input wire S_AXIS_TLAST, | |||||
// Data is in valid | |||||
input wire S_AXIS_TVALID, | |||||
input wire tready_in, | |||||
output logic read_en | |||||
); | |||||
// function called clogb2 that returns an integer which has the | |||||
// value of the ceiling of the log base 2. | |||||
function integer clogb2 (input integer bit_depth); | |||||
begin | |||||
for(clogb2=0; bit_depth>0; clogb2=clogb2+1) | |||||
bit_depth = bit_depth >> 1; | |||||
end | |||||
endfunction | |||||
// Total number of input data. | |||||
localparam NUMBER_OF_INPUT_WORDS = 8; | |||||
localparam NUMBER_OF_OUTPUT_WORDS = 8; | |||||
// bit_num gives the minimum number of bits needed to address 'NUMBER_OF_INPUT_WORDS' size of FIFO. | |||||
localparam bit_num = clogb2(NUMBER_OF_INPUT_WORDS-1); | |||||
localparam aw = clogb2(C_S_AXIS_TDATA_WIDTH); | |||||
// The control state machine oversees the writing of input streaming data to the FIFO, | |||||
// and outputs the streaming data from the FIFO | |||||
localparam [1:0] IDLE = 2'b00, // This is the initial/idle state | |||||
WRITE_FIFO = 2'b01, // In this state FIFO is written with the | |||||
// input stream data S_AXIS_TDATA | |||||
FIRST_READ = 2'b10, // Read first from FIFO as soon as it writes | |||||
READ_FIFO = 2'b11; // Read State | |||||
logic axis_tready; | |||||
logic [1:0] mst_exec_state; // State variable | |||||
logic fifo_wren; // FIFO write enable | |||||
logic fifo_full_flag; // FIFO full flag | |||||
logic fifo_empty; // FIFO Empty | |||||
logic full_n; // FIFO is being written | |||||
logic first_read_en; // First Read Enable | |||||
logic [5:0] count; | |||||
logic tx_en; | |||||
// I/O Connections assignments | |||||
assign read_en = (tready_in || first_read_en); | |||||
assign S_AXIS_TREADY = axis_tready; | |||||
// Control state machine implementation | |||||
always @(posedge S_AXIS_ACLK) | |||||
begin | |||||
if (!S_AXIS_ARESETN) | |||||
// Synchronous reset (active low) | |||||
begin | |||||
mst_exec_state <= IDLE; | |||||
first_read_en <= 0; | |||||
end | |||||
else | |||||
case (mst_exec_state) | |||||
IDLE: begin | |||||
// The sink starts accepting tdata when | |||||
// there tvalid is asserted to mark the | |||||
// presence of valid streaming data | |||||
first_read_en <= 0; | |||||
if (S_AXIS_TVALID) | |||||
begin | |||||
mst_exec_state <= WRITE_FIFO; | |||||
end | |||||
else | |||||
begin | |||||
mst_exec_state <= IDLE; | |||||
end | |||||
end | |||||
WRITE_FIFO: begin | |||||
// When the sink has accepted all the streaming input data, | |||||
// the interface swiches functionality to a streaming master | |||||
// if (writes_done) | |||||
first_read_en <= 0; | |||||
if(full_n && count == 1) | |||||
mst_exec_state <= FIRST_READ; | |||||
else if (fifo_full_flag) | |||||
begin | |||||
mst_exec_state <= READ_FIFO; | |||||
end | |||||
else | |||||
begin | |||||
// The sink accepts and stores tdata | |||||
// into FIFO | |||||
mst_exec_state <= WRITE_FIFO; | |||||
end | |||||
end | |||||
FIRST_READ: begin | |||||
first_read_en <= 1'b1; | |||||
if(!fifo_full_flag) | |||||
mst_exec_state <= WRITE_FIFO; | |||||
else | |||||
mst_exec_state <= READ_FIFO; | |||||
end | |||||
READ_FIFO : begin | |||||
first_read_en <= 0; | |||||
if(fifo_empty) | |||||
mst_exec_state <= IDLE; | |||||
else if(!fifo_full_flag) | |||||
mst_exec_state <= WRITE_FIFO; | |||||
else | |||||
mst_exec_state <= READ_FIFO; | |||||
end | |||||
endcase | |||||
end | |||||
// AXI Streaming Sink | |||||
// | |||||
// design sink is always ready to accept the S_AXIS_TDATA until | |||||
// the FIFO is not filled with NUMBER_OF_INPUT_WORDS number of input words. | |||||
assign axis_tready = ((mst_exec_state == WRITE_FIFO) || (mst_exec_state == READ_FIFO)) && !fifo_full_flag && !S_AXIS_TLAST; | |||||
// FIFO write enable generation | |||||
assign fifo_wren = S_AXIS_TVALID && axis_tready && !fifo_full_flag && !S_AXIS_TLAST; | |||||
fifo #(.dw(C_S_AXIS_TDATA_WIDTH),.aw(aw-1),.n(C_S_AXIS_TDATA_WIDTH))FIFO(.clk(S_AXIS_ACLK),.rst(S_AXIS_ARESETN),.din(S_AXIS_TDATA),.we(fifo_wren),.dout(M_AXIS_TDATA),.re(read_en), | |||||
.full(),.empty(),.full_r(fifo_full_flag),.empty_r(fifo_empty),.full_n(full_n), .empty_n(), .full_n_r(), .empty_n_r(),.level(),.count(count)); | |||||
//FIFO read enable generation | |||||
assign tx_en = axis_tready && S_AXIS_TVALID && tready_in; | |||||
endmodule |
@@ -0,0 +1,10 @@ | |||||
// For PBCH A = 32 | |||||
// For PBCH G = 864 | |||||
`define A 32 | |||||
`define G 864 | |||||
`define PBCH 1 |
@@ -0,0 +1,105 @@ | |||||
`timescale 1ns / 1ps | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
// Company: BITSILICA PVT LTD | |||||
// Design Name:PBCH_POLAR_ENCODER_IP | |||||
// Module Name: PBCH_POLAR_ENCODER_IP | |||||
// Project Name: POLAR IP | |||||
// Description: The PBCH_POLAR_ENCODER IP is interfaced with AXI4 Stream DIN | |||||
// Slave and DOUT Master interfaces. | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
`include "PBCH_Defines.vh" | |||||
`define Dx_WIDTH 32 // Dx_WIDTH => DIN_WIDTH / DOUT_WIDTH => AXI4-Stream Interface | |||||
`define PDCCH 0 | |||||
module PBCH_POLAR_ENCODER_IP( | |||||
/**************************************************************/ | |||||
// Global Signals | |||||
input logic reset_n, // Active Low Reset | |||||
input logic core_clk, // Core Clock | |||||
/**************************************************************/ | |||||
// AXI4 DIN Stream Interface | |||||
input logic [`Dx_WIDTH - 1 : 0] s_axis_din_tdata, | |||||
input logic s_axis_din_tvalid, | |||||
input logic s_axis_din_tlast, | |||||
output logic DIN_TREADY, | |||||
/**************************************************************/ | |||||
// AXI4 DOUT Stream Interface | |||||
input logic s_axis_dout_tready, | |||||
output logic [`Dx_WIDTH - 1 : 0] DOUT_TDATA, | |||||
output logic DOUT_TVALID, | |||||
output logic DOUT_TLAST | |||||
); | |||||
logic [`Dx_WIDTH - 1 : 0] m_axis_din_tdata; | |||||
logic [`G - 1 : 0] msg_o; | |||||
logic [9:0] global_count; | |||||
logic done; | |||||
S_AXIS # | |||||
(.C_S_AXIS_TDATA_WIDTH(`Dx_WIDTH) | |||||
) DIN_STREAM | |||||
(.S_AXIS_ACLK(core_clk), | |||||
.S_AXIS_ARESETN(reset_n), | |||||
.S_AXIS_TREADY(DIN_TREADY), | |||||
.M_AXIS_TDATA(m_axis_din_tdata), // Output from Stream | |||||
.S_AXIS_TDATA(s_axis_din_tdata), // Input from Stream | |||||
.S_AXIS_TLAST(s_axis_din_tlast), | |||||
.S_AXIS_TVALID(s_axis_din_tvalid), | |||||
.tready_in(done) | |||||
); | |||||
POLAR_ENCODER | |||||
#(.PBCH(`PBCH), // Broadcast Channel enable | |||||
.A(`A), // Message width A if no segmentation needed, A'=A/2 if segmentation is needed. | |||||
.G(`G) // Length of output | |||||
) PBCH | |||||
(.clock_i(core_clk), // input clock signal | |||||
.reset_ni(reset_n), // input reset | |||||
.msg_i(m_axis_din_tdata), // input message bits | |||||
.msg_o(msg_o) // output bits | |||||
); | |||||
always_ff@(posedge core_clk) | |||||
if(!reset_n) | |||||
global_count <= 0; | |||||
else if(global_count <= 'd525) | |||||
global_count <= global_count + 1'b1; | |||||
else | |||||
global_count <= 0; | |||||
assign done = (reset_n == 0)||(global_count =='d524) ? 1'b1 : 1'b0; | |||||
DOUT_M_AXIS # | |||||
( | |||||
// Width of S_AXIS address bus. The slave accepts the read and write addresses of width C_M_AXIS_TDATA_WIDTH. | |||||
.C_M_AXIS_TDATA_WIDTH(`Dx_WIDTH), | |||||
.C_S_AXIS_TDATA_WIDTH(`G), | |||||
.DEPTH(27), | |||||
.C_M_START_COUNT(2)) DOUT_STREAM | |||||
( | |||||
// Global ports | |||||
.M_AXIS_ACLK(core_clk), | |||||
.M_AXIS_ARESETN(reset_n), | |||||
// Master Stream Ports. TVALID indicates that the master is driving a valid transfer, A transfer takes place when both TVALID and TREADY are asserted. | |||||
.M_AXIS_TVALID(DOUT_TVALID), | |||||
// TDATA is the primary payload that is used to provide the data that is passing across the interface from the master. | |||||
.M_AXIS_TDATA(DOUT_TDATA), | |||||
// TLAST indicates the boundary of a packet. | |||||
.M_AXIS_TLAST(DOUT_TLAST), | |||||
// TREADY indicates that the slave can accept a transfer in the current cycle. | |||||
.M_AXIS_TREADY(s_axis_dout_tready), | |||||
// Input from PBCH Encoder Core of Width 864 bits | |||||
.S_AXIS_TDATA(msg_o), | |||||
// Input from PBCH Encoder Core | |||||
.DONE(done) | |||||
); | |||||
endmodule |
@@ -0,0 +1,45 @@ | |||||
`timescale 1ns / 1ps | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
// Company: BITSILICA PRIVATE LIMITED | |||||
// | |||||
// Design Name: Register | |||||
// Module Name: register | |||||
// Project Name: POLAR ENCODER-DECODER | |||||
// Tool Versions: VIVADO 2020.1 | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
// register is written to synchronize a combiational logic w.r.t clock and reset signals | |||||
module register #( | |||||
parameter int WIDTH = 1, // width of the input and output of the register | |||||
parameter logic [1:0] SR = 2'b00, // SET and RESET inputs of the register | |||||
parameter logic [WIDTH-1:0] RST_VAL = {WIDTH{1'b0}} // reset value to be provided at the output when reset signal is active | |||||
) ( | |||||
input logic clk, // clock signal for register | |||||
input logic rstb, // active low, synchronous reset | |||||
input logic [WIDTH-1:0] din, // input to be registered | |||||
output logic [WIDTH-1:0] dout // registered outputs | |||||
); | |||||
generate | |||||
if(SR==2'b00) begin : NON_RESET_FLOP // if SR==00, irrespective of other signals the input needs to be registered | |||||
always_ff @ (posedge clk) begin | |||||
dout <= din; // registering input w.r.t posedge of clock signal | |||||
end | |||||
end : NON_RESET_FLOP | |||||
else begin: RESET_FLOP // if SR!==00, input needs to be registered according to other signals w.r.t posedge of clock signal | |||||
always_ff @ (posedge clk ) begin | |||||
if (~rstb) // if reset is active | |||||
if (SR == 2'b01) | |||||
dout <= {WIDTH{1'b0}}; // if SR==01, reset the output | |||||
else if (SR == 2'b10) | |||||
dout <= {WIDTH{1'b1}}; // if SR==10, set the output | |||||
else | |||||
dout <= RST_VAL; // if SR==11, reset the output according the reset value provided | |||||
else | |||||
dout <= din; // if reset is inactive, register the input | |||||
end | |||||
end: RESET_FLOP | |||||
endgenerate | |||||
endmodule | |||||
@@ -0,0 +1,61 @@ | |||||
`timescale 1ns / 1ps | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
// Company: BITSILICA PRIVATE LIMITED | |||||
// Design Name: ENCODER BIT SELECTION | |||||
// Module Name: encoder_bit_selection_rtl | |||||
// Project Name: POLAR ENCODER-DECODER | |||||
// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) | |||||
// Tool Versions: VIVADO 2020.1 | |||||
// Description: RTL code for bit selection, in order to change the length of a sequence from N to E, | |||||
// also known as rate matching. | |||||
// | |||||
// | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
module encoder_bit_selection_rtl | |||||
#( | |||||
parameter K = 164, | |||||
parameter G = 1728, | |||||
parameter C = 1, | |||||
parameter E = G/C, | |||||
parameter N=512 | |||||
) | |||||
( | |||||
input wire clock_i, // system clock | |||||
input wire reset_ni, // active low synchronous reset | |||||
input wire [N-1:0] msg_i, // input message for bit selection | |||||
output reg [E-1:0] msg_o // output message bit selection | |||||
); | |||||
localparam Y = E/N; | |||||
localparam Z = E%N; | |||||
integer i; | |||||
generate | |||||
always@(posedge clock_i) begin | |||||
if(!reset_ni )begin | |||||
msg_o <= 0; | |||||
end | |||||
else begin | |||||
if(E>=N) | |||||
begin | |||||
for(i = 1;i <= Y;i = i+1) // Repitition // | |||||
msg_o[((i*N)-1) -: N]<=msg_i[N-1:0]; // Assigning same N bits to output reg for E/N times | |||||
if(Z != 0)begin | |||||
msg_o[E-1:N*(Y)] <= msg_i[Z-1:0]; // Assingning remaining E%N bits | |||||
end | |||||
end | |||||
else | |||||
begin | |||||
if((10000*(K/E)) <= (70000/16)) // Puncturing // | |||||
msg_o[E-1:0] <= msg_i[N-1:N-E]; // Assigning last E bits to output register | |||||
else // Shortening // | |||||
msg_o[E-1:0] <= msg_i[E-1:0]; // Assigning first E bits to output register | |||||
end | |||||
end | |||||
end | |||||
endgenerate | |||||
endmodule | |||||
@@ -0,0 +1,55 @@ | |||||
`timescale 1ns / 1ps | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
// Company: BITSILICA PRIVATE LIMITED | |||||
// Design Name: ENCODER CORE | |||||
// Module Name: encoder_core_rtl | |||||
// Project Name: POLAR ENCODER-DECODER | |||||
// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) | |||||
// Tool Versions: VIVADO 2020.1 | |||||
// Description: RTL code for polar encoder core operation. | |||||
// | |||||
// encoder_core_rtl is written to encode an N-bit input message and produce an N-bit | |||||
// encoded codeword as an output | |||||
// | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
module encoder_core_rtl | |||||
#( | |||||
parameter N = 512, // length of input and output messages for encoder_core_rtl | |||||
localparam DEPTH = $clog2(N) // to derive depth of binary tree to carry out the operation of polar encoder core | |||||
) | |||||
( | |||||
input wire clock_i, // system clock | |||||
input wire reset_ni, // active low, synchronous reset | |||||
input wire [N-1:0] msg_i, // input message to be encoded | |||||
output reg [N-1:0] msg_o // output encoded codeword | |||||
); | |||||
reg [N-1:0] msg_1; // internal register to hold the encoded codeword throughout the operation | |||||
integer i,j,k; // looping variables | |||||
// instantiating a register(group of FF's) to hold the output and synchronize the module w.r.t clock and reset signals | |||||
register #( | |||||
.WIDTH(N), // overriding the width of register with the length of output to be registered | |||||
.SR(2'b00), // overriding SR inputs of the register | |||||
.RST_VAL({N{1'b0}}) // overriding the reset value with expected value in the output when reset is applied | |||||
) REG ( | |||||
.clk(clock_i), // connecting clock ports | |||||
.rstb(reset_ni), // connecting reset ports | |||||
.din(msg_1), // connecting input of register with the value that needs to be registered | |||||
.dout(msg_o) // connecting the registered output with the output port of current module | |||||
); | |||||
// combinational always block for performing encoder operation | |||||
always_comb begin | |||||
msg_1 = msg_i; // temporary register is fed with input message | |||||
for (i = 0; i <= DEPTH; i = i+1) begin : depth // to loop through the depth of binary tree | |||||
for (j = 0; j <= (N-(2 ** i)); j = j+(2 ** i)) begin : limit // to find the boundaries of bits in different depths | |||||
for (k = j; k < (j+(2 ** (i-1))); k = k+1) begin : count // to find the number of xor operations required to encode the message | |||||
msg_1[k] = msg_1[k] ^ msg_1[k + (2 ** (i-1))]; // xor between two particular bits to be stored in another bit, based on the index calculated | |||||
end : count | |||||
end : limit | |||||
end : depth | |||||
end | |||||
endmodule |
@@ -0,0 +1,86 @@ | |||||
`timescale 1ns / 1ps | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
// Company: BITSILICA PRIVATE LIMITED | |||||
// Design Name: ENCODER CRC ATTACHMENT | |||||
// Module Name: encoder_crc_attachment_rtl | |||||
// Project Name: POLAR ENCODER-DECODER | |||||
// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) | |||||
// Tool Versions: VIVADO 2020.1 | |||||
// Description: RTL code for calculation and attachment of CRC to a given message, according to selected polynomial. | |||||
// | |||||
//~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~// | |||||
// If the CRC width i.e., P = X, // | |||||
// it means that we are going to use a X degree polynomial of length X+1 bits, // | |||||
// the crc_out is of X bits. // | |||||
// CRC POLYNOMIALS used in Polar IP // | |||||
// CRC6 =0x21 == 010_0001 // | |||||
// CRC11 =0x621 == 0110_0010_0001 // | |||||
// CRC16 =0x1021 == 0_0001_0000_0010_0001 // | |||||
// CRC24C =0xB2B117 == 0_1011_0010_1011_0001_0001_0111 // | |||||
//~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~// | |||||
// | |||||
// encoder_crc_attachment_rtl is written to calculate and attach CRC for a given message input. | |||||
// | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
module encoder_crc_attachment_rtl | |||||
#( | |||||
parameter PUCCH = 0, // Uplink Channel enable | |||||
parameter PBCH = 0, // Broadcast Channel enable | |||||
parameter N = 512, | |||||
parameter A = 140, // Message width A if no segmentation needed, A'=A/2 if segmentation is needed. | |||||
parameter P=24, | |||||
parameter K = A+P // Message width after CRC is appended | |||||
) | |||||
( | |||||
input wire clock_i, // System clock | |||||
input wire reset_ni, // System reset,active low synchronous | |||||
input wire [A-1:0] msg_i, // Input message bits | |||||
output reg [K-1:0] msg_o // total message = message input + CRC bits | |||||
); | |||||
integer i; // looping variable | |||||
wire [P:0] polynomial; // polynomial using which CRC needs to be calculated | |||||
reg [K-1:0] polynomial_1='d0; // polynomial_1 is to store the right shifted polynomial in each step | |||||
reg [K-1:0] msg_1='d0; // msg_1 is to hold the modified message in between the XOR operations | |||||
reg [P-1:0] crc_out='d0; // Calculated CRC output for given msg_i | |||||
reg [K-1:0] msg_2; // msg_2 is to hold the output msg after msg_i is appended with crc_out | |||||
generate | |||||
if (P == 'd6) //CRC-6 | |||||
assign polynomial = 'h21; | |||||
else if (P == 'd11) //CRC-11 | |||||
assign polynomial = 'h621; | |||||
else if (P == 'd24) //CRC-24C | |||||
assign polynomial = 'h1d11a9b; | |||||
else //CRC-16 | |||||
assign polynomial = 'h1021; | |||||
endgenerate | |||||
// Procedural block to calculate CRC for input message bits. | |||||
always@(*) begin | |||||
polynomial_1 = { {(A-1){1'b0}}, polynomial[P:0] }; // initialization of polynomial_1 | |||||
msg_1 = { {P{1'b0}}, msg_i[A-1:0] }; // initialization of msg_1 | |||||
for (i = 0; i < A; i = i+1) begin // calculating CRC and storing in temporary internal register(A number of times) | |||||
msg_1 = ( msg_1[i] )? ( msg_1 ^ polynomial_1 ) : ( msg_1 ^ {K{1'b0}} ); // exor with polynomial if message bit is 1, else exor with 0's. | |||||
polynomial_1 = polynomial_1 << 1'b1; // left shifting the polynomial for each message bit | |||||
end | |||||
crc_out = msg_1[K-1 : A]; // assigning the internal register to CRC output | |||||
msg_2 = { crc_out[P-1 : 0], msg_i[A-1 : 0] }; // the final message output | |||||
end | |||||
// instantiating a register(group of FF's) to hold the output and synchronize the module w.r.t clock and reset signals | |||||
register #( | |||||
.WIDTH(K), // overriding the width of register with the length of output to be registered | |||||
.SR(2'b01), // overriding SR inputs of the register | |||||
.RST_VAL({N{1'b0}}) // overriding the reset value with expected value in the output when reset is applied | |||||
) REG ( | |||||
.clk(clock_i), // connecting clock ports | |||||
.rstb(reset_ni), // connecting reset ports | |||||
.din(msg_2), // connecting input of register with the value that needs to be registered | |||||
.dout(msg_o) // connecting the registered output with the output port of current module | |||||
); | |||||
endmodule | |||||
@@ -0,0 +1,77 @@ | |||||
`timescale 1ns / 1ps | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
// Company: BITSILICA PRIVATE LIMITED | |||||
// Design Name: ENCODER CRC INTERLEAVING | |||||
// Module Name: encoder_crc_interleaving_rtl | |||||
// Project Name: POLAR ENCODER-DECODER | |||||
// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) | |||||
// Tool Versions: VIVADO 2020.1 | |||||
// Description: RTL code for interleaving the message attached with CRC, according to a CRC interleaver pattern. | |||||
// | |||||
// | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
module encoder_crc_interleaving_rtl | |||||
#( | |||||
parameter K = 164, | |||||
parameter ITLV = 0, | |||||
parameter KMAX = 164 | |||||
) | |||||
( | |||||
input wire clock_i, // system clock | |||||
input wire reset_ni, // active low, synchronous reset | |||||
input wire [K-1:0] msg_i, // input message to be interleaved | |||||
output reg [K-1:0] msg_o // output crc interleaved message | |||||
); | |||||
integer k = 1'd0; | |||||
integer j = 1'd0; | |||||
integer i = 1'd0; | |||||
integer m = 1'd0; | |||||
reg [K-1:0] msg_1; // internal register to hold the interleaved message throughout the operation | |||||
reg [7:0] pi [K-1:0]; //internal register for interleaving logic | |||||
//interleaving pattern for interleaving the given message | |||||
reg [7:0] pimax [163:0] = '{8'd163,8'd162,8'd161,8'd160,8'd159,8'd158,8'd157,8'd156,8'd155,8'd154,8'd153,8'd152,8'd151,8'd150,8'd149,8'd148,8'd147,8'd41,8'd146, | |||||
8'd40,8'd145,8'd39,8'd144,8'd38,8'd18,8'd13,8'd143,8'd137,8'd86,8'd80,8'd75,8'd48,8'd37,8'd23,8'd17,8'd12,8'd142,8'd136,8'd131,8'd125, | |||||
8'd117,8'd103,8'd100,8'd97,8'd85,8'd79,8'd74,8'd64,8'd47,8'd44,8'd36,8'd33,8'd30,8'd22,8'd16,8'd11,8'd6,8'd141,8'd135,8'd133,8'd130, | |||||
8'd128,8'd124,8'd121,8'd116,8'd114,8'd112,8'd109,8'd107,8'd105,8'd102,8'd99,8'd96,8'd94,8'd92,8'd90,8'd84,8'd78,8'd73,8'd68,8'd63,8'd60, | |||||
8'd57,8'd55,8'd52,8'd46,8'd43,8'd35,8'd32,8'd29,8'd27,8'd21,8'd15,8'd10,8'd8,8'd5,8'd3,8'd1,8'd140,8'd139,8'd138,8'd134,8'd132,8'd129, | |||||
8'd127,8'd126,8'd123,8'd122,8'd120,8'd119,8'd118,8'd115,8'd113,8'd111,8'd110,8'd108,8'd106,8'd104,8'd101,8'd98,8'd95,8'd93,8'd91,8'd89, | |||||
8'd88,8'd87,8'd83,8'd82,8'd81,8'd77,8'd76,8'd72,8'd71,8'd70,8'd69,8'd67,8'd66,8'd65,8'd62,8'd61,8'd59,8'd58,8'd56,8'd54,8'd53,8'd51, | |||||
8'd50,8'd49,8'd45,8'd42,8'd34,8'd31,8'd28,8'd26,8'd25,8'd24,8'd20,8'd19,8'd14,8'd9,8'd7,8'd4,8'd2,8'd0}; | |||||
// instantiating a register(group of FF's) to hold the output and synchronize the module w.r.t clock and reset signals | |||||
register #( | |||||
.WIDTH(K), // overriding the width of register with the length of output to be registered | |||||
.SR(2'b00), // overriding SR inputs of the register | |||||
.RST_VAL({K{1'b0}}) // overriding the reset value with expected value in the output when reset is applied | |||||
) REG ( | |||||
.clk(clock_i), // connecting clock ports | |||||
.rstb(reset_ni), // connecting reset ports | |||||
.din(msg_1), // connecting input of register with the value that needs to be registered | |||||
.dout(msg_o) // connecting the registered output with the output port of current module | |||||
); | |||||
// combinational always block for performing crc interleaving operation | |||||
always_comb begin | |||||
if(ITLV == 0) begin | |||||
for(i = 0 ; i < K ; i = i+1) | |||||
pi[i] = i; | |||||
end | |||||
else begin | |||||
k = 0; begin | |||||
for( m = 0 ; (m < KMAX) ; m = m+1) | |||||
if(pimax[m] >= (KMAX-K)) begin | |||||
pi[k] = (pimax[m]-(KMAX-K)); | |||||
k = k+1'b1; | |||||
end | |||||
end | |||||
begin | |||||
for( j = 'd0 ; j < K ; j = j+1) | |||||
msg_1[j] = msg_i[pi[j]]; | |||||
end | |||||
end | |||||
end | |||||
endmodule |
@@ -0,0 +1,168 @@ | |||||
`timescale 1ns / 1ps | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
// Company: BITSILICA PRIVATE LIMITED | |||||
// Design Name: ENCODER FROZEN BIT INSERTION | |||||
// Module Name: encoder_frozen_bit_insertion_rtl | |||||
// Project Name: POLAR ENCODER-DECODER | |||||
// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) | |||||
// Tool Versions: VIVADO 2020.1 | |||||
// Description: RTL code for inserting frozen bits into information, according to given reliability sequence. | |||||
// | |||||
// encoder_frozen_bit_insertion_rtl is written to insert frozen bits in between information bits, according to reliability sequence | |||||
// | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
module encoder_frozen_bit_insertion_rtl1 | |||||
#( | |||||
parameter N = 512, // length of information+CRC+Frozen bits | |||||
parameter K = 164 // length of information+CRC bits | |||||
) | |||||
( | |||||
input wire clock_i, // system clock | |||||
input wire reset_ni, // active low synchronous reset | |||||
input wire [K-1:0] msg_i, // input information+CRC bits | |||||
output reg [N-1:0] msg_o // information+CRC+frozen bits | |||||
); | |||||
reg [N-1:0] msg_1; // internal register to hold the output of frozen bit insertion | |||||
reg [K-1:0] msg_2; | |||||
int i,j,k='d0,p='d0,x='d0; // looping variables | |||||
int q='d0; | |||||
// storing the frozen locations in rel_seq array (reliability in ascending order) | |||||
reg [9:0]rel_seq_512[511:0] = | |||||
'{10'd511, 10'd510, 10'd509, 10'd507, 10'd503, 10'd495, 10'd508, 10'd479, 10'd506, 10'd505, 10'd447, 10'd501, 10'd494, | |||||
10'd502, 10'd499, 10'd493, 10'd383, 10'd478, 10'd491, 10'd477, 10'd255, 10'd504, 10'd487, 10'd475, 10'd446, 10'd500, | |||||
10'd471, 10'd445, 10'd498, 10'd382, 10'd443, 10'd492, 10'd497, 10'd381, 10'd463, 10'd490, 10'd439, 10'd476, 10'd486, | |||||
10'd489, 10'd431, 10'd379, 10'd254, 10'd474, 10'd473, 10'd485, 10'd415, 10'd483, 10'd470, 10'd444, 10'd375, 10'd253, | |||||
10'd367, 10'd247, 10'd469, 10'd441, 10'd442, 10'd462, 10'd251, 10'd438, 10'd467, 10'd351, 10'd496, 10'd461, 10'd380, | |||||
10'd437, 10'd459, 10'd378, 10'd239, 10'd488, 10'd430, 10'd484, 10'd319, 10'd435, 10'd377, 10'd455, 10'd472, 10'd223, | |||||
10'd414, 10'd427, 10'd482, 10'd373, 10'd252, 10'd429, 10'd468, 10'd366, 10'd413, 10'd481, 10'd371, 10'd250, 10'd466, | |||||
10'd423, 10'd374, 10'd440, 10'd365, 10'd411, 10'd249, 10'd460, 10'd350, 10'd246, 10'd465, 10'd436, 10'd407, 10'd191, | |||||
10'd127, 10'd363, 10'd458, 10'd245, 10'd349, 10'd434, 10'd399, 10'd457, 10'd359, 10'd238, 10'd428, 10'd376, 10'd318, | |||||
10'd454, 10'd243, 10'd347, 10'd433, 10'd237, 10'd453, 10'd426, 10'd222, 10'd317, 10'd372, 10'd343, 10'd412, 10'd235, | |||||
10'd451, 10'd425, 10'd422, 10'd370, 10'd221, 10'd315, 10'd480, 10'd335, 10'd364, 10'd190, 10'd369, 10'd248, 10'd231, | |||||
10'd410, 10'd421, 10'd311, 10'd219, 10'd409, 10'd362, 10'd464, 10'd406, 10'd419, 10'd348, 10'd215, 10'd361, 10'd189, | |||||
10'd244, 10'd303, 10'd405, 10'd358, 10'd456, 10'd346, 10'd398, 10'd242, 10'd126, 10'd236, 10'd187, 10'd357, 10'd432, | |||||
10'd207, 10'd403, 10'd397, 10'd452, 10'd345, 10'd241, 10'd316, 10'd342, 10'd125, 10'd234, 10'd183, 10'd287, 10'd355, | |||||
10'd395, 10'd424, 10'd314, 10'd220, 10'd341, 10'd123, 10'd175, 10'd233, 10'd334, 10'd450, 10'd313, 10'd391, 10'd230, | |||||
10'd368, 10'd218, 10'd339, 10'd119, 10'd333, 10'd310, 10'd420, 10'd159, 10'd229, 10'd408, 10'd217, 10'd449, 10'd188, | |||||
10'd309, 10'd214, 10'd331, 10'd111, 10'd360, 10'd302, 10'd418, 10'd227, 10'd404, 10'd186, 10'd213, 10'd417, 10'd301, | |||||
10'd307, 10'd356, 10'd402, 10'd327, 10'd95, 10'd206, 10'd240, 10'd344, 10'd396, 10'd185, 10'd401, 10'd211, 10'd354, | |||||
10'd299, 10'd286, 10'd182, 10'd205, 10'd124, 10'd232, 10'd285, 10'd295, 10'd181, 10'd394, 10'd340, 10'd63, 10'd203, | |||||
10'd353, 10'd448, 10'd122, 10'd283, 10'd393, 10'd174, 10'd390, 10'd312, 10'd338, 10'd228, 10'd179, 10'd199, 10'd121, | |||||
10'd173, 10'd389, 10'd332, 10'd118, 10'd337, 10'd158, 10'd279, 10'd271, 10'd416, 10'd216, 10'd308, 10'd387, 10'd226, | |||||
10'd330, 10'd171, 10'd212, 10'd117, 10'd110, 10'd329, 10'd157, 10'd306, 10'd326, 10'd225, 10'd167, 10'd115, 10'd184, | |||||
10'd109, 10'd300, 10'd305, 10'd210, 10'd155, 10'd325, 10'd352, 10'd400, 10'd298, 10'd204, 10'd94, 10'd284, 10'd209, | |||||
10'd151, 10'd180, 10'd107, 10'd297, 10'd392, 10'd323, 10'd202, 10'd93, 10'd294, 10'd178, 10'd103, 10'd143, 10'd282, | |||||
10'd62, 10'd336, 10'd201, 10'd120, 10'd172, 10'd198, 10'd91, 10'd388, 10'd293, 10'd177, 10'd278, 10'd281, 10'd61, | |||||
10'd170, 10'd116, 10'd197, 10'd87, 10'd156, 10'd277, 10'd114, 10'd169, 10'd59, 10'd291, 10'd275, 10'd270, 10'd195, | |||||
10'd166, 10'd224, 10'd108, 10'd269, 10'd79, 10'd154, 10'd113, 10'd328, 10'd55, 10'd106, 10'd165, 10'd153, 10'd150, | |||||
10'd386, 10'd208, 10'd324, 10'd385, 10'd267, 10'd47, 10'd92, 10'd163, 10'd296, 10'd304, 10'd105, 10'd102, 10'd149, | |||||
10'd263, 10'd322, 10'd292, 10'd90, 10'd200, 10'd31, 10'd321, 10'd142, 10'd176, 10'd147, 10'd101, 10'd141, 10'd196, | |||||
10'd290, 10'd89, 10'd280, 10'd60, 10'd86, 10'd99, 10'd139, 10'd168, 10'd58, 10'd276, 10'd85, 10'd194, 10'd289, | |||||
10'd78, 10'd135, 10'd112, 10'd57, 10'd83, 10'd54, 10'd274, 10'd268, 10'd164, 10'd77, 10'd152, 10'd193, 10'd53, | |||||
10'd162, 10'd104, 10'd273, 10'd266, 10'd75, 10'd46, 10'd148, 10'd51, 10'd100, 10'd45, 10'd161, 10'd265, 10'd262, | |||||
10'd71, 10'd146, 10'd30, 10'd140, 10'd88, 10'd98, 10'd43, 10'd29, 10'd261, 10'd145, 10'd138, 10'd84, 10'd259, 10'd39, | |||||
10'd97, 10'd27, 10'd56, 10'd82, 10'd137, 10'd76, 10'd384, 10'd134, 10'd23, 10'd52, 10'd133, 10'd320, 10'd15, 10'd73, | |||||
10'd50, 10'd81, 10'd131, 10'd44, 10'd70, 10'd192, 10'd288, 10'd160, 10'd272, 10'd74, 10'd49, 10'd42, 10'd69, 10'd28, | |||||
10'd144, 10'd41, 10'd67, 10'd96, 10'd38, 10'd264, 10'd260, 10'd136, 10'd22, 10'd25, 10'd37, 10'd80, 10'd26, 10'd258, | |||||
10'd35, 10'd132, 10'd21, 10'd257, 10'd72, 10'd14, 10'd48, 10'd13, 10'd19, 10'd130, 10'd68, 10'd40, 10'd11, 10'd66, | |||||
10'd129, 10'd7, 10'd36, 10'd24, 10'd34, 10'd256, 10'd20, 10'd65, 10'd33, 10'd12, 10'd128, 10'd18, 10'd10, 10'd17, | |||||
10'd6, 10'd9, 10'd64, 10'd5, 10'd3, 10'd32, 10'd16, 10'd8, 10'd4, 10'd2, 10'd1, 10'd0} ; | |||||
reg [9:0]rel_seq_256[255:0] = | |||||
'{10'd255, 10'd254, 10'd253, 10'd247, 10'd251, 10'd239, 10'd223, 10'd252, 10'd250, 10'd249, 10'd246, 10'd191, 10'd127, | |||||
10'd245, 10'd238, 10'd243, 10'd237, 10'd222, 10'd235, 10'd221, 10'd190, 10'd248, 10'd231, 10'd219, 10'd215, 10'd189, | |||||
10'd244, 10'd242, 10'd126, 10'd236, 10'd187, 10'd207, 10'd241, 10'd125, 10'd234, 10'd183, 10'd220, 10'd123, 10'd175, | |||||
10'd233, 10'd230, 10'd218, 10'd119, 10'd159, 10'd229, 10'd217, 10'd188, 10'd214, 10'd111, 10'd227, 10'd186, 10'd213, | |||||
10'd95, 10'd206, 10'd240, 10'd185, 10'd211, 10'd182, 10'd205, 10'd124, 10'd232, 10'd181, 10'd63, 10'd203, 10'd122, | |||||
10'd174, 10'd228, 10'd179, 10'd199, 10'd121, 10'd173, 10'd118, 10'd158, 10'd216, 10'd226, 10'd171, 10'd212, 10'd117, | |||||
10'd110, 10'd157, 10'd225, 10'd167, 10'd115, 10'd184, 10'd109, 10'd210, 10'd155, 10'd204, 10'd94, 10'd209, 10'd151, | |||||
10'd180, 10'd107, 10'd202, 10'd93, 10'd178, 10'd103, 10'd143, 10'd62, 10'd201, 10'd120, 10'd172, 10'd198, 10'd91, | |||||
10'd177, 10'd61, 10'd170, 10'd116, 10'd197, 10'd87, 10'd156, 10'd114, 10'd169, 10'd59, 10'd195, 10'd166, 10'd224, | |||||
10'd108, 10'd79, 10'd154, 10'd113, 10'd55, 10'd106, 10'd165, 10'd153, 10'd150, 10'd208, 10'd47, 10'd92, 10'd163, | |||||
10'd105, 10'd102, 10'd149, 10'd90, 10'd200, 10'd31, 10'd142, 10'd176, 10'd147, 10'd101, 10'd141, 10'd196, 10'd89, | |||||
10'd60, 10'd86, 10'd99, 10'd139, 10'd168, 10'd58, 10'd85, 10'd194, 10'd78, 10'd135, 10'd112, 10'd57, 10'd83, 10'd54, | |||||
10'd164, 10'd77, 10'd152, 10'd193, 10'd53, 10'd162, 10'd104, 10'd75, 10'd46, 10'd148, 10'd51, 10'd100, 10'd45, 10'd161, | |||||
10'd71, 10'd146, 10'd30, 10'd140, 10'd88, 10'd98, 10'd43, 10'd29, 10'd145, 10'd138, 10'd84, 10'd39, 10'd97, 10'd27, | |||||
10'd56, 10'd82, 10'd137, 10'd76, 10'd134, 10'd23, 10'd52, 10'd133, 10'd15, 10'd73, 10'd50, 10'd81, 10'd131, 10'd44, | |||||
10'd70, 10'd192, 10'd160, 10'd74, 10'd49, 10'd42, 10'd69, 10'd28, 10'd144, 10'd41, 10'd67, 10'd96, 10'd38, 10'd136, | |||||
10'd22, 10'd25, 10'd37, 10'd80, 10'd26, 10'd35, 10'd132, 10'd21, 10'd72, 10'd14, 10'd48, 10'd13, 10'd19, 10'd130, | |||||
10'd68, 10'd40, 10'd11, 10'd66, 10'd129, 10'd7, 10'd36, 10'd24, 10'd34, 10'd20, 10'd65, 10'd33, 10'd12, 10'd128, | |||||
10'd18, 10'd10, 10'd17, 10'd6, 10'd9, 10'd64, 10'd5, 10'd3, 10'd32, 10'd16, 10'd8, 10'd4, 10'd2, 10'd1, 10'd0}; | |||||
reg [9:0]rel_seq_128[127:0] = | |||||
'{10'd127, 10'd126, 10'd125, 10'd123, 10'd119, 10'd111, 10'd95, 10'd124, 10'd63, 10'd122, 10'd121, 10'd118, 10'd117, 10'd110, | |||||
10'd115, 10'd109, 10'd94, 10'd107, 10'd93, 10'd103, 10'd62, 10'd120, 10'd91, 10'd61, 10'd116, 10'd87, 10'd114, 10'd59, 10'd108, | |||||
10'd79, 10'd113, 10'd55, 10'd106, 10'd47, 10'd92, 10'd105, 10'd102, 10'd90, 10'd31, 10'd101, 10'd89, 10'd60, 10'd86, 10'd99, | |||||
10'd58, 10'd85, 10'd78, 10'd112, 10'd57, 10'd83, 10'd54, 10'd77, 10'd53, 10'd104, 10'd75, 10'd46, 10'd51, 10'd100, 10'd45, | |||||
10'd71, 10'd30, 10'd88, 10'd98, 10'd43, 10'd29, 10'd84, 10'd39, 10'd97, 10'd27, 10'd56, 10'd82, 10'd76, 10'd23, 10'd52, 10'd15, | |||||
10'd73, 10'd50, 10'd81, 10'd44, 10'd70, 10'd74, 10'd49, 10'd42, 10'd69, 10'd28, 10'd41, 10'd67, 10'd96, 10'd38, 10'd22, 10'd25, | |||||
10'd37, 10'd80, 10'd26, 10'd35, 10'd21, 10'd72, 10'd14, 10'd48, 10'd13, 10'd19, 10'd68, 10'd40, 10'd11, 10'd66, 10'd7, 10'd36, | |||||
10'd24, 10'd34, 10'd20, 10'd65, 10'd33, 10'd12, 10'd18, 10'd10, 10'd17, 10'd6, 10'd9, 10'd64, 10'd5, 10'd3, 10'd32, 10'd16, | |||||
10'd8, 10'd4, 10'd2, 10'd1, 10'd0}; | |||||
reg [9:0]rel_seq_64[63:0] = | |||||
'{10'd63, 10'd62, 10'd61, 10'd59, 10'd55, 10'd47, 10'd31, 10'd60, 10'd58, 10'd57, 10'd54, 10'd53, 10'd46, 10'd51, 10'd45, 10'd30, | |||||
10'd43, 10'd29, 10'd39, 10'd27, 10'd56, 10'd23, 10'd52, 10'd15, 10'd50, 10'd44, 10'd49, 10'd42, 10'd28, 10'd41, 10'd38, 10'd22, | |||||
10'd25, 10'd37, 10'd26, 10'd35, 10'd21, 10'd14, 10'd48, 10'd13, 10'd19, 10'd40, 10'd11, 10'd7, 10'd36, 10'd24, 10'd34, 10'd20, 10'd33, | |||||
10'd12, 10'd18, 10'd10, 10'd17, 10'd6, 10'd9, 10'd5, 10'd3, 10'd32, 10'd16, 10'd8, 10'd4, 10'd2, 10'd1, 10'd0}; | |||||
reg [9:0]rel_seq_32[31:0] = | |||||
'{10'd31, 10'd30, 10'd29, 10'd27, 10'd23, 10'd15, 10'd28, 10'd22, 10'd25, 10'd26, 10'd21, 10'd14, 10'd13, 10'd19, 10'd11, 10'd7, 10'd24, | |||||
10'd20, 10'd12, 10'd18, 10'd10, 10'd17, 10'd6, 10'd9, 10'd5, 10'd3, 10'd16, 10'd8, 10'd4, 10'd2, 10'd1, 10'd0}; | |||||
always@(posedge clock_i) | |||||
begin : insert_frz_zeroes | |||||
if(q == 0) | |||||
msg_2 <= msg_i; | |||||
if(q >= (N-K) ) begin : insert_msg_crc | |||||
case(N) | |||||
32 : msg_1[rel_seq_32[q]] <= msg_2[x]; // filling remaining most reliable K positions with information+CRC bits | |||||
64 : msg_1[rel_seq_64[q]] <= msg_2[x]; | |||||
128 : msg_1[rel_seq_128[q]] <= msg_2[x]; | |||||
256 : msg_1[rel_seq_256[q]] <= msg_2[x]; | |||||
512 : msg_1[rel_seq_512[q]] <= msg_2[x]; | |||||
default:msg_1 <= 'b0; | |||||
endcase | |||||
if(x < K) | |||||
x ++; | |||||
else | |||||
x <= 0; | |||||
end : insert_msg_crc // N - K bits need to be frozen | |||||
else begin | |||||
case(N) | |||||
32 : msg_1[rel_seq_32[q]] <= 1'b0; // filling the least reliable frozen positions with 0's | |||||
64 : msg_1[rel_seq_64[q]] <= 1'b0; | |||||
128 : msg_1[rel_seq_128[q]] <= 1'b0; | |||||
256 : msg_1[rel_seq_256[q]] <= 1'b0; | |||||
512 : msg_1[rel_seq_512[q]] <= 1'b0; | |||||
default:msg_1 <= 'b0; | |||||
endcase | |||||
end | |||||
if(msg_2 == msg_i && q<N ) | |||||
q <= q+1; | |||||
else | |||||
q <= 0; | |||||
end : insert_frz_zeroes | |||||
always@(posedge clock_i) | |||||
if(!reset_ni) | |||||
msg_o <= 0; | |||||
else if(q==N) | |||||
msg_o <= msg_1; | |||||
else | |||||
msg_o <= msg_o; | |||||
endmodule |
@@ -0,0 +1,78 @@ | |||||
`timescale 1ns / 1ps | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
// Company: BITSILICA PRIVATE LIMITED | |||||
// Design Name: ENCODER SUB-BLOCK INTERLEAVING | |||||
// Module Name: encoder_sub_block_interleaving_rtl | |||||
// Project Name: POLAR ENCODER-DECODER | |||||
// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) | |||||
// Tool Versions: VIVADO 2020.1 | |||||
// Description: RTL code for sub block interleaving, in order to interleave the sub blocks of encoded codeword. | |||||
// | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
module encoder_sub_block_interleaving_rtl#( | |||||
parameter N=512 // input and output sequence length | |||||
// parameter to break down the input message into 32- sub blocks of euqal length, S=N/32 | |||||
) ( | |||||
input wire clock_i, | |||||
input wire reset_ni, | |||||
input wire [N-1:0] msg_i, // input message for sub block interleaver | |||||
output reg [N-1:0] msg_o // output message after sub block interleaving | |||||
); | |||||
localparam S=(N >> 3'd5); // parameter to break down the input message into 32- sub blocks of euqal length, S=N/32 | |||||
reg [4:0] sbi_pat [31:0] = '{5'd31, 5'd30, 5'd29, 5'd27, | |||||
5'd28, 5'd26,5'd25, 5'd24, | |||||
5'd23,5'd15,5'd22, 5'd14, | |||||
5'd21, 5'd13, 5'd20, 5'd12, | |||||
5'd19, 5'd11, 5'd18, 5'd10, | |||||
5'd17, 5'd9, 5'd16, 5'd8, | |||||
5'd7, 5'd6, 5'd5, 5'd3, | |||||
5'd4, 5'd2, 5'd1, 5'd0}; | |||||
logic [N-1:0] msg_1; | |||||
logic sub_blocks [31:0] [S-1:0]; //register to store the sub divided blocks | |||||
logic temp [31:0] [S-1:0]; //register to store the interleaved sub blocks | |||||
integer i,j,k,p,q,r; //looping variables | |||||
// instantiating a register(group of FF's) to hold the output and synchronize the module w.r.t clock and reset signals | |||||
register #( | |||||
.WIDTH(N), // overriding the width of register with the length of output to be registered | |||||
.SR(2'b00), // overriding SR inputs of the register | |||||
.RST_VAL({N{1'b0}}) // overriding the reset value with expected value in the output when reset is applied | |||||
) REG ( | |||||
.clk(clock_i), // connecting clock ports | |||||
.rstb(reset_ni), // connecting reset ports | |||||
.din(msg_1), // connecting input of register with the value that needs to be registered | |||||
.dout(msg_o) // connecting the registered output with the output port of current module | |||||
); | |||||
always_comb begin | |||||
//breaking down the message into 32 bit sub blocks of width N/32 | |||||
begin | |||||
for(j = 0 ; j < 32 ; j=j+1) begin | |||||
for (i = 0 ; i < S ; i = i+1) begin | |||||
sub_blocks[j][i] = msg_i[(j*S)+i]; | |||||
end | |||||
end | |||||
end | |||||
//interleaving the subblocks according to the interleaving pattern | |||||
begin | |||||
for(p = 0 ; p < 32 ; p = p+1) begin | |||||
temp[p] = sub_blocks[sbi_pat[p]]; | |||||
end | |||||
end | |||||
//assigning interleaved bits to the output | |||||
begin | |||||
for(q = 0 ; q < 32 ; q = q+1) begin | |||||
for (r = 0 ; r < S ; r = r+1) begin | |||||
msg_1[(q*S)+r] = temp[q][r]; | |||||
end | |||||
end | |||||
end | |||||
end | |||||
endmodule |
@@ -0,0 +1,127 @@ | |||||
`timescale 1ns / 1ps | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
// Company: BITSILICA PRIVATE LIMITED | |||||
// | |||||
// Design Name: POLAE_ENCODER | |||||
// Module Name: POLAR_ENCODER | |||||
// Project Name: POLAR ENCODER-DECODER | |||||
// Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) | |||||
// Tool Versions: VIVADO 2020.1 | |||||
// Description: RTL code for integration of all sub blocks of polar encoder | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
module POLAR_ENCODER | |||||
#( | |||||
parameter PUCCH=0, // Uplink Channel enable | |||||
parameter PBCH=1, // Broadcast Channel enable | |||||
parameter A=32, // Message width A if no segmentation needed, A'=A/2 if segmentation is needed. | |||||
parameter P=24, | |||||
parameter G=864, // Length of output | |||||
parameter C=1, // Value of C=2 if segmentation need to be done otherwise C=1 | |||||
parameter E=G/C, // Value of E based on G and C | |||||
parameter K=A+P, // Length of information+CRC width | |||||
parameter n_min=5, | |||||
parameter n_max=9, | |||||
parameter n_1= ((E<=((9/8)*(2**(($clog2(E))-1))))&&((K/E)<(9/16)))? ($clog2(E)-1) : $clog2(E), | |||||
parameter n_2= $clog2(8*K), | |||||
parameter min_n1_n2= (n_1 >= n_2)? n_2 : n_1, | |||||
parameter min_n1_n2_nmax = (min_n1_n2 >= n_max) ? n_max : min_n1_n2 , | |||||
parameter n=(min_n1_n2_nmax >= n_min)? min_n1_n2_nmax : n_min, | |||||
parameter N=2**n, | |||||
parameter ITLV=1, // Interleave flag for CRC interleaving process | |||||
parameter KMAX=164 // Maximum value of K for CRC interleaving | |||||
) | |||||
( | |||||
input clock_i, // input clock signal | |||||
input reset_ni, // input reset | |||||
input wire [A-1:0] msg_i, // input message bits | |||||
output reg [G-1:0] msg_o // output bits | |||||
); | |||||
wire [K-1:0] msg_1; // output of CRC attachment | |||||
wire [K-1:0] msg_2; // output of CRC scrambling | |||||
wire [K-1:0] msg_x; // output of CRC interleaving | |||||
wire [N-1:0] msg_3; // output of frozen insertion | |||||
wire [N-1:0] msg_4; // output of encoder core | |||||
wire [N-1:0] msg_5; // output of sub block interleaving | |||||
wire [G-1:0] msg_6; // output of bit selection | |||||
if(PBCH) begin | |||||
encoder_crc_attachment_rtl #( | |||||
.PUCCH( PUCCH ), // Uplink Channel enable | |||||
.PBCH( PBCH ), // Broadcast Channel enable | |||||
.A(A), // Message width A if no segmentation needed, A'=A/2 if segmentation is needed. | |||||
.N(N) | |||||
) ENCODER_PBCH_CRC_ATTACHMENT ( | |||||
.clock_i(clock_i), // System clock | |||||
.reset_ni(reset_ni), // System reset,active low synchronous | |||||
.msg_i( msg_i), // Input message bits | |||||
.msg_o( msg_1) // total message = message input + CRC bits | |||||
); | |||||
encoder_crc_interleaving_rtl#( | |||||
.K(K), | |||||
.ITLV(ITLV), | |||||
.KMAX(KMAX) | |||||
) ENCODER_PBCH_CRC_INTERLEAVING ( | |||||
.clock_i(clock_i), // system clock | |||||
.reset_ni(reset_ni), // active low, synchronous reset | |||||
.msg_i( msg_1), // input message to be interleaved | |||||
.msg_o( msg_2) // output crc interleaved message | |||||
); | |||||
encoder_frozen_bit_insertion_rtl1 #( | |||||
.N(N), // length of information+CRC+Frozen bits | |||||
.K(K) // length of information+CRC bits | |||||
) ENCODER_PBCH_FROZEN_INSERTION ( | |||||
.clock_i(clock_i), // system clock | |||||
.reset_ni(reset_ni), // active low synchronous reset | |||||
.msg_i( msg_2), // input information+CRC bits | |||||
.msg_o(msg_3) // information+CRC+frozen bits | |||||
); | |||||
encoder_core_rtl #( | |||||
.N(N) // length of input and output messages for encoder_core_rtl | |||||
) ENCODER_PBCH_CORE ( | |||||
.clock_i(clock_i), // system clock | |||||
.reset_ni(reset_ni), // active low, synchronous reset | |||||
.msg_i( msg_3), // input message to be encoded | |||||
.msg_o(msg_4) // output encoded codeword | |||||
); | |||||
encoder_sub_block_interleaving_rtl #( | |||||
.N( N) // input and output sequence length | |||||
) ENCODER_PBCH_SUB_BLOCK_INTERLEAVING ( | |||||
.clock_i(clock_i), | |||||
.reset_ni(reset_ni), | |||||
.msg_i(msg_4), // input message for sub block interleaver | |||||
.msg_o(msg_5) // output message after sub block interleaving | |||||
); | |||||
encoder_bit_selection_rtl #( | |||||
.K(K), | |||||
.G(G), | |||||
.C(C), | |||||
.E(E), | |||||
.N(N) | |||||
) ENCODER_PBCH_BIT_SELECTION ( | |||||
.clock_i(clock_i), // system clock | |||||
.reset_ni(reset_ni), // active low, synchronous reset | |||||
.msg_i(msg_5), // input message for bit selection | |||||
.msg_o(msg_6) // output message after bit selection | |||||
); | |||||
end | |||||
always@(posedge clock_i) // registering output with respect to clock | |||||
if(!reset_ni) | |||||
msg_o <=0; | |||||
else | |||||
begin | |||||
msg_o <=msg_6; | |||||
end | |||||
endmodule | |||||
@@ -0,0 +1,226 @@ | |||||
`timescale 1ns / 1ps | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
// Company: BITSILICA PVT LTD | |||||
// Design Name: | |||||
// Module Name: FIFO | |||||
// Project Name: | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
/* | |||||
Description | |||||
=========== | |||||
I/Os | |||||
---- | |||||
rst low active, either sync. or async. master reset (see below how to select) | |||||
clr synchronous clear (just like reset but always synchronous), high active | |||||
re read enable, synchronous, high active | |||||
we read enable, synchronous, high active | |||||
din Data Input | |||||
dout Data Output | |||||
full Indicates the FIFO is full (combinatorial output) | |||||
full_r same as above, but registered output (see note below) | |||||
empty Indicates the FIFO is empty | |||||
empty_r same as above, but registered output (see note below) | |||||
full_n Indicates if the FIFO has space for N entries (combinatorial output) | |||||
full_n_r same as above, but registered output (see note below) | |||||
empty_n Indicates the FIFO has at least N entries (combinatorial output) | |||||
empty_n_r same as above, but registered output (see note below) | |||||
level indicates the FIFO level: | |||||
2'b00 0-25% full | |||||
2'b01 25-50% full | |||||
2'b10 50-75% full | |||||
2'b11 %75-100% full | |||||
combinatorial vs. registered status outputs | |||||
------------------------------------------- | |||||
Both the combinatorial and registered status outputs have exactly the same | |||||
synchronous timing. Meaning they are being asserted immediately at the clock | |||||
edge after the last read or write. The combinatorial outputs however, pass | |||||
through several levels of logic before they are output. The registered status | |||||
outputs are direct outputs of a flip-flop. The reason both are provided, is | |||||
that the registered outputs require quite a bit of additional logic inside | |||||
the FIFO. If you can meet timing of your device with the combinatorial | |||||
outputs, use them ! The FIFO will be smaller. If the status signals are | |||||
in the critical pass, use the registered outputs, they have a much smaller | |||||
output delay (actually only Tcq). | |||||
Parameters | |||||
---------- | |||||
The FIFO takes 3 parameters: | |||||
dw Data bus width | |||||
aw Address bus width (Determines the FIFO size by evaluating 2^aw) | |||||
n N is a second status threshold constant for full_n and empty_n | |||||
*/ | |||||
// Selecting Sync. or Async Reset | |||||
// ------------------------------ | |||||
// Uncomment one of the two lines below. The first line for | |||||
// synchronous reset, the second for asynchronous reset | |||||
`define SC_FIFO_ASYNC_RESET //Uncomment for Syncr. reset | |||||
//`define SC_FIFO_ASYNC_RESET or negedge rst // Uncomment for Async. reset | |||||
module fifo#(parameter dw=32,aw=5,n=32)(clk, rst, din, we, dout, re, | |||||
full, empty, full_r, empty_r, | |||||
full_n, empty_n, full_n_r, empty_n_r, | |||||
level,count); | |||||
parameter max_size = 1<<aw; | |||||
input clk, rst; | |||||
input [dw-1:0] din; | |||||
input we; | |||||
output [dw-1:0] dout; | |||||
input re; | |||||
output full, full_r; | |||||
output empty, empty_r; | |||||
output full_n, full_n_r; | |||||
output empty_n, empty_n_r; | |||||
output [1:0] level; | |||||
output [aw:0] count; | |||||
//////////////////////////////////////////////////////////////////// | |||||
// | |||||
// Local Wires | |||||
// | |||||
wire wen; // Write Enable | |||||
wire ren; // Read Enable | |||||
reg [aw-1:0] wp; | |||||
wire [aw-1:0] wp_pl1; | |||||
wire [aw-1:0] wp_pl2; | |||||
reg [aw-1:0] rp; | |||||
wire [aw-1:0] rp_pl1; | |||||
reg full_r; | |||||
reg empty_r; | |||||
reg gb; | |||||
reg gb2; | |||||
reg [aw:0] cnt; | |||||
wire full_n, empty_n; | |||||
reg full_n_r, empty_n_r; | |||||
// Write Only when FIFO isn't full & write enable is there | |||||
assign wen = (!full && we) ? 1'b1 : 1'b0; | |||||
assign ren = (!empty && re) ? 1'b1 : 1'b0; | |||||
assign count = cnt; | |||||
//////////////////////////////////////////////////////////////////// | |||||
// Memory Block | |||||
//////////////////////////////////////////////////////////////////// | |||||
simple_dual_port_ram #(.WIDTH(dw),.DEPTH(n),.AW(aw))u0(.clk(clk),.wea(wen),.enb(ren),.addra(wp),.addrb(rp),.dia(din),.dob(dout)); | |||||
//////////////////////////////////////////////////////////////////// | |||||
// Misc Logic | |||||
always @(posedge clk `SC_FIFO_ASYNC_RESET) | |||||
if(!rst) wp <= #1 {aw{1'b0}}; | |||||
else | |||||
if(we) wp <= #1 wp_pl1; | |||||
assign wp_pl1 = wp + { {aw-1{1'b0}}, 1'b1}; | |||||
assign wp_pl2 = wp + { {aw-2{1'b0}}, 2'b10}; | |||||
always @(posedge clk `SC_FIFO_ASYNC_RESET) | |||||
if(!rst) rp <= #1 {aw{1'b0}}; | |||||
else | |||||
if(re) rp <= #1 rp_pl1; | |||||
assign rp_pl1 = rp + { {aw-1{1'b0}}, 1'b1}; | |||||
//////////////////////////////////////////////////////////////////// | |||||
// Combinatorial Full & Empty Flags | |||||
// | |||||
assign empty = ((wp == rp) & !gb); | |||||
assign full = ((wp == rp) & gb); | |||||
// Guard Bit ... | |||||
always @(posedge clk `SC_FIFO_ASYNC_RESET) | |||||
if(!rst) gb <= #1 1'b0; | |||||
else | |||||
if((wp_pl1 == rp) & we) gb <= #1 1'b1; | |||||
else | |||||
if(re) gb <= #1 1'b0; | |||||
//////////////////////////////////////////////////////////////////// | |||||
// Registered Full & Empty Flags | |||||
// | |||||
// Guard Bit ... | |||||
always @(posedge clk `SC_FIFO_ASYNC_RESET) | |||||
if(!rst) gb2 <= #1 1'b0; | |||||
else | |||||
if((wp_pl2 == rp) & we) gb2 <= #1 1'b1; | |||||
else | |||||
if((wp != rp) & re) gb2 <= #1 1'b0; | |||||
always @(posedge clk `SC_FIFO_ASYNC_RESET) | |||||
if(!rst) full_r <= #1 1'b0; | |||||
else | |||||
if(we & ((wp_pl1 == rp) & gb2) & !re) full_r <= #1 1'b1; | |||||
else | |||||
if(re & ((wp_pl1 != rp) | !gb2) & !we) full_r <= #1 1'b0; | |||||
always @(posedge clk `SC_FIFO_ASYNC_RESET) | |||||
if(!rst) empty_r <= #1 1'b1; | |||||
else | |||||
if(we & ((wp != rp_pl1) | gb2) & !re) empty_r <= #1 1'b0; | |||||
else | |||||
if(re & ((wp == rp_pl1) & !gb2) & !we) empty_r <= #1 1'b1; | |||||
//////////////////////////////////////////////////////////////////// | |||||
// Combinatorial Full_n & Empty_n Flags | |||||
assign empty_n = cnt < n; | |||||
assign full_n = !(cnt < (max_size-n+1)); | |||||
assign level = {2{cnt[aw]}} | cnt[aw-1:aw-2]; | |||||
// N entries status | |||||
always @(posedge clk `SC_FIFO_ASYNC_RESET) | |||||
if(!rst) cnt <= #1 {aw+1{1'b0}}; | |||||
else | |||||
if( re & !we) cnt <= #1 cnt + { {aw{1'b1}}, 1'b1}; | |||||
else | |||||
if(!re & we) cnt <= #1 cnt + { {aw{1'b0}}, 1'b1}; | |||||
//////////////////////////////////////////////////////////////////// | |||||
// Registered Full_n & Empty_n Flags | |||||
always @(posedge clk `SC_FIFO_ASYNC_RESET) | |||||
if(!rst) empty_n_r <= #1 1'b1; | |||||
else | |||||
if(we & (cnt >= (n-1) ) & !re) empty_n_r <= #1 1'b0; | |||||
else | |||||
if(re & (cnt <= n ) & !we) empty_n_r <= #1 1'b1; | |||||
always @(posedge clk `SC_FIFO_ASYNC_RESET) | |||||
if(!rst) full_n_r <= #1 1'b0; | |||||
else | |||||
if(we & (cnt >= (max_size-n) ) & !re) full_n_r <= #1 1'b1; | |||||
else | |||||
if(re & (cnt <= (max_size-n+1)) & !we) full_n_r <= #1 1'b0; | |||||
//////////////////////////////////////////////////////////////////// | |||||
// Sanity Check | |||||
always @(posedge clk) | |||||
if(we & full) | |||||
$display("%m WARNING: Writing while fifo is FULL (%t)",$time); | |||||
always @(posedge clk) | |||||
if(re & empty) | |||||
$display("%m WARNING: Reading while fifo is EMPTY (%t)",$time); | |||||
endmodule | |||||
@@ -0,0 +1,28 @@ | |||||
`timescale 1ns / 1ps | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
// Company: BITSILICA PVT LTD | |||||
// Design Name: | |||||
// Module Name: simple_dual_port_ram | |||||
// Project Name: | |||||
////////////////////////////////////////////////////////////////////////////////// | |||||
module simple_dual_port_ram#(parameter WIDTH = 32, DEPTH = 16,AW = 4)(clk,enb,wea,addra,addrb,dia,dob); | |||||
input clk,wea,enb; | |||||
input [AW -1:0] addra,addrb; | |||||
input [WIDTH -1:0] dia; | |||||
output [WIDTH -1:0] dob; | |||||
reg [WIDTH -1:0] dob; | |||||
reg [WIDTH -1:0] ram [DEPTH -1:0]; | |||||
always @(posedge clk) begin | |||||
if (wea) | |||||
ram[addra] <= dia; | |||||
end | |||||
always @(posedge clk) begin | |||||
if (enb) | |||||
dob <= ram[addrb]; | |||||
end | |||||
endmodule |