URL
https://opencores.org/ocsvn/crcahb/crcahb/trunk
Subversion Repositories crcahb
Compare Revisions
- This comparison shows the changes necessary to convert path
/crcahb/trunk
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/testbench/tb_crc_ip.v
0,0 → 1,665
module tb_crc_ip(); |
|
//Memory Map |
localparam CRC_DR = 32'h0; |
localparam CRC_IDR = 32'h4; |
localparam CRC_CR = 32'h8; |
localparam CRC_INIT = 32'h10; |
localparam CRC_POL = 32'h14; |
|
//HTRANS Encoding |
localparam IDLE = 2'b00; |
localparam BUSY = 2'b01; |
localparam NON_SEQ = 2'b10; |
localparam SEQ = 2'b11; |
|
//HSIZE Encoding |
localparam BYTE = 2'b00; |
localparam HALF_WORD = 2'b01; |
localparam WORD = 2'b10; |
|
//CRC_CR Encoding |
localparam RESET = 32'h00000001; |
localparam POLY_SIZE_32 = 32'h00000000; |
localparam POLY_SIZE_16 = 32'h00000001 << 3; |
localparam POLY_SIZE_8 = 32'h00000001 << 4; |
localparam POLY_SIZE_7 = 32'h00000003 << 3; |
localparam REV_IN_NORMAL = 32'h00000000; |
localparam REV_IN_BYTE = 32'h00000001 << 5; |
localparam REV_IN_HALF_WORD = 32'h00000001 << 6; |
localparam REV_IN_WORD = 32'h00000003 << 5; |
localparam REV_OUT_NORMAL = 32'h00000000; |
localparam REV_OUT_REV = 32'h00000001 << 7; |
|
wire [31:0] HRDATA; |
wire HREADYOUT; |
wire HRESP; |
|
reg [31:0] HWDATA; |
reg [31:0] HADDR; |
reg [ 2:0] HSIZE; |
reg [ 1:0] HTRANS; |
reg HWRITE; |
reg HSElx; |
reg HREADY; |
reg HRESETn; |
reg HCLK; |
|
reg [31:0] result, golden; |
reg [31:0] data_init, data_crc; |
reg [31:0] data_rev; |
|
task reset; |
begin |
HWDATA = 0; |
HADDR = 0; |
HSIZE = 0; |
HTRANS = 0; |
HWRITE = 0; |
HSElx = 0; |
HREADY = 1; |
HRESETn = 0; |
HCLK = 0; |
@(posedge HCLK); |
@(posedge HCLK); |
HRESETn = 1; |
@(posedge HCLK); |
end |
endtask |
|
task write_ahb; |
input [31:0] addr; |
input [31:0] data; |
input [ 1:0] size; |
begin |
HADDR <= addr; |
HSElx <= 1; |
HTRANS <= NON_SEQ; |
HSIZE <= size; |
HWRITE <= 1; |
@(negedge HCLK); |
if(HREADYOUT == 0) |
@(posedge HREADYOUT); |
@(posedge HCLK); |
HWDATA <= data; |
HSElx <= 0; |
HTRANS <= IDLE; |
end |
endtask |
|
task read_ahb; |
input [31:0] addr; |
output [31:0] data_rd; |
begin |
HADDR <= addr; |
HSElx <= 1; |
HTRANS <= NON_SEQ; |
HWRITE <= 0; |
@(posedge HCLK); |
@(negedge HCLK); |
if(HREADYOUT == 0) |
@(posedge HREADYOUT); |
@(negedge HCLK); |
//@(posedge HCLK); |
data_rd = HRDATA; |
HSElx = 0; |
HTRANS = IDLE; |
end |
endtask |
|
task compare; |
input [31:0] golden; |
input [31:0] result; |
begin |
if(golden != result) |
begin |
$display("Error Founded...Expected %x, obtained %x", golden, result); |
$stop; |
end |
end |
endtask |
|
crc_ip CRC_IP |
( |
.HRDATA ( HRDATA ), |
.HREADYOUT ( HREADYOUT ), |
.HRESP ( HRESP ), |
.HWDATA ( HWDATA ), |
.HADDR ( HADDR ), |
.HSIZE ( HSIZE ), |
.HTRANS ( HTRANS ), |
.HWRITE ( HWRITE ), |
.HSElx ( HSElx ), |
.HREADY ( HREADY ), |
.HRESETn ( HRESETn ), |
.HCLK ( HCLK ) |
); |
|
initial |
begin |
reset; |
|
write_ahb(CRC_DR, 32'h01020304, WORD); |
write_ahb(3'h1, 32'h05060708, WORD); |
write_ahb(3'h2, 32'h090a0b0c, WORD); |
write_ahb(3'h3, 32'h0d0e0f00, WORD); |
write_ahb(3'h4, 32'h00112233, WORD); |
|
read_ahb(CRC_DR, result); |
|
write_ahb(CRC_IDR, 32'h89abcdef, WORD); |
read_ahb(CRC_IDR, result); |
|
//Test Case 1: Write and Read in IDR |
golden = 32'h89abcdee; |
write_ahb(CRC_IDR, golden, WORD); |
read_ahb(CRC_IDR, result); |
compare(32'hff & golden, result); |
|
golden = 32'hffeeddcc; |
write_ahb(CRC_IDR, golden, BYTE); |
read_ahb(CRC_IDR, result); |
compare(32'hff & golden, result); |
|
//Test Case 2: Write and Read in CR |
golden = 32'hffeeddcc; |
|
//Test Case 2: Write and Read in CR |
golden = 32'hffeeddcc; |
write_ahb(CRC_CR, golden, WORD); |
read_ahb(CRC_CR, result); |
compare(32'hf8 & golden, result); |
|
golden = 32'hffeeddff; |
write_ahb(CRC_CR, golden, WORD); |
read_ahb(CRC_CR, result); |
compare(32'hf8 & golden, result); |
|
//Test Case 3: Write and Read in INIT |
golden = 32'hffeeddcc; |
write_ahb(CRC_INIT, golden, WORD); |
read_ahb(CRC_INIT, result); |
compare(golden, result); |
|
golden = 32'hffeeddff; |
write_ahb(CRC_INIT, golden, WORD); |
read_ahb(CRC_INIT, result); |
compare(golden, result); |
|
//Test Case 4: Write and Read in POL |
golden = 32'h11235813; |
write_ahb(CRC_POL, golden, WORD); |
read_ahb(CRC_POL, result); |
compare(golden, result); |
|
golden = 32'h24161614; |
write_ahb(CRC_POL, golden, WORD); |
read_ahb(CRC_POL, result); |
compare(golden, result); |
|
//Test Case 5: Programmable Initial CRC Value |
//POLY_SIZE_32, Data_32 |
data_init = 32'h14635287; |
data_crc = 32'haabbccdd; |
golden = //crc_32(32'hddccbbaa, data_init); |
crc_32(data_crc[31:24], crc_32(data_crc[23:16], crc_32(data_crc[15:8], crc_32(data_crc[7:0], data_init)))); |
write_ahb(CRC_POL, 32'h04c11db7, WORD); |
write_ahb(CRC_CR, POLY_SIZE_32 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, WORD); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//POLY_SIZE_32, Data_16 |
data_init = 32'h14635287; |
data_crc = 32'h11223344; |
golden = crc_32(data_crc[15:8], crc_32(data_crc[7:0], data_init)); |
write_ahb(CRC_POL, 32'h04c11db7, WORD); |
write_ahb(CRC_CR, POLY_SIZE_32 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, HALF_WORD); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//POLY_SIZE_32, Data_8 |
data_init = 32'h11223344; |
data_crc = 32'h01463528; |
golden = crc_32(data_crc[7:0], data_init); |
write_ahb(CRC_POL, 32'h04c11db7, WORD); |
write_ahb(CRC_CR, POLY_SIZE_32 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, BYTE); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//POLY_SIZE_16, Data_32 |
data_init = 32'hadefbc89; |
data_crc = 32'h01463528; |
golden = crc_16(data_crc[31:24], crc_16(data_crc[23:16], crc_16(data_crc[15:8], crc_16(data_crc[7:0], data_init)))); |
write_ahb(CRC_POL, 32'h00018005, WORD); |
write_ahb(CRC_CR, POLY_SIZE_16 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, WORD); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//POLY_SIZE_16, Data_16 |
data_init = 32'h01463528; |
data_crc = 32'hadefbc89; |
golden = crc_16(data_crc[15:8], crc_16(data_crc[7:0], data_init)); |
write_ahb(CRC_POL, 32'h00018005, WORD); |
write_ahb(CRC_CR, POLY_SIZE_16 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, HALF_WORD); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//POLY_SIZE_16, Data_8 |
data_init = 32'h01463d28; |
data_crc = 32'haedfbc89; |
golden = crc_16(data_crc[7:0], data_init); |
write_ahb(CRC_POL, 32'h00018005, WORD); |
write_ahb(CRC_CR, POLY_SIZE_16 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, BYTE); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//POLY_SIZE_8, Data_32 |
data_init = 32'h11453028; |
data_crc = 32'haed7bc39; |
golden = crc_8(data_crc[31:24], crc_8(data_crc[23:16], crc_8(data_crc[15:8], crc_8(data_crc[7:0], data_init)))); |
write_ahb(CRC_POL, 32'h00000107, WORD); |
write_ahb(CRC_CR, POLY_SIZE_8 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, WORD); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//POLY_SIZE_8, Data_16 |
data_init = 32'h11003028; |
data_crc = 32'haed70039; |
golden = crc_8(data_crc[15:8], crc_8(data_crc[7:0], data_init)); |
write_ahb(CRC_POL, 32'h00000107, WORD); |
write_ahb(CRC_CR, POLY_SIZE_8 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, HALF_WORD); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//POLY_SIZE_8, Data_8 |
data_init = 32'h11000028; |
data_crc = 32'hafdfff39; |
golden = crc_8(data_crc[7:0], data_init); |
write_ahb(CRC_POL, 32'h00000107, WORD); |
write_ahb(CRC_CR, POLY_SIZE_8 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, BYTE); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//POLY_SIZE_7, Data_32 |
data_init = 32'h11453087; |
data_crc = 32'haed7bcfd; |
golden = crc_7(data_crc[31:24], crc_7(data_crc[23:16], crc_7(data_crc[15:8], crc_7(data_crc[7:0], data_init)))); |
write_ahb(CRC_POL, 32'h00000087, WORD); |
write_ahb(CRC_CR, POLY_SIZE_7 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, WORD); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//POLY_SIZE_7, Data_16 |
data_init = 32'h00453057; |
data_crc = 32'haed773fd; |
golden = crc_7(data_crc[15:8], crc_7(data_crc[7:0], data_init)); |
write_ahb(CRC_POL, 32'h00000087, WORD); |
write_ahb(CRC_CR, POLY_SIZE_7 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, HALF_WORD); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//POLY_SIZE_7, Data_8 |
data_init = 32'h0045301d; |
data_crc = 32'haed7732a; |
golden = crc_7(data_crc[7:0], data_init); |
write_ahb(CRC_POL, 32'h00000087, WORD); |
write_ahb(CRC_CR, POLY_SIZE_7 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, BYTE); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//Test Case 6: Test REV_IN configuratin |
//REV_IN_BYTE |
data_init = 32'h14635287; |
data_crc = 32'h1a2b3c4d; |
data_rev = 32'h58d43cb2; |
golden = crc_32(data_rev[31:24], crc_32(data_rev[23:16], crc_32(data_rev[15:8], crc_32(data_rev[7:0], data_init)))); |
write_ahb(CRC_POL, 32'h04c11db7, WORD); |
write_ahb(CRC_CR, POLY_SIZE_32 | RESET | REV_IN_BYTE, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, WORD); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//REV_IN_HALF_WORD |
data_init = 32'h14635287; |
data_crc = 32'h1a2b3c4d; |
data_rev = 32'hd458b23c; |
golden = crc_32(data_rev[31:24], crc_32(data_rev[23:16], crc_32(data_rev[15:8], crc_32(data_rev[7:0], data_init)))); |
write_ahb(CRC_POL, 32'h04c11db7, WORD); |
write_ahb(CRC_CR, POLY_SIZE_32 | RESET | REV_IN_HALF_WORD, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, WORD); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//REV_IN_WORD |
data_init = 32'h14635287; |
data_crc = 32'h1a2b3c4d; |
data_rev = 32'hb23cd458; |
golden = crc_32(data_rev[31:24], crc_32(data_rev[23:16], crc_32(data_rev[15:8], crc_32(data_rev[7:0], data_init)))); |
write_ahb(CRC_POL, 32'h04c11db7, WORD); |
write_ahb(CRC_CR, POLY_SIZE_32 | RESET | REV_IN_WORD, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, WORD); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//Test Case 7: Test REV_OUT configuratin |
//REV_IN_BYTE |
data_init = 32'h14635287; |
data_crc = 32'h1a2b3c4d; |
golden = rev_out(crc_32(data_crc[31:24], crc_32(data_crc[23:16], crc_32(data_crc[15:8], crc_32(data_crc[7:0], data_init))))); |
write_ahb(CRC_POL, 32'h04c11db7, WORD); |
write_ahb(CRC_CR, POLY_SIZE_32 | RESET | REV_OUT_REV, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, WORD); |
read_ahb(CRC_DR, result); |
compare(golden, result); |
$display("%x", golden); |
|
//Test Case 8: Test RESET, Data 32 |
data_init = 32'h14635287; |
write_ahb(CRC_POL, 32'h04c11db7, WORD); |
write_ahb(CRC_CR, POLY_SIZE_32 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
|
//Data 1 |
data_crc = 32'h00112233; |
write_ahb(CRC_DR, data_crc, WORD); |
write_ahb(CRC_CR, RESET, WORD); |
|
//Data 2 |
data_crc = 32'h44556677; |
write_ahb(CRC_DR, data_crc, WORD); |
write_ahb(CRC_CR, RESET, WORD); |
|
//Data 3 |
data_crc = 32'h8899aabb; |
write_ahb(CRC_DR, data_crc, WORD); |
write_ahb(CRC_CR, RESET, WORD); |
|
//Data 4 |
data_crc = 32'hccddeeff; |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, WORD); |
write_ahb(CRC_CR, RESET, WORD); |
|
|
read_ahb(CRC_DR, result); |
golden = crc_32(data_crc[31:24], crc_32(data_crc[23:16], crc_32(data_crc[15:8], crc_32(data_crc[7:0], data_init)))); |
compare(golden, result); |
$display("%x", golden); |
|
//Test Case 9: Test RESET, Data 16 |
data_init = 32'h14635287; |
write_ahb(CRC_POL, 32'h04c11db7, WORD); |
write_ahb(CRC_CR, POLY_SIZE_32 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
|
//Data 1 |
data_crc = 32'h00112233; |
write_ahb(CRC_DR, data_crc, HALF_WORD); |
write_ahb(CRC_CR, RESET, WORD); |
|
//Data 2 |
data_crc = 32'h44556677; |
write_ahb(CRC_DR, data_crc, HALF_WORD); |
write_ahb(CRC_CR, RESET, WORD); |
|
//Data 3 |
data_crc = 32'h8899aabb; |
write_ahb(CRC_DR, data_crc, HALF_WORD); |
write_ahb(CRC_CR, RESET, WORD); |
|
//Data 4 |
data_crc = 32'hccddeeff; |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, HALF_WORD); |
write_ahb(CRC_CR, RESET, WORD); |
|
|
read_ahb(CRC_DR, result); |
golden = crc_32(data_crc[15:8], crc_32(data_crc[7:0], data_init)); |
compare(golden, result); |
$display("%x", golden); |
|
//Test Case 10: Test RESET, Data 8 |
data_init = 32'h14635287; |
write_ahb(CRC_POL, 32'h04c11db7, WORD); |
write_ahb(CRC_CR, POLY_SIZE_32 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
|
//Data 1 |
data_crc = 32'h00112233; |
write_ahb(CRC_DR, data_crc, BYTE); |
write_ahb(CRC_CR, RESET, WORD); |
|
//Data 2 |
data_crc = 32'h44556677; |
write_ahb(CRC_DR, data_crc, BYTE); |
write_ahb(CRC_CR, RESET, WORD); |
|
//Data 3 |
data_crc = 32'h8899aabb; |
write_ahb(CRC_DR, data_crc, BYTE); |
write_ahb(CRC_CR, RESET, WORD); |
|
//Data 4 |
data_crc = 32'hccddeeff; |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, BYTE); |
write_ahb(CRC_CR, RESET, WORD); |
|
|
read_ahb(CRC_DR, result); |
golden = crc_32(data_crc[7:0], data_init); |
compare(golden, result); |
$display("%x", golden); |
|
//Test Case 11: Write-Write-Reset |
data_init = 32'h146352dd; |
write_ahb(CRC_POL, 32'h04c11db7, WORD); |
write_ahb(CRC_CR, POLY_SIZE_32 | RESET, WORD); |
write_ahb(CRC_INIT, data_init, WORD); |
|
//Data 1 |
data_crc = 32'h55112233; |
write_ahb(CRC_DR, data_crc, WORD); |
golden = crc_32(data_crc[31:24], crc_32(data_crc[23:16], crc_32(data_crc[15:8], crc_32(data_crc[7:0], data_init)))); |
|
//Data 2 |
data_crc = 32'h44006677; |
write_ahb(CRC_DR, data_crc, WORD); |
write_ahb(CRC_CR, RESET, WORD); |
|
read_ahb(CRC_DR, result); |
golden = crc_32(data_crc[31:24], crc_32(data_crc[23:16], crc_32(data_crc[15:8], crc_32(data_crc[7:0], golden)))); |
compare(golden, result); |
$display("%x", golden); |
|
//Data 3 |
data_crc = 32'h44005127; |
data_init = 32'h11112222; |
write_ahb(CRC_INIT, data_init, WORD); |
write_ahb(CRC_DR, data_crc, WORD); |
read_ahb(CRC_DR, result); |
golden = crc_32(data_crc[31:24], crc_32(data_crc[23:16], crc_32(data_crc[15:8], crc_32(data_crc[7:0], data_init)))); |
compare(golden, result); |
$display("%x", golden); |
$stop; |
end |
|
always #10 |
HCLK = !HCLK; |
|
function [31:0] rev_out; |
input [31:0] in; |
integer i; |
begin |
for(i = 0; i < 32; i = i + 1) |
rev_out[i] = in[31 - i]; |
end |
endfunction |
|
function [31:0] crc_32; |
|
input [7:0] Data; |
input [31:0] crc; |
reg [7:0] d; |
reg [31:0] c; |
reg [31:0] newcrc; |
begin |
d = Data; |
c = crc; |
|
newcrc[0] = d[6] ^ d[0] ^ c[24] ^ c[30]; |
newcrc[1] = d[7] ^ d[6] ^ d[1] ^ d[0] ^ c[24] ^ c[25] ^ c[30] ^ c[31]; |
newcrc[2] = d[7] ^ d[6] ^ d[2] ^ d[1] ^ d[0] ^ c[24] ^ c[25] ^ c[26] ^ c[30] ^ c[31]; |
newcrc[3] = d[7] ^ d[3] ^ d[2] ^ d[1] ^ c[25] ^ c[26] ^ c[27] ^ c[31]; |
newcrc[4] = d[6] ^ d[4] ^ d[3] ^ d[2] ^ d[0] ^ c[24] ^ c[26] ^ c[27] ^ c[28] ^ c[30]; |
newcrc[5] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[1] ^ d[0] ^ c[24] ^ c[25] ^ c[27] ^ c[28] ^ c[29] ^ c[30] ^ c[31]; |
newcrc[6] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[2] ^ d[1] ^ c[25] ^ c[26] ^ c[28] ^ c[29] ^ c[30] ^ c[31]; |
newcrc[7] = d[7] ^ d[5] ^ d[3] ^ d[2] ^ d[0] ^ c[24] ^ c[26] ^ c[27] ^ c[29] ^ c[31]; |
newcrc[8] = d[4] ^ d[3] ^ d[1] ^ d[0] ^ c[0] ^ c[24] ^ c[25] ^ c[27] ^ c[28]; |
newcrc[9] = d[5] ^ d[4] ^ d[2] ^ d[1] ^ c[1] ^ c[25] ^ c[26] ^ c[28] ^ c[29]; |
newcrc[10] = d[5] ^ d[3] ^ d[2] ^ d[0] ^ c[2] ^ c[24] ^ c[26] ^ c[27] ^ c[29]; |
newcrc[11] = d[4] ^ d[3] ^ d[1] ^ d[0] ^ c[3] ^ c[24] ^ c[25] ^ c[27] ^ c[28]; |
newcrc[12] = d[6] ^ d[5] ^ d[4] ^ d[2] ^ d[1] ^ d[0] ^ c[4] ^ c[24] ^ c[25] ^ c[26] ^ c[28] ^ c[29] ^ c[30]; |
newcrc[13] = d[7] ^ d[6] ^ d[5] ^ d[3] ^ d[2] ^ d[1] ^ c[5] ^ c[25] ^ c[26] ^ c[27] ^ c[29] ^ c[30] ^ c[31]; |
newcrc[14] = d[7] ^ d[6] ^ d[4] ^ d[3] ^ d[2] ^ c[6] ^ c[26] ^ c[27] ^ c[28] ^ c[30] ^ c[31]; |
newcrc[15] = d[7] ^ d[5] ^ d[4] ^ d[3] ^ c[7] ^ c[27] ^ c[28] ^ c[29] ^ c[31]; |
newcrc[16] = d[5] ^ d[4] ^ d[0] ^ c[8] ^ c[24] ^ c[28] ^ c[29]; |
newcrc[17] = d[6] ^ d[5] ^ d[1] ^ c[9] ^ c[25] ^ c[29] ^ c[30]; |
newcrc[18] = d[7] ^ d[6] ^ d[2] ^ c[10] ^ c[26] ^ c[30] ^ c[31]; |
newcrc[19] = d[7] ^ d[3] ^ c[11] ^ c[27] ^ c[31]; |
newcrc[20] = d[4] ^ c[12] ^ c[28]; |
newcrc[21] = d[5] ^ c[13] ^ c[29]; |
newcrc[22] = d[0] ^ c[14] ^ c[24]; |
newcrc[23] = d[6] ^ d[1] ^ d[0] ^ c[15] ^ c[24] ^ c[25] ^ c[30]; |
newcrc[24] = d[7] ^ d[2] ^ d[1] ^ c[16] ^ c[25] ^ c[26] ^ c[31]; |
newcrc[25] = d[3] ^ d[2] ^ c[17] ^ c[26] ^ c[27]; |
newcrc[26] = d[6] ^ d[4] ^ d[3] ^ d[0] ^ c[18] ^ c[24] ^ c[27] ^ c[28] ^ c[30]; |
newcrc[27] = d[7] ^ d[5] ^ d[4] ^ d[1] ^ c[19] ^ c[25] ^ c[28] ^ c[29] ^ c[31]; |
newcrc[28] = d[6] ^ d[5] ^ d[2] ^ c[20] ^ c[26] ^ c[29] ^ c[30]; |
newcrc[29] = d[7] ^ d[6] ^ d[3] ^ c[21] ^ c[27] ^ c[30] ^ c[31]; |
newcrc[30] = d[7] ^ d[4] ^ c[22] ^ c[28] ^ c[31]; |
newcrc[31] = d[5] ^ c[23] ^ c[29]; |
crc_32 = newcrc; |
end |
endfunction |
|
function [15:0] crc_16; |
|
input [7:0] Data; |
input [15:0] crc; |
reg [7:0] d; |
reg [15:0] c; |
reg [15:0] newcrc; |
begin |
d = Data; |
c = crc; |
|
newcrc[0] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ d[0] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[15]; |
newcrc[1] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[15]; |
newcrc[2] = d[1] ^ d[0] ^ c[8] ^ c[9]; |
newcrc[3] = d[2] ^ d[1] ^ c[9] ^ c[10]; |
newcrc[4] = d[3] ^ d[2] ^ c[10] ^ c[11]; |
newcrc[5] = d[4] ^ d[3] ^ c[11] ^ c[12]; |
newcrc[6] = d[5] ^ d[4] ^ c[12] ^ c[13]; |
newcrc[7] = d[6] ^ d[5] ^ c[13] ^ c[14]; |
newcrc[8] = d[7] ^ d[6] ^ c[0] ^ c[14] ^ c[15]; |
newcrc[9] = d[7] ^ c[1] ^ c[15]; |
newcrc[10] = c[2]; |
newcrc[11] = c[3]; |
newcrc[12] = c[4]; |
newcrc[13] = c[5]; |
newcrc[14] = c[6]; |
newcrc[15] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ d[0] ^ c[7] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[15]; |
crc_16 = newcrc; |
end |
endfunction |
|
function [7:0] crc_8; |
|
input [7:0] Data; |
input [7:0] crc; |
reg [7:0] d; |
reg [7:0] c; |
reg [7:0] newcrc; |
begin |
d = Data; |
c = crc; |
|
newcrc[0] = d[7] ^ d[6] ^ d[0] ^ c[0] ^ c[6] ^ c[7]; |
newcrc[1] = d[6] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[6]; |
newcrc[2] = d[6] ^ d[2] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[2] ^ c[6]; |
newcrc[3] = d[7] ^ d[3] ^ d[2] ^ d[1] ^ c[1] ^ c[2] ^ c[3] ^ c[7]; |
newcrc[4] = d[4] ^ d[3] ^ d[2] ^ c[2] ^ c[3] ^ c[4]; |
newcrc[5] = d[5] ^ d[4] ^ d[3] ^ c[3] ^ c[4] ^ c[5]; |
newcrc[6] = d[6] ^ d[5] ^ d[4] ^ c[4] ^ c[5] ^ c[6]; |
newcrc[7] = d[7] ^ d[6] ^ d[5] ^ c[5] ^ c[6] ^ c[7]; |
crc_8 = newcrc; |
end |
endfunction |
|
function [6:0] crc_7; |
|
input [7:0] Data; |
input [6:0] crc; |
reg [7:0] d; |
reg [6:0] c; |
reg [6:0] newcrc; |
begin |
d = Data; |
c = crc; |
|
newcrc[0] = d[7] ^ d[6] ^ d[5] ^ d[0] ^ c[4] ^ c[5] ^ c[6]; |
newcrc[1] = d[5] ^ d[1] ^ d[0] ^ c[0] ^ c[4]; |
newcrc[2] = d[7] ^ d[5] ^ d[2] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[4] ^ c[6]; |
newcrc[3] = d[6] ^ d[3] ^ d[2] ^ d[1] ^ c[0] ^ c[1] ^ c[2] ^ c[5]; |
newcrc[4] = d[7] ^ d[4] ^ d[3] ^ d[2] ^ c[1] ^ c[2] ^ c[3] ^ c[6]; |
newcrc[5] = d[5] ^ d[4] ^ d[3] ^ c[2] ^ c[3] ^ c[4]; |
newcrc[6] = d[6] ^ d[5] ^ d[4] ^ c[3] ^ c[4] ^ c[5]; |
crc_7 = newcrc; |
end |
endfunction |
endmodule |
/rtl/crc_datapath.v
0,0 → 1,273
module crc_datapath |
( |
//OUTPUTS |
output [31:0] crc_out, |
output [ 1:0] size_out, |
output [ 7:0] crc_idr_out, |
output [31:0] crc_poly_out, |
output [31:0] crc_init_out, |
//INPUTS |
input [31:0] bus_wr, //Write data Bus |
input [ 1:0] rev_in_type, //select type of reversion of bus |
input rev_out_type, |
input buffer_en, |
input byte_en, |
input crc_init_en, |
input crc_out_en, |
input crc_idr_en, |
input crc_poly_en, |
input buffer_rst, |
input bypass_byte0, |
input bypass_size, |
input [1:0] byte_sel, |
input [1:0] size_in, |
input clear_crc_init_sel, |
input set_crc_init_sel, |
input [1:0] crc_poly_size, |
input clk, |
input rst_n |
); |
|
//Reset definitions |
localparam RESET_BUFFER = 32'hffffffff; |
localparam RESET_BYTE = 32'hffffffff; |
localparam RESET_BF_SIZE = 2'b10; |
localparam RESET_SIZE = 2'b10; |
localparam RESET_CRC_INIT_SEL = 1'b0; |
localparam RESET_CRC_INIT = 32'hffffffff; |
localparam RESET_CRC_OUT = 32'h0; |
localparam RESET_CRC_IDR = 8'h0; |
localparam RESET_CRC_POLY = 32'h04c11db7; |
|
//Parameters definitions |
localparam BYTE_0 = 2'b00; |
localparam BYTE_1 = 2'b01; |
localparam BYTE_2 = 2'b10; |
localparam BYTE_3 = 2'b11; |
|
localparam POLY_SIZE_32 = 2'b00; |
localparam POLY_SIZE_16 = 2'b01; |
localparam POLY_SIZE_8 = 2'b10; |
localparam POLY_SIZE_7 = 2'b11; |
|
//Flops Definition |
reg [31:0] buffer_ff; |
reg [31:0] byte_ff; |
reg [31:0] crc_init_ff; |
reg [31:0] crc_out_ff; |
reg [31:0] crc_poly_ff; |
reg [ 7:0] crc_idr_ff; |
reg [ 1:0] bf_size_ff; |
reg [ 1:0] size_ff; |
reg crc_init_sel_ff; |
|
//internal signals definition |
reg [7:0] crc_data_in; |
reg crc_poly_size_7; |
reg crc_poly_size_8; |
reg crc_poly_size_16; |
reg crc_poly_size_32; |
wire [31:0] bus_reversed; |
wire [31:0] crc_init_mux; |
wire [31:0] crc_unit_out; |
wire [31:0] crc_poly_size_in; |
wire [31:0] crc_out_rev; |
wire [ 7:0] byte0_in; |
wire [ 7:0] byte1_in; |
wire [ 7:0] byte2_in; |
wire [ 7:0] byte3_in; |
wire [ 7:0] byte0_mux_out; |
|
//Instantiatin of bit_reversed module |
//to perform reversion fuctionality according with rev_type bits |
bit_reversal |
#( |
.DATA_SIZE ( 32 ) |
)REV_IN |
( |
.data_out ( bus_reversed ), |
.data_in ( bus_wr ), |
.rev_type ( rev_in_type ) |
); |
|
//Definition of Registers buffer_ff and byte_ff |
always @(posedge clk) |
begin |
if(!rst_n) |
begin |
buffer_ff <= RESET_BUFFER; |
byte_ff <= RESET_BYTE; |
end |
else |
begin |
if(buffer_en) |
buffer_ff <= bus_reversed; |
//else |
// if(buffer_rst) |
// buffer_ff <= RESET_BUFFER; |
|
if(byte_en) |
byte_ff <= buffer_ff; |
end |
end |
|
//Definition of Registers bf_size_ff and size_ff |
always @(posedge clk) |
begin |
if(!rst_n) |
begin |
bf_size_ff <= RESET_BF_SIZE; |
size_ff <= RESET_SIZE; |
end |
else |
begin |
if(buffer_en) |
bf_size_ff <= size_in; |
else |
if(buffer_rst) |
bf_size_ff <= RESET_BF_SIZE; |
|
if(byte_en) |
size_ff <= bf_size_ff; |
end |
end |
|
//Mux to bypass size_ff |
//This informatin is used by FSM to decide the size of the current operatin |
assign size_out = (bypass_size) ? bf_size_ff : size_ff; |
|
assign byte0_in = byte_ff[ 7: 0]; |
assign byte1_in = byte_ff[15: 8]; |
assign byte2_in = byte_ff[23:16]; |
assign byte3_in = byte_ff[31:24]; |
|
//Mux to bypass byte0_ff |
assign byte0_mux_out = (bypass_byte0) ? buffer_ff[7:0] : byte0_in; |
|
//Mux to select input of CRC Unit |
//TODO:AVALIAR A INFLUENCIA DA CODIFICACAO DA FSM NO SINAL BYTE_SEL |
always @(*) |
begin |
crc_data_in = 32'h0; |
case(byte_sel) |
BYTE_0: crc_data_in = byte0_mux_out; |
BYTE_1: crc_data_in = byte1_in; |
BYTE_2: crc_data_in = byte2_in; |
BYTE_3: crc_data_in = byte3_in; |
default:crc_data_in = 32'h0; |
endcase |
end |
|
//Definition of Register crc_init_sel_ff |
//This is a set/clear flop where the clear wins set |
//This flop controls when the CRC operation is chained (crc_init_sel_ff = 1) or not |
//In the chained operatin the current crc calculation depends of the previous crc calculated |
//in the unchained operatin the current crc calculation depends of value of crc_init register |
always @(posedge clk) |
begin |
if(!rst_n) |
crc_init_sel_ff <= RESET_CRC_INIT_SEL; |
else |
begin |
if(clear_crc_init_sel) |
crc_init_sel_ff <= 1'b0; |
else |
if(set_crc_init_sel) |
crc_init_sel_ff <= 1'b1; |
end |
end |
|
//This register contains the init value used in non chained operatin of crc |
assign crc_init_out = crc_init_ff; |
always @(posedge clk) |
begin |
if(!rst_n) |
crc_init_ff <= RESET_CRC_INIT; |
else |
if(crc_init_en) |
crc_init_ff <= bus_wr; |
else |
if(buffer_rst) |
crc_init_ff <= RESET_CRC_INIT; |
end |
|
//This register contains the final value of crc |
always @(posedge clk) |
begin |
if(!rst_n) |
crc_out_ff <= RESET_CRC_OUT; |
else |
if(crc_out_en) |
crc_out_ff <= crc_unit_out; |
end |
|
//this is a general purpouse register |
//see the spec for more details |
assign crc_idr_out = crc_idr_ff; |
always @(posedge clk) |
begin |
if(!rst_n) |
crc_idr_ff <= RESET_CRC_IDR; |
else |
if(crc_idr_en) |
crc_idr_ff <= bus_wr[7:0]; |
end |
|
//This register contains the polynomial coefficients to crc calculation |
assign crc_poly_out = crc_poly_ff; |
always @(posedge clk) |
begin |
if(!rst_n) |
crc_poly_ff <= RESET_CRC_POLY; |
else |
if(crc_poly_en) |
crc_poly_ff <= bus_wr; |
end |
|
//Mux that define the type of operation (chained or not) |
assign crc_init_mux = (crc_init_sel_ff) ? crc_out_ff : crc_init_ff; |
|
//Decoding of crc_poly_sizesignal |
always @(*) |
begin |
crc_poly_size_7 = 1'b0; |
crc_poly_size_8 = 1'b0; |
crc_poly_size_16 = 1'b0; |
crc_poly_size_32 = 1'b0; |
case(crc_poly_size) |
POLY_SIZE_7 : crc_poly_size_7 = 1'b1; |
POLY_SIZE_8 : crc_poly_size_8 = 1'b1; |
POLY_SIZE_16: crc_poly_size_16 = 1'b1; |
POLY_SIZE_32: crc_poly_size_32 = 1'b1; |
endcase |
end |
|
//This signal define the configurability of the CRC Unit |
//In this case, the size of the polynomial can be: 7, 8, 16 or 32 |
assign crc_poly_size_in = {crc_poly_size_32, 15'h0, crc_poly_size_16, 7'h0, crc_poly_size_8, crc_poly_size_7, 6'h0}; |
|
//Instanciation of CRC Unit |
//The module is configured to calculate CRC of 32 bits for 8 bits of data in parallel |
crc_parallel |
#( |
.CRC_SIZE ( 32 ), |
.FRAME_SIZE ( 8 ) |
)CRC_UNIT |
( |
.crc_out ( crc_unit_out ), |
.data_in ( crc_data_in ), |
.crc_init ( crc_init_mux ), |
.crc_poly ( crc_poly_ff ), |
.crc_poly_size ( crc_poly_size_in ) |
); |
|
//crc_out_rev[31:0] = crc_out_ff[0:31] |
generate |
genvar i; |
for(i = 0; i < 32; i = i + 1) |
assign crc_out_rev[i] = crc_out_ff[31 - i]; |
endgenerate |
|
assign crc_out = (rev_out_type) ? crc_out_rev : crc_out_ff; |
|
endmodule |
/rtl/host_interface.v
0,0 → 1,164
module host_interface |
( |
//OUTPUTS |
output [31:0] HRDATA, |
output HREADYOUT, |
output HRESP, |
output [31:0] bus_wr, |
output [ 1:0] crc_poly_size, |
output [ 1:0] bus_size, |
output [ 1:0] rev_in_type, |
output rev_out_type, |
output crc_init_en, |
output crc_idr_en, |
output crc_poly_en, |
output buffer_write_en, |
output reset_chain, |
//INPUTS |
input [31:0] HWDATA, |
input [31:0] HADDR, |
input [ 2:0] HSIZE, |
input [ 1:0] HTRANS, |
input HWRITE, |
input HSElx, |
input HREADY, |
input HRESETn, |
input HCLK, |
input [31:0] crc_poly_out, |
input [31:0] crc_out, |
input [31:0] crc_init_out, |
input [ 7:0] crc_idr_out, |
input buffer_full, |
input reset_pending, |
input read_wait |
); |
|
//Reset Values |
localparam RESET_CRC_CR = 6'h00; |
|
//CRC Register Map |
localparam CRC_DR = 3'h0; |
localparam CRC_IDR = 3'h1; |
localparam CRC_CR = 3'h2; |
localparam CRC_INIT = 3'h4; |
localparam CRC_POL = 3'h5; |
|
//Transfer Type Encoding |
localparam IDLE = 2'b00; |
localparam BUSY = 2'b01; |
localparam NON_SEQ = 2'b10; |
localparam SEQ = 2'b11; |
|
//HRESP Encoding |
localparam OK = 1'b0; |
localparam ERROR = 1'b1; |
|
//Pipeline flops |
reg [2:0] haddr_pp; |
reg [2:0] hsize_pp; |
reg [1:0] htrans_pp; |
reg hwrite_pp; |
reg hselx_pp; |
|
//Flops |
reg [4:0] crc_cr_ff; |
|
//Internal Signals |
wire [31:0] crc_cr_rd; |
wire crc_dr_sel; |
wire crc_init_sel; |
wire crc_idr_sel; |
wire crc_poly_sel; |
wire crc_cr_sel; |
wire ahb_enable; |
wire write_en; |
wire read_en; |
wire crc_cr_en; |
wire sample_bus; |
wire buffer_read_en; |
|
//Pipeline Registers for Address Phase of AHB Protocol |
always @(posedge HCLK) |
begin |
if(!HRESETn) |
begin |
hselx_pp <= 1'b0; |
end |
else |
if(sample_bus) |
begin |
haddr_pp <= HADDR[4:2]; |
hsize_pp <= HSIZE; |
htrans_pp <= HTRANS; |
hwrite_pp <= HWRITE; |
hselx_pp <= HSElx; |
end |
end |
|
//Enable Signals |
assign ahb_enable = (htrans_pp == NON_SEQ); |
assign write_en = hselx_pp && hwrite_pp && ahb_enable; |
assign read_en = hselx_pp && !hwrite_pp && ahb_enable; |
|
//Registers decoding |
assign crc_dr_sel = (haddr_pp == CRC_DR ); |
assign crc_init_sel = (haddr_pp == CRC_INIT); |
assign crc_idr_sel = (haddr_pp == CRC_IDR ); |
assign crc_poly_sel = (haddr_pp == CRC_POL ); |
assign crc_cr_sel = (haddr_pp == CRC_CR ); |
|
//Write Esnables Signals for Registers |
assign buffer_write_en = crc_dr_sel && write_en; |
assign crc_init_en = crc_init_sel && write_en; |
assign crc_idr_en = crc_idr_sel && write_en; |
assign crc_poly_en = crc_poly_sel && write_en; |
assign crc_cr_en = crc_cr_sel && write_en; |
|
//Indicates reading operation request to crc_dr register |
assign buffer_read_en = crc_dr_sel && read_en; |
|
//Bus Size is the output of HSIZE pipeline register |
assign bus_size = hsize_pp; |
|
//The Write Bus is not pipelined |
assign bus_wr = HWDATA; |
|
//HREADY Signal outputed to Master |
assign HREADYOUT = !((buffer_write_en && buffer_full ) || |
(buffer_read_en && read_wait ) || |
(crc_init_en && reset_pending ) ); |
|
//Signal to control sampling of bus |
assign sample_bus = HREADYOUT && HREADY; |
|
//HRESP Signal outputed to Master |
//This implementation never signalize bus error to master |
assign HRESP = OK; |
|
//CRC_CR Data Read |
assign crc_cr_rd = {24'h0, crc_cr_ff[4:0], 3'h0}; |
|
//Mux to HRDATA |
assign HRDATA = ({32{crc_dr_sel }} & crc_out ) | |
({32{crc_init_sel}} & crc_init_out ) | |
({32{crc_idr_sel }} & {24'h0, crc_idr_out}) | |
({32{crc_poly_sel}} & crc_poly_out ) | |
({32{crc_cr_sel }} & crc_cr_rd ) ; |
|
//Control Register |
always @(posedge HCLK) |
begin |
if(!HRESETn) |
crc_cr_ff <= RESET_CRC_CR; |
else |
if(crc_cr_en) |
crc_cr_ff <= {HWDATA[7], HWDATA[6:5], HWDATA[4:3]}; |
end |
|
//Configuration Signals |
assign reset_chain = (crc_cr_en && HWDATA[0]); |
assign crc_poly_size = crc_cr_ff[1:0]; |
assign rev_in_type = crc_cr_ff[3:2]; |
assign rev_out_type = crc_cr_ff[4]; |
|
endmodule |
/rtl/crc_ip.v
0,0 → 1,94
module crc_ip |
( |
//OUTPUTS |
output [31:0] HRDATA, |
output HREADYOUT, |
output HRESP, |
//INPUTS |
input [31:0] HWDATA, |
input [31:0] HADDR, |
input [ 2:0] HSIZE, |
input [ 1:0] HTRANS, |
input HWRITE, |
input HSElx, |
input HREADY, |
input HRESETn, |
input HCLK |
); |
|
//Internal Signals |
wire [31:0] crc_poly_out; |
wire [31:0] crc_out; |
wire [31:0] crc_init_out; |
wire [ 7:0] crc_idr_out; |
wire buffer_full; |
wire read_wait; |
wire [31:0] bus_wr; |
wire [ 1:0] crc_poly_size; |
wire [ 1:0] bus_size; |
wire [ 1:0] rev_in_type; |
wire rev_out_type; |
wire crc_init_en; |
wire crc_idr_en; |
wire crc_poly_en; |
wire buffer_write_en; |
wire reset_chain; |
|
//Instanciation of Host Interface |
host_interface HOST_INTERFACE |
( |
.HRDATA ( HRDATA ), |
.HREADYOUT ( HREADYOUT ), |
.HRESP ( HRESP ), |
.bus_wr ( bus_wr ), |
.crc_poly_size ( crc_poly_size ), |
.bus_size ( bus_size ), |
.rev_in_type ( rev_in_type ), |
.rev_out_type ( rev_out_type ), |
.crc_init_en ( crc_init_en ), |
.crc_idr_en ( crc_idr_en ), |
.crc_poly_en ( crc_poly_en ), |
.buffer_write_en ( buffer_write_en ), |
.reset_chain ( reset_chain ), |
.reset_pending ( reset_pending ), |
.HWDATA ( HWDATA ), |
.HADDR ( HADDR ), |
.HSIZE ( HSIZE ), |
.HTRANS ( HTRANS ), |
.HWRITE ( HWRITE ), |
.HSElx ( HSElx ), |
.HREADY ( HREADY ), |
.HRESETn ( HRESETn ), |
.HCLK ( HCLK ), |
.crc_poly_out ( crc_poly_out ), |
.crc_out ( crc_out ), |
.crc_init_out ( crc_init_out ), |
.crc_idr_out ( crc_idr_out ), |
.buffer_full ( buffer_full ), |
.read_wait ( read_wait ) |
); |
|
//Instantiation of crc_unit |
crc_unit CRC_UNIT |
( |
.crc_poly_out ( crc_poly_out ), |
.crc_out ( crc_out ), |
.crc_init_out ( crc_init_out ), |
.crc_idr_out ( crc_idr_out ), |
.buffer_full ( buffer_full ), |
.read_wait ( read_wait ), |
.bus_wr ( bus_wr ), |
.crc_poly_size ( crc_poly_size ), |
.bus_size ( bus_size ), |
.rev_in_type ( rev_in_type ), |
.rev_out_type ( rev_out_type ), |
.crc_init_en ( crc_init_en ), |
.crc_idr_en ( crc_idr_en ), |
.crc_poly_en ( crc_poly_en ), |
.buffer_write_en ( buffer_write_en ), |
.reset_chain ( reset_chain ), |
.reset_pending ( reset_pending ), |
.clk ( HCLK ), |
.rst_n ( HRESETn ) |
); |
endmodule |
/rtl/bit_reversal.v
0,0 → 1,44
`define size ((DATA_SIZE/4) * (2 ** (type - 1))) |
|
module bit_reversal |
#( |
parameter DATA_SIZE = 32 |
) |
( |
//OUTPUTS |
output [DATA_SIZE - 1 : 0] data_out, |
//INPUTS |
input [DATA_SIZE - 1 : 0] data_in, |
input [1 : 0] rev_type |
); |
|
|
//Bit reversing types |
localparam NO_REVERSE = 2'b00; |
localparam BYTE = 2'b01; |
localparam HALF_WORD = 2'b10; |
localparam WORD = 2'b11; |
|
localparam TYPES = 4; |
|
wire [DATA_SIZE - 1 : 0] data_reversed[0 : 3]; |
|
|
assign data_reversed[NO_REVERSE] = data_in; //bit order not affected |
|
generate |
genvar i, type; |
for(type = 1 ; type < TYPES; type = type + 1) |
for(i = 0; i < DATA_SIZE; i = i + 1) |
begin |
if(i < `size) |
assign data_reversed[type][i] = data_in[`size*((i/`size) + 1) - 1 - i]; |
else |
assign data_reversed[type][i] = data_in[`size*((i/`size) + 1) - 1 - (i%(`size*(i/`size)))]; |
end |
endgenerate |
|
//Output Mux |
assign data_out = data_reversed[rev_type]; |
|
endmodule |
/rtl/crc_parrallel.v
0,0 → 1,75
module crc_parallel |
#( |
parameter CRC_SIZE = 8, // Define the size of CRC Code |
parameter FRAME_SIZE = 8 // Number of bits in the data block |
)( |
//OUTPUTS |
output [CRC_SIZE - 1 : 0] crc_out, |
//INPUTS |
input [FRAME_SIZE - 1 : 0] data_in, |
input [CRC_SIZE - 1 : 0] crc_init, |
input [CRC_SIZE - 1 : 0] crc_poly, |
input [CRC_SIZE - 1 : 0] crc_poly_size |
); |
localparam ENABLE = {CRC_SIZE{1'b1}}; |
localparam DISABLE = {CRC_SIZE{1'b0}}; |
|
wire [CRC_SIZE - 1 : 0] crc_comb_out[0 : FRAME_SIZE]; |
wire [CRC_SIZE - 1 : 0] poly_sel [1 : CRC_SIZE - 1]; |
wire [CRC_SIZE - 1 : 0] sel_out [0 : CRC_SIZE - 1]; |
wire [CRC_SIZE - 1 : 0] crc_init_sel[0 : CRC_SIZE - 1]; |
wire [CRC_SIZE - 1 : 0] poly_mux; |
wire [CRC_SIZE - 1 : 0] crc_poly_size_reversed; |
wire [CRC_SIZE - 1 : 0] crc_init_justified; |
|
assign poly_mux[0] = crc_poly[0]; |
generate |
genvar k; |
for(k = 1; k < CRC_SIZE; k = k + 1) |
begin |
assign poly_sel[CRC_SIZE - k] = crc_poly_size >> (k - 1); |
assign poly_mux[k] = |(crc_poly & poly_sel[k]); |
end |
endgenerate |
|
generate |
genvar l; |
for(l = 0; l < CRC_SIZE; l = l + 1) |
begin |
assign crc_poly_size_reversed[l] = crc_poly_size[CRC_SIZE - 1 - l]; |
assign sel_out[l] = crc_poly_size_reversed << l; |
assign crc_out[l] = |(sel_out[l] & crc_comb_out[FRAME_SIZE]); |
end |
endgenerate |
|
generate |
genvar m; |
for(m = CRC_SIZE - 1; m >= 0; m = m - 1) |
begin |
assign crc_init_sel[m] = crc_poly_size >> (CRC_SIZE - 1 - m); |
assign crc_init_justified[m] = |(crc_init & crc_init_sel[m]); |
end |
endgenerate |
|
assign crc_comb_out[0] = crc_init_justified; |
|
generate |
genvar i; |
for(i = 0; i < FRAME_SIZE; i = i + 1) |
begin |
crc_comb |
#( |
.CRC_SIZE ( CRC_SIZE ), |
.MASK ( ENABLE ) |
) CRC_COMB |
( |
.crc_out ( crc_comb_out[i + 1] ), |
.data_in ( data_in[FRAME_SIZE - 1 - i] ), |
.crc_in ( crc_comb_out[i] ), |
.crc_poly ( poly_mux ), |
.crc_poly_size ( crc_poly_size[CRC_SIZE - 2:0] ) |
); |
end |
endgenerate |
|
endmodule |
/rtl/crc_control_unit.v
0,0 → 1,270
module crc_control_unit |
( |
//OUTPUTS |
output reg [1:0] byte_sel, |
output bypass_byte0, |
output buffer_full, |
output read_wait, |
output bypass_size, |
output set_crc_init_sel, |
output clear_crc_init_sel, |
output crc_out_en, |
output byte_en, |
output reset_pending, |
//INPUTS |
input [1:0] size_in, |
input write, |
input reset_chain, |
input clk, |
input rst_n |
); |
|
//States definition for state_full |
localparam EMPTY = 2'b00; |
localparam WRITE_1 = 2'b01; |
localparam WRITE_2 = 2'b10; |
localparam BYPASS = 2'b11; |
|
//States definition for state_byte |
localparam IDLE = 3'b100; |
localparam BYTE_0 = 3'b000; |
localparam BYTE_1 = 3'b001; |
localparam BYTE_2 = 3'b010; |
localparam BYTE_3 = 3'b011; |
|
//States definition for state_reset |
localparam NO_RESET = 3'b000; |
localparam RESET = 3'b001; |
localparam WAIT = 3'b010; |
localparam WRITE = 3'b011; |
localparam RESET_2 = 3'b100; |
|
//Coding for size signal |
localparam BYTE = 2'b00; |
localparam HALF_WORD = 2'b01; |
localparam WORD = 2'b10; |
|
//Flops Definition |
reg [1:0] state_full; |
reg [2:0] state_byte; |
reg [2:0] state_reset; |
|
//Internal signals |
reg [1:0] next_state_full; |
reg [2:0] next_state_byte; |
reg [2:0] next_state_reset; |
|
wire last_byte; |
wire has_data; |
|
|
//FSM for management of writes in the input buffers |
//Definition of state register |
always @(posedge clk) |
begin |
if(!rst_n) |
state_full <= EMPTY; |
else |
state_full <= next_state_full; |
end |
|
//This signal indicates that the last byte is in processing |
assign last_byte = (size_in == BYTE && state_byte == BYTE_0) || |
(size_in == HALF_WORD && state_byte == BYTE_1) || |
(size_in == WORD && state_byte == BYTE_3) ; |
|
//Next state Logic |
always @(*) |
begin |
next_state_full = state_full; |
case(state_full) |
EMPTY : next_state_full = (write) ? WRITE_1 : EMPTY; |
WRITE_1: |
begin |
if(last_byte) |
begin |
if(!write) |
next_state_full = EMPTY; |
end |
else |
begin |
if(write) |
next_state_full = WRITE_2; |
end |
end |
WRITE_2: |
begin |
if(last_byte) |
next_state_full = (write) ? BYPASS : WRITE_1; |
end |
BYPASS : |
begin |
if(last_byte && !write) |
next_state_full = WRITE_1; |
end |
endcase |
end |
|
//The flag full indicates that buffer is full and any attempt of writing must wait |
assign buffer_full = (state_full == WRITE_2 && !last_byte) || |
(state_full == BYPASS && !last_byte); |
|
assign read_wait = (state_byte != IDLE); |
|
//This signal controls the selection of the byte0 |
//When bypass_byte0 = 1 the input of byte_ff is taken |
//Otherwise, its output is taken |
assign bypass_byte0 = (state_full != BYPASS); |
|
//This signal indicates that there are data in the second position of the buffer |
assign has_data = (state_full == WRITE_2) || |
(state_full == BYPASS ) ; |
|
|
//FSM for management of readings in the buffer |
//Definition of state register |
always @(posedge clk) |
begin |
if(!rst_n) |
state_byte <= IDLE; |
else |
state_byte <= next_state_byte; |
end |
|
always @(*) |
begin |
next_state_byte = state_byte; |
case(state_byte) |
IDLE: next_state_byte = (write) ? BYTE_0 : IDLE; |
BYTE_0: |
begin |
if(size_in == BYTE) |
begin |
if(!write && !has_data) |
next_state_byte = IDLE; |
end |
else |
begin |
next_state_byte = BYTE_1; |
end |
end |
BYTE_1: |
begin |
if(size_in == HALF_WORD) |
begin |
if(has_data || (write && !buffer_full)) |
next_state_byte = BYTE_0; |
else |
next_state_byte = IDLE; |
end |
else |
begin |
next_state_byte = BYTE_2; |
end |
end |
BYTE_2: |
begin |
next_state_byte = BYTE_3; |
end |
BYTE_3: |
begin |
if(has_data || (write && !buffer_full)) |
next_state_byte = BYTE_0; |
else |
next_state_byte = IDLE; |
end |
endcase |
end |
|
//The signal byte_sel controls the number of byte that will be processed by CRC Unit |
always @(*) |
begin |
byte_sel = 2'b00; |
case(state_byte) |
BYTE_0: byte_sel = BYTE_0; |
BYTE_1: byte_sel = BYTE_1; |
BYTE_2: byte_sel = BYTE_2; |
BYTE_3: byte_sel = BYTE_3; |
endcase |
end |
//This signal controls the selection of the metadata size |
//When bypass_size = 1 the input of size_ff is taken |
//Otherwise, its output is taken |
assign bypass_size = !( (state_full != BYPASS && state_byte != BYTE_0) || |
(state_full == BYPASS) |
); |
|
//This signal enables the write in the crc_out register |
assign crc_out_en = (state_byte != IDLE); |
|
// |
assign byte_en = (state_byte == BYTE_0 && (size_in == HALF_WORD || size_in == WORD) && state_full != BYPASS) || |
(last_byte && has_data); |
|
//FSM for control of reset of chained operation |
//Definition of state register |
always @(posedge clk) |
begin |
if(!rst_n) |
state_reset <= NO_RESET; |
else |
state_reset <= next_state_reset; |
end |
|
always @(*) |
begin |
next_state_reset = state_reset; |
case(state_reset) |
NO_RESET: |
begin |
if((reset_chain && !has_data && state_byte != IDLE && !last_byte) || (reset_chain && has_data && last_byte)) |
next_state_reset = RESET; |
if(reset_chain && has_data && !last_byte) |
next_state_reset = WAIT; |
end |
RESET: |
begin |
if(last_byte) |
next_state_reset = NO_RESET; |
else |
next_state_reset = (write) ? WRITE : RESET; |
end |
WAIT: |
begin |
if(last_byte) |
next_state_reset = (write) ? WRITE : RESET; |
else |
next_state_reset = WAIT; |
end |
WRITE: |
begin |
if(reset_chain) |
next_state_reset = (last_byte) ? RESET : RESET_2; |
else |
next_state_reset = (last_byte) ? NO_RESET : WRITE; |
end |
RESET_2: |
begin |
if(last_byte) |
next_state_reset = (write) ? WRITE : RESET; |
else |
next_state_reset = RESET_2; |
end |
endcase |
end |
|
//This signal set the crc_init_sel flop |
//When seted this flop turn on the chained operation of crc |
assign set_crc_init_sel = (state_byte == BYTE_0); |
|
//This signal clear the crc_init_sel |
//The clear get priority over set |
assign clear_crc_init_sel = (state_reset == NO_RESET && last_byte && reset_chain) || |
(state_byte == IDLE && reset_chain ) || |
(state_reset == RESET && last_byte ) || |
(state_reset == WRITE && last_byte ) || |
(state_reset == RESET_2 && last_byte ) ; |
|
assign reset_pending = (state_reset != NO_RESET); |
|
endmodule |
/rtl/crc_unit.v
0,0 → 1,88
module crc_unit |
( |
//OUTPUTS |
output [31:0] crc_poly_out, |
output [31:0] crc_out, |
output [31:0] crc_init_out, |
output [7:0] crc_idr_out, |
output buffer_full, |
output read_wait, |
output reset_pending, |
//INPUTS |
input [31:0] bus_wr, |
input [ 1:0] crc_poly_size, |
input [ 1:0] bus_size, |
input [ 1:0] rev_in_type, |
input rev_out_type, |
input crc_init_en, |
input crc_idr_en, |
input crc_poly_en, |
input buffer_write_en, |
input reset_chain, |
input clk, |
input rst_n |
); |
|
//Interconection signals |
wire [ 1:0] size_in; |
wire [ 1:0] byte_sel; |
wire clear_crc_init; |
wire set_crc_init; |
wire bypass_byte0; |
wire bypass_size; |
wire crc_out_en; |
wire byte_en; |
wire buffer_en; |
|
//The write in the buffer only occur if there is free space |
assign buffer_en = buffer_write_en && !buffer_full; |
|
//Instance of the Datapath |
crc_datapath DATAPATH |
( |
.crc_out ( crc_out ), |
.size_out ( size_in ), |
.crc_idr_out ( crc_idr_out ), |
.crc_poly_out ( crc_poly_out ), |
.crc_init_out ( crc_init_out ), |
.bus_wr ( bus_wr ), |
.rev_in_type ( rev_in_type ), |
.rev_out_type ( rev_out_type ), |
.buffer_en ( buffer_en ), |
.byte_en ( byte_en ), |
.crc_init_en ( crc_init_en ), |
.crc_out_en ( crc_out_en ), |
.crc_idr_en ( crc_idr_en ), |
.crc_poly_en ( crc_poly_en ), |
.buffer_rst ( clear_crc_init ), |
.bypass_byte0 ( bypass_byte0 ), |
.bypass_size ( bypass_size ), |
.byte_sel ( byte_sel ), |
.size_in ( bus_size ), |
.clear_crc_init_sel ( clear_crc_init ), |
.set_crc_init_sel ( set_crc_init ), |
.crc_poly_size ( crc_poly_size ), |
.clk ( clk ), |
.rst_n ( rst_n ) |
); |
|
//Instance of the Control unit |
crc_control_unit CONTROL_UNIT |
( |
.byte_en ( byte_en ), |
.crc_out_en ( crc_out_en ), |
.byte_sel ( byte_sel ), |
.bypass_byte0 ( bypass_byte0 ), |
.buffer_full ( buffer_full ), |
.read_wait ( read_wait ), |
.bypass_size ( bypass_size ), |
.set_crc_init_sel ( set_crc_init ), |
.clear_crc_init_sel ( clear_crc_init ), |
.size_in ( size_in ), |
.write ( buffer_write_en ), |
.reset_chain ( reset_chain ), |
.reset_pending ( reset_pending ), |
.clk ( clk ), |
.rst_n ( rst_n ) |
); |
endmodule |
/rtl/crc_comb.v
0,0 → 1,38
//This module implements the combinational logic for one iteration of CRC Calculation |
//If conected to shift register and after n clock cycles, this module realize CRC calculation |
//for n bits of data. |
//If instantiated in serial form, this module realize the parallel CRC calculation |
//for n bits of data. |
module crc_comb |
#( |
parameter CRC_SIZE = 8, // Define the size of CRC Code |
parameter MASK = 8'hff // This mask define the level of configurability of the module |
)( |
//OUTPUTS |
output [CRC_SIZE - 1 : 0] crc_out, // CRC code after one round of calculation |
//INPUTS |
input data_in, // One bit of data block |
input [CRC_SIZE - 1 : 0] crc_in, // In cascated mode, this input is the previous calculated CRC code |
input [CRC_SIZE - 1 : 0] crc_poly, // Generator Polynomial |
input [CRC_SIZE - 2 : 0] crc_poly_size |
); |
|
wire [CRC_SIZE - 2 : 0] MASK_REVERSED; |
wire [CRC_SIZE - 1 : 0] feedback; |
wire [CRC_SIZE - 2 : 0] crc_in_masked; |
wire [CRC_SIZE - 2 : 0] crc_poly_size_reversed; |
|
generate |
genvar i; |
for(i = 0; i < CRC_SIZE - 1; i = i + 1) |
begin |
assign crc_poly_size_reversed[i] = crc_poly_size[CRC_SIZE - 2 - i]; |
assign MASK_REVERSED[i] = MASK[CRC_SIZE - 2 - i]; |
end |
endgenerate |
|
assign feedback = crc_poly & {CRC_SIZE{crc_in[CRC_SIZE - 1] ^ data_in}}; |
assign crc_in_masked = crc_in[CRC_SIZE - 2 : 0] & (~(crc_poly_size_reversed[CRC_SIZE - 2 : 0] & MASK_REVERSED)); |
assign crc_out = {crc_in_masked ^ feedback[CRC_SIZE - 1 : 1], feedback[0]}; |
|
endmodule |