aboutsummaryrefslogtreecommitdiff
path: root/src/prga.sv
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/prga.sv228
1 files changed, 228 insertions, 0 deletions
diff --git a/src/prga.sv b/src/prga.sv
new file mode 100644
index 0000000..57f326f
--- /dev/null
+++ b/src/prga.sv
@@ -0,0 +1,228 @@
+module prga (
+ input logic clk,
+ input logic rst_n,
+ input logic en,
+ output logic rdy,
+ input logic [23:0] key,
+
+ output logic [7:0] s_addr,
+ input logic [7:0] s_rddata,
+ output logic [7:0] s_wrdata,
+ output logic s_wren,
+
+ output logic [7:0] ct_addr,
+ input logic [7:0] ct_rddata,
+
+ output logic [7:0] pt_addr,
+ input logic [7:0] pt_rddata,
+ output logic [7:0] pt_wrdata,
+ output logic pt_wren
+);
+
+ logic [7:0] i_d, i_q, j_d, j_q, k_d, k_q, si_d, si_q, sj_d, sj_q;
+ logic [7:0] length_d, length_q;
+
+ enum logic [3:0] {
+ INIT,
+ SET_LENGTH,
+ FETCH_I,
+ FETCH_J,
+ WRITE_I,
+ WRITE_J,
+ FETCH_PAD,
+ WRITE_PT,
+ DONE
+ } state_d, state_q;
+
+ always_comb begin: fsm_output_logic
+ rdy = '0;
+
+ i_d = i_q;
+ j_d = j_q;
+ k_d = k_q;
+ si_d = si_q;
+ sj_d = sj_q;
+ length_d = length_q;
+
+ unique case (state_q)
+ INIT: begin
+ rdy = '1;
+
+ s_addr = '0;
+ s_wrdata = '0;
+ s_wren = '0;
+
+ /* Fetch message length. */
+ ct_addr = '0;
+
+ pt_addr = '0;
+ pt_wrdata = '0;
+ pt_wren = '0;
+ end
+ SET_LENGTH: begin
+ length_d = ct_rddata;
+
+ rdy = '0;
+
+ s_addr = '0;
+ s_wrdata = '0;
+ s_wren = '0;
+
+ ct_addr = '0;
+
+ pt_addr = '0;
+ pt_wrdata = ct_rddata;
+ pt_wren = '1;
+ end
+ FETCH_I: begin
+ i_d = i_q + 1'b1;
+
+ rdy = '0;
+
+ s_addr = i_d;
+ s_wrdata = '0;
+ s_wren = '0;
+
+ ct_addr = '0;
+
+ pt_addr = '0;
+ pt_wrdata = '0;
+ pt_wren = '0;
+ end
+ /* s_rddata now contains s[i]. */
+ FETCH_J: begin
+ /* Calculate j. */
+ j_d = j_q + s_rddata;
+
+ /* Save s[i]. */
+ si_d = s_rddata;
+
+ rdy = '0;
+
+ s_addr = j_d;
+ s_wrdata = '0;
+ s_wren = '0;
+
+ ct_addr = '0;
+
+ pt_addr = '0;
+ pt_wrdata = '0;
+ pt_wren = '0;
+ end
+ /* s_rddata now contains s[j]. */
+ WRITE_I: begin
+ /* Save s[j]. */
+ sj_d = s_rddata;
+
+ rdy = '0;
+
+ s_addr = j_d;
+ s_wrdata = si_q;
+ s_wren = '1;
+
+ ct_addr = '0;
+
+ pt_addr = '0;
+ pt_wrdata = '0;
+ pt_wren = '0;
+ end
+ WRITE_J: begin
+ rdy = '0;
+
+ s_addr = i_d;
+ s_wrdata = sj_q;
+ s_wren = '1;
+
+ ct_addr = '0;
+
+ pt_addr = '0;
+ pt_wrdata = '0;
+ pt_wren = '0;
+ end
+ FETCH_PAD: begin
+ rdy = '0;
+
+ s_addr = si_q + sj_q;
+ s_wrdata = '0;
+ s_wren = '0;
+
+ ct_addr = k_q;
+
+ pt_addr = '0;
+ pt_wrdata = '0;
+ pt_wren = '0;
+ end
+ WRITE_PT: begin
+ k_d = k_q + 1'b1;
+
+ rdy = '0;
+
+ s_addr = '0;
+ s_wrdata = '0;
+ s_wren = '0;
+
+ ct_addr = '0;
+
+ pt_addr = k_q;
+ pt_wrdata = s_rddata ^ ct_rddata;
+ pt_wren = '1;
+ end
+ DONE: begin
+ rdy = '1;
+
+ s_addr = '0;
+ s_wrdata = '0;
+ s_wren = '0;
+
+ ct_addr = '0;
+
+ pt_addr = '0;
+ pt_wrdata = '0;
+ pt_wren = '0;
+ end
+ default: begin end
+ endcase
+ end: fsm_output_logic
+
+ always_comb begin: fsm_next_state_logic
+ unique case (state_q)
+ INIT: begin
+ if (rdy && en) state_d = SET_LENGTH;
+ else state_d = INIT;
+ end
+ SET_LENGTH: state_d = FETCH_I;
+ FETCH_I: state_d = FETCH_J;
+ FETCH_J: state_d = WRITE_I;
+ WRITE_I: state_d = WRITE_J;
+ WRITE_J: state_d = FETCH_PAD;
+ FETCH_PAD: state_d = WRITE_PT;
+ WRITE_PT: begin
+ if (k_q == length_q) state_d = DONE;
+ else state_d = FETCH_I;
+ end
+ DONE: state_d = DONE;
+ default: state_d = INIT;
+ endcase
+ end: fsm_next_state_logic
+
+ always_ff @(posedge clk) begin: fsm_reg
+ if (~rst_n) begin
+ state_q <= INIT;
+ i_q <= '0;
+ j_q <= '0;
+ k_q <= 1'b1;
+ si_q <= '0;
+ sj_q <= '0;
+ length_q <= '0;
+ end else begin
+ state_q <= state_d;
+ i_q <= i_d;
+ j_q <= j_d;
+ k_q <= k_d;
+ si_q <= si_d;
+ sj_q <= sj_d;
+ length_q <= length_d;
+ end
+ end: fsm_reg
+
+endmodule: prga